Merge "Revert Media 1.0 API changes introduced for making 1.0 updatable"
diff --git a/Android.bp b/Android.bp
index fb6ff0f..4e7aa5f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -108,8 +108,8 @@
"core/java/android/app/prediction/IPredictionCallback.aidl",
"core/java/android/app/prediction/IPredictionManager.aidl",
"core/java/android/app/role/IOnRoleHoldersChangedListener.aidl",
+ "core/java/android/app/role/IRoleController.aidl",
"core/java/android/app/role/IRoleManager.aidl",
- "core/java/android/app/role/IRoleManagerCallback.aidl",
"core/java/android/app/slice/ISliceManager.aidl",
"core/java/android/app/slice/ISliceListener.aidl",
"core/java/android/app/timedetector/ITimeDetectorService.aidl",
@@ -225,6 +225,8 @@
"core/java/android/net/INetworkScoreService.aidl",
"core/java/android/net/INetworkStatsService.aidl",
"core/java/android/net/INetworkStatsSession.aidl",
+ "core/java/android/net/ITestNetworkManager.aidl",
+ "core/java/android/net/ITetheringEventCallback.aidl",
"core/java/android/net/ITetheringStatsProvider.aidl",
"core/java/android/net/nsd/INsdManager.aidl",
"core/java/android/nfc/IAppCallback.aidl",
@@ -274,7 +276,6 @@
"core/java/android/os/storage/IStorageShutdownObserver.aidl",
"core/java/android/os/storage/IObbActionListener.aidl",
"core/java/android/permission/IPermissionController.aidl",
- "core/java/android/rolecontrollerservice/IRoleControllerService.aidl",
":keystore_aidl",
"core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
"core/java/android/service/appprediction/IPredictionService.aidl",
@@ -604,6 +605,7 @@
"telephony/java/com/android/internal/telephony/IOns.aidl",
"telephony/java/com/android/internal/telephony/ITelephony.aidl",
"telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
+ "telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl",
"telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
"telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl",
"telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index c53075c..f1b5459 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3947,7 +3947,7 @@
method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
method @Deprecated public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
method @Deprecated public java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
- method public boolean isActivityStartAllowedOnDisplay(android.content.Context, int, android.content.Intent);
+ method public boolean isActivityStartAllowedOnDisplay(@NonNull android.content.Context, int, @NonNull android.content.Intent);
method public boolean isBackgroundRestricted();
method @Deprecated public boolean isInLockTaskMode();
method public boolean isLowRamDevice();
@@ -4454,7 +4454,7 @@
ctor public AutomaticZenRule(android.os.Parcel);
method public int describeContents();
method public android.net.Uri getConditionId();
- method public android.content.ComponentName getConfigurationActivity();
+ method @Nullable public android.content.ComponentName getConfigurationActivity();
method public long getCreationTime();
method public int getInterruptionFilter();
method public String getName();
@@ -4462,7 +4462,7 @@
method public android.service.notification.ZenPolicy getZenPolicy();
method public boolean isEnabled();
method public void setConditionId(android.net.Uri);
- method public void setConfigurationActivity(android.content.ComponentName);
+ method public void setConfigurationActivity(@Nullable android.content.ComponentName);
method public void setEnabled(boolean);
method public void setInterruptionFilter(int);
method public void setName(String);
@@ -5262,7 +5262,7 @@
method public int describeContents();
method public boolean getAllowSystemGeneratedContextualActions();
method public int getBadgeIconType();
- method public android.app.Notification.BubbleMetadata getBubbleMetadata();
+ method @Nullable public android.app.Notification.BubbleMetadata getBubbleMetadata();
method public String getChannelId();
method public String getGroup();
method public int getGroupAlertBehavior();
@@ -5479,25 +5479,25 @@
public static final class Notification.BubbleMetadata implements android.os.Parcelable {
method public int describeContents();
method public boolean getAutoExpandBubble();
- method public android.app.PendingIntent getDeleteIntent();
+ method @Nullable public android.app.PendingIntent getDeleteIntent();
method public int getDesiredHeight();
- method public android.graphics.drawable.Icon getIcon();
- method public android.app.PendingIntent getIntent();
+ method @NonNull public android.graphics.drawable.Icon getIcon();
+ method @NonNull public android.app.PendingIntent getIntent();
method public boolean getSuppressInitialNotification();
method @Deprecated public CharSequence getTitle();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.BubbleMetadata> CREATOR;
}
- public static class Notification.BubbleMetadata.Builder {
+ public static final class Notification.BubbleMetadata.Builder {
ctor public Notification.BubbleMetadata.Builder();
- method public android.app.Notification.BubbleMetadata build();
- method public android.app.Notification.BubbleMetadata.Builder setAutoExpandBubble(boolean);
- method public android.app.Notification.BubbleMetadata.Builder setDeleteIntent(android.app.PendingIntent);
- method public android.app.Notification.BubbleMetadata.Builder setDesiredHeight(int);
- method public android.app.Notification.BubbleMetadata.Builder setIcon(android.graphics.drawable.Icon);
- method public android.app.Notification.BubbleMetadata.Builder setIntent(android.app.PendingIntent);
- method public android.app.Notification.BubbleMetadata.Builder setSuppressInitialNotification(boolean);
+ method @NonNull public android.app.Notification.BubbleMetadata build();
+ method @NonNull public android.app.Notification.BubbleMetadata.Builder setAutoExpandBubble(boolean);
+ method @NonNull public android.app.Notification.BubbleMetadata.Builder setDeleteIntent(@Nullable android.app.PendingIntent);
+ method @NonNull public android.app.Notification.BubbleMetadata.Builder setDesiredHeight(int);
+ method @NonNull public android.app.Notification.BubbleMetadata.Builder setIcon(@NonNull android.graphics.drawable.Icon);
+ method @NonNull public android.app.Notification.BubbleMetadata.Builder setIntent(@NonNull android.app.PendingIntent);
+ method @NonNull public android.app.Notification.BubbleMetadata.Builder setSuppressInitialNotification(boolean);
method @Deprecated public android.app.Notification.BubbleMetadata.Builder setTitle(CharSequence);
}
@@ -5522,7 +5522,7 @@
method @NonNull public android.app.Notification.Builder setAllowSystemGeneratedContextualActions(boolean);
method @NonNull public android.app.Notification.Builder setAutoCancel(boolean);
method @NonNull public android.app.Notification.Builder setBadgeIconType(int);
- method @NonNull public android.app.Notification.Builder setBubbleMetadata(android.app.Notification.BubbleMetadata);
+ method @NonNull public android.app.Notification.Builder setBubbleMetadata(@Nullable android.app.Notification.BubbleMetadata);
method @NonNull public android.app.Notification.Builder setCategory(String);
method @NonNull public android.app.Notification.Builder setChannelId(String);
method @NonNull public android.app.Notification.Builder setChronometerCountDown(boolean);
@@ -5819,10 +5819,9 @@
method public void notify(String, int, android.app.Notification);
method public void notifyAsPackage(@NonNull String, @NonNull String, int, @NonNull android.app.Notification);
method public boolean removeAutomaticZenRule(String);
- method public void revokeNotificationDelegate();
method public void setAutomaticZenRuleState(@NonNull String, @NonNull android.service.notification.Condition);
method public final void setInterruptionFilter(int);
- method public void setNotificationDelegate(@NonNull String);
+ method public void setNotificationDelegate(@Nullable String);
method public void setNotificationPolicy(@NonNull android.app.NotificationManager.Policy);
method public boolean shouldHideSilentStatusBarIcons();
method public boolean updateAutomaticZenRule(String, android.app.AutomaticZenRule);
@@ -6753,7 +6752,8 @@
method public void setDelegatedScopes(@NonNull android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.lang.String>);
method public void setDeviceOwnerLockScreenInfo(@NonNull android.content.ComponentName, CharSequence);
method public void setEndUserSessionMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
- method public int setGlobalPrivateDns(@NonNull android.content.ComponentName, int, @Nullable String);
+ method public int setGlobalPrivateDnsModeOpportunistic(@NonNull android.content.ComponentName);
+ method @WorkerThread public int setGlobalPrivateDnsModeSpecifiedHost(@NonNull android.content.ComponentName, @NonNull String);
method public void setGlobalSetting(@NonNull android.content.ComponentName, String, String);
method public void setKeepUninstalledPackages(@Nullable android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
method public boolean setKeyPairCertificate(@Nullable android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.security.cert.Certificate>, boolean);
@@ -7732,6 +7732,7 @@
field public static final int ACTIVITY_STOPPED = 23; // 0x17
field public static final int CONFIGURATION_CHANGE = 5; // 0x5
field public static final int DEVICE_SHUTDOWN = 26; // 0x1a
+ field public static final int DEVICE_STARTUP = 27; // 0x1b
field public static final int FOREGROUND_SERVICE_START = 19; // 0x13
field public static final int FOREGROUND_SERVICE_STOP = 20; // 0x14
field public static final int KEYGUARD_HIDDEN = 18; // 0x12
@@ -8644,9 +8645,9 @@
}
public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
- method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method public int getConnectionState(android.bluetooth.BluetoothDevice);
- method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED";
}
@@ -12283,6 +12284,7 @@
method public final void flushLayoutCache();
method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimatorRes @AnimRes int) throws android.content.res.Resources.NotFoundException;
method public final android.content.res.AssetManager getAssets();
+ method @AnyRes public static int getAttributeSetSourceResId(@Nullable android.util.AttributeSet);
method public boolean getBoolean(@BoolRes int) throws android.content.res.Resources.NotFoundException;
method @Deprecated @ColorInt public int getColor(@ColorRes int) throws android.content.res.Resources.NotFoundException;
method @ColorInt public int getColor(@ColorRes int, @Nullable android.content.res.Resources.Theme) throws android.content.res.Resources.NotFoundException;
@@ -12378,7 +12380,7 @@
method public String getPositionDescription();
method @AnyRes public int getResourceId(@StyleableRes int, int);
method public android.content.res.Resources getResources();
- method @StyleRes public int getSourceResourceId(@StyleableRes int, @StyleRes int);
+ method @AnyRes public int getSourceResourceId(@StyleableRes int, @AnyRes int);
method @Nullable public String getString(@StyleableRes int);
method public CharSequence getText(@StyleableRes int);
method public CharSequence[] getTextArray(@StyleableRes int);
@@ -14249,7 +14251,7 @@
method @NonNull public static android.graphics.Insets subtract(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.graphics.Insets> CREATOR;
- field public static final android.graphics.Insets NONE;
+ field @NonNull public static final android.graphics.Insets NONE;
field public final int bottom;
field public final int left;
field public final int right;
@@ -14461,7 +14463,7 @@
method public android.graphics.Paint.Style getStyle();
method public android.graphics.Paint.Align getTextAlign();
method public void getTextBounds(String, int, int, android.graphics.Rect);
- method public void getTextBounds(CharSequence, int, int, android.graphics.Rect);
+ method public void getTextBounds(@NonNull CharSequence, int, int, @NonNull android.graphics.Rect);
method public void getTextBounds(char[], int, int, android.graphics.Rect);
method @NonNull public java.util.Locale getTextLocale();
method @NonNull @Size(min=1) public android.os.LocaleList getTextLocales();
@@ -14480,7 +14482,7 @@
method public android.graphics.Typeface getTypeface();
method @Px public float getUnderlinePosition();
method @Px public float getUnderlineThickness();
- method public float getWordSpacing();
+ method @Px public float getWordSpacing();
method @Deprecated public android.graphics.Xfermode getXfermode();
method public boolean hasGlyph(String);
method public final boolean isAntiAlias();
@@ -14536,7 +14538,7 @@
method public void setTextSkewX(float);
method public android.graphics.Typeface setTypeface(android.graphics.Typeface);
method public void setUnderlineText(boolean);
- method public void setWordSpacing(float);
+ method public void setWordSpacing(@Px float);
method @Deprecated public android.graphics.Xfermode setXfermode(android.graphics.Xfermode);
field public static final int ANTI_ALIAS_FLAG = 1; // 0x1
field public static final int CURSOR_AFTER = 0; // 0x0
@@ -15116,13 +15118,13 @@
method public android.graphics.Typeface.Builder setWeight(@IntRange(from=1, to=1000) int);
}
- public static class Typeface.CustomFallbackBuilder {
+ public static final class Typeface.CustomFallbackBuilder {
ctor public Typeface.CustomFallbackBuilder(@NonNull android.graphics.fonts.FontFamily);
- method public android.graphics.Typeface.CustomFallbackBuilder addCustomFallback(@NonNull android.graphics.fonts.FontFamily);
- method public android.graphics.Typeface build();
+ method @NonNull public android.graphics.Typeface.CustomFallbackBuilder addCustomFallback(@NonNull android.graphics.fonts.FontFamily);
+ method @NonNull public android.graphics.Typeface build();
method @IntRange(from=64) public static int getMaxCustomFallbackCount();
- method public android.graphics.Typeface.CustomFallbackBuilder setStyle(@NonNull android.graphics.fonts.FontStyle);
- method public android.graphics.Typeface.CustomFallbackBuilder setSystemFallback(@NonNull String);
+ method @NonNull public android.graphics.Typeface.CustomFallbackBuilder setStyle(@NonNull android.graphics.fonts.FontStyle);
+ method @NonNull public android.graphics.Typeface.CustomFallbackBuilder setSystemFallback(@NonNull String);
}
public class Xfermode {
@@ -15776,15 +15778,15 @@
method @NonNull public java.nio.ByteBuffer getBuffer();
method @Nullable public java.io.File getFile();
method @NonNull public android.os.LocaleList getLocaleList();
- method public android.graphics.fonts.FontStyle getStyle();
+ method @NonNull public android.graphics.fonts.FontStyle getStyle();
method @IntRange(from=0) public int getTtcIndex();
}
- public static class Font.Builder {
+ public static final class Font.Builder {
ctor public Font.Builder(@NonNull java.nio.ByteBuffer);
ctor public Font.Builder(@NonNull java.io.File);
- ctor public Font.Builder(@NonNull java.io.FileDescriptor);
- ctor public Font.Builder(@NonNull java.io.FileDescriptor, @IntRange(from=0) long, @IntRange(from=0xffffffff) long);
+ ctor public Font.Builder(@NonNull android.os.ParcelFileDescriptor);
+ ctor public Font.Builder(@NonNull android.os.ParcelFileDescriptor, @IntRange(from=0) long, @IntRange(from=0xffffffff) long);
ctor public Font.Builder(@NonNull android.content.res.AssetManager, @NonNull String);
ctor public Font.Builder(@NonNull android.content.res.Resources, int);
method @Nullable public android.graphics.fonts.Font build() throws java.io.IOException;
@@ -15796,11 +15798,11 @@
}
public final class FontFamily {
- method public android.graphics.fonts.Font getFont(@IntRange(from=0) int);
- method public int getSize();
+ method @NonNull public android.graphics.fonts.Font getFont(@IntRange(from=0) int);
+ method @IntRange(from=1) public int getSize();
}
- public static class FontFamily.Builder {
+ public static final class FontFamily.Builder {
ctor public FontFamily.Builder(@NonNull android.graphics.fonts.Font);
method @NonNull public android.graphics.fonts.FontFamily.Builder addFont(@NonNull android.graphics.fonts.Font);
method @NonNull public android.graphics.fonts.FontFamily build();
@@ -15892,7 +15894,7 @@
package android.graphics.text {
public class LineBreaker {
- method public android.graphics.text.LineBreaker.Result computeLineBreaks(@NonNull android.graphics.text.MeasuredText, @NonNull android.graphics.text.LineBreaker.ParagraphConstraints, @IntRange(from=0) int);
+ method @NonNull public android.graphics.text.LineBreaker.Result computeLineBreaks(@NonNull android.graphics.text.MeasuredText, @NonNull android.graphics.text.LineBreaker.ParagraphConstraints, @IntRange(from=0) int);
field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
field public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; // 0x1
field public static final int BREAK_STRATEGY_SIMPLE = 0; // 0x0
@@ -15903,13 +15905,13 @@
field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
}
- public static class LineBreaker.Builder {
+ public static final class LineBreaker.Builder {
ctor public LineBreaker.Builder();
- method public android.graphics.text.LineBreaker build();
- method public android.graphics.text.LineBreaker.Builder setBreakStrategy(int);
- method public android.graphics.text.LineBreaker.Builder setHyphenationFrequency(int);
- method public android.graphics.text.LineBreaker.Builder setIndents(@Nullable int[]);
- method public android.graphics.text.LineBreaker.Builder setJustified(int);
+ method @NonNull public android.graphics.text.LineBreaker build();
+ method @NonNull public android.graphics.text.LineBreaker.Builder setBreakStrategy(int);
+ method @NonNull public android.graphics.text.LineBreaker.Builder setHyphenationFrequency(int);
+ method @NonNull public android.graphics.text.LineBreaker.Builder setIndents(@Nullable int[]);
+ method @NonNull public android.graphics.text.LineBreaker.Builder setJustificationMode(int);
}
public static class LineBreaker.ParagraphConstraints {
@@ -15941,14 +15943,14 @@
method @FloatRange(from=0.0) @Px public float getWidth(@IntRange(from=0) int, @IntRange(from=0) int);
}
- public static class MeasuredText.Builder {
+ public static final class MeasuredText.Builder {
ctor public MeasuredText.Builder(@NonNull char[]);
ctor public MeasuredText.Builder(@NonNull android.graphics.text.MeasuredText);
- method public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @FloatRange(from=0) float);
- method public android.graphics.text.MeasuredText.Builder appendStyleRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, boolean);
- method public android.graphics.text.MeasuredText build();
- method public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean);
- method public android.graphics.text.MeasuredText.Builder setComputeLayout(boolean);
+ method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @Px @FloatRange(from=0) float);
+ method @NonNull public android.graphics.text.MeasuredText.Builder appendStyleRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, boolean);
+ method @NonNull public android.graphics.text.MeasuredText build();
+ method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean);
+ method @NonNull public android.graphics.text.MeasuredText.Builder setComputeLayout(boolean);
}
}
@@ -25725,7 +25727,7 @@
public static class MediaPlayer2.TrackInfo {
method @Nullable public android.media.MediaFormat getFormat();
- method @Nullable public String getLanguage();
+ method @NonNull public String getLanguage();
method public int getTrackType();
field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
@@ -29943,6 +29945,8 @@
method public int getLinkSpeed();
method public String getMacAddress();
method public int getNetworkId();
+ method @Nullable public String getPasspointFqdn();
+ method @Nullable public String getPasspointProviderFriendlyName();
method public int getRssi();
method @IntRange(from=0xffffffff) public int getRxLinkSpeedMbps();
method public String getSSID();
@@ -30090,7 +30094,7 @@
public static final class WifiNetworkSpecifier.Builder {
ctor public WifiNetworkSpecifier.Builder();
- method @NonNull public android.net.NetworkSpecifier build();
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier build();
method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssid(@NonNull android.net.MacAddress);
method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssidPattern(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsEnhancedOpen();
@@ -30188,7 +30192,7 @@
}
public final class ParcelablePeerHandle extends android.net.wifi.aware.PeerHandle implements android.os.Parcelable {
- ctor public ParcelablePeerHandle(android.net.wifi.aware.PeerHandle);
+ ctor public ParcelablePeerHandle(@NonNull android.net.wifi.aware.PeerHandle);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.ParcelablePeerHandle> CREATOR;
@@ -30256,16 +30260,6 @@
field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
}
- public static final class WifiAwareManager.NetworkSpecifierBuilder {
- ctor public WifiAwareManager.NetworkSpecifierBuilder();
- method @NonNull public android.net.NetworkSpecifier build();
- method @NonNull public android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder setDiscoverySession(@NonNull android.net.wifi.aware.DiscoverySession);
- method @NonNull public android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder setPeerHandle(@NonNull android.net.wifi.aware.PeerHandle);
- method @NonNull public android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder setPort(int);
- method @NonNull public android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder setPskPassphrase(@NonNull String);
- method @NonNull public android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder setTransportProtocol(int);
- }
-
public final class WifiAwareNetworkInfo implements android.os.Parcelable android.net.TransportInfo {
method public int describeContents();
method @Nullable public java.net.Inet6Address getPeerIpv6Addr();
@@ -30275,6 +30269,22 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.WifiAwareNetworkInfo> CREATOR;
}
+ public final class WifiAwareNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.WifiAwareNetworkSpecifier> CREATOR;
+ }
+
+ public static final class WifiAwareNetworkSpecifier.Builder {
+ ctor public WifiAwareNetworkSpecifier.Builder();
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier build();
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setDiscoverySession(@NonNull android.net.wifi.aware.DiscoverySession);
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPeerHandle(@NonNull android.net.wifi.aware.PeerHandle);
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPort(int);
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPskPassphrase(@NonNull String);
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setTransportProtocol(int);
+ }
+
public class WifiAwareSession implements java.lang.AutoCloseable {
method public void close();
method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, @NonNull byte[]);
@@ -30565,7 +30575,7 @@
}
public static interface WifiP2pManager.NetworkInfoListener {
- method public void onNetworkInfoAvailable(android.net.NetworkInfo);
+ method public void onNetworkInfoAvailable(@NonNull android.net.NetworkInfo);
}
public static interface WifiP2pManager.P2pStateListener {
@@ -30912,10 +30922,10 @@
method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
method public boolean removeAidsForService(android.content.ComponentName, String);
- method public boolean setOffHostForService(android.content.ComponentName, String);
+ method public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
method public boolean supportsAidPrefixRegistration();
- method public boolean unsetOffHostForService(android.content.ComponentName);
+ method public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
method public boolean unsetPreferredService(android.app.Activity);
field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
field public static final String CATEGORY_OTHER = "other";
@@ -34677,46 +34687,46 @@
public class Handler {
ctor public Handler();
- ctor public Handler(android.os.Handler.Callback);
- ctor public Handler(android.os.Looper);
- ctor public Handler(android.os.Looper, android.os.Handler.Callback);
+ ctor public Handler(@Nullable android.os.Handler.Callback);
+ ctor public Handler(@NonNull android.os.Looper);
+ ctor public Handler(@NonNull android.os.Looper, @Nullable android.os.Handler.Callback);
method @NonNull public static android.os.Handler createAsync(@NonNull android.os.Looper);
method @NonNull public static android.os.Handler createAsync(@NonNull android.os.Looper, @NonNull android.os.Handler.Callback);
- method public void dispatchMessage(android.os.Message);
- method public final void dump(android.util.Printer, String);
- method public final android.os.Looper getLooper();
- method public String getMessageName(android.os.Message);
- method public void handleMessage(android.os.Message);
- method public final boolean hasCallbacks(Runnable);
+ method public void dispatchMessage(@NonNull android.os.Message);
+ method public final void dump(@NonNull android.util.Printer, @NonNull String);
+ method @NonNull public final android.os.Looper getLooper();
+ method @NonNull public String getMessageName(@NonNull android.os.Message);
+ method public void handleMessage(@NonNull android.os.Message);
+ method public final boolean hasCallbacks(@NonNull Runnable);
method public final boolean hasMessages(int);
- method public final boolean hasMessages(int, Object);
- method public final android.os.Message obtainMessage();
- method public final android.os.Message obtainMessage(int);
- method public final android.os.Message obtainMessage(int, Object);
- method public final android.os.Message obtainMessage(int, int, int);
- method public final android.os.Message obtainMessage(int, int, int, Object);
- method public final boolean post(Runnable);
- method public final boolean postAtFrontOfQueue(Runnable);
- method public final boolean postAtTime(Runnable, long);
- method public final boolean postAtTime(Runnable, Object, long);
- method public final boolean postDelayed(Runnable, long);
- method public final boolean postDelayed(Runnable, Object, long);
- method public final void removeCallbacks(Runnable);
- method public final void removeCallbacks(Runnable, Object);
- method public final void removeCallbacksAndMessages(Object);
+ method public final boolean hasMessages(int, @Nullable Object);
+ method @NonNull public final android.os.Message obtainMessage();
+ method @NonNull public final android.os.Message obtainMessage(int);
+ method @NonNull public final android.os.Message obtainMessage(int, @Nullable Object);
+ method @NonNull public final android.os.Message obtainMessage(int, int, int);
+ method @NonNull public final android.os.Message obtainMessage(int, int, int, @Nullable Object);
+ method public final boolean post(@NonNull Runnable);
+ method public final boolean postAtFrontOfQueue(@NonNull Runnable);
+ method public final boolean postAtTime(@NonNull Runnable, long);
+ method public final boolean postAtTime(@NonNull Runnable, @Nullable Object, long);
+ method public final boolean postDelayed(@NonNull Runnable, long);
+ method public final boolean postDelayed(@NonNull Runnable, @Nullable Object, long);
+ method public final void removeCallbacks(@NonNull Runnable);
+ method public final void removeCallbacks(@NonNull Runnable, @Nullable Object);
+ method public final void removeCallbacksAndMessages(@Nullable Object);
method public final void removeMessages(int);
- method public final void removeMessages(int, Object);
+ method public final void removeMessages(int, @Nullable Object);
method public final boolean sendEmptyMessage(int);
method public final boolean sendEmptyMessageAtTime(int, long);
method public final boolean sendEmptyMessageDelayed(int, long);
- method public final boolean sendMessage(android.os.Message);
- method public final boolean sendMessageAtFrontOfQueue(android.os.Message);
- method public boolean sendMessageAtTime(android.os.Message, long);
- method public final boolean sendMessageDelayed(android.os.Message, long);
+ method public final boolean sendMessage(@NonNull android.os.Message);
+ method public final boolean sendMessageAtFrontOfQueue(@NonNull android.os.Message);
+ method public boolean sendMessageAtTime(@NonNull android.os.Message, long);
+ method public final boolean sendMessageDelayed(@NonNull android.os.Message, long);
}
public static interface Handler.Callback {
- method public boolean handleMessage(android.os.Message);
+ method public boolean handleMessage(@NonNull android.os.Message);
}
public class HandlerThread extends java.lang.Thread {
@@ -35486,6 +35496,7 @@
field public static final String DISALLOW_CONFIG_VPN = "no_config_vpn";
field public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi";
field public static final String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
+ field public static final String DISALLOW_CONTENT_SUGGESTIONS = "no_content_suggestions";
field public static final String DISALLOW_CREATE_WINDOWS = "no_create_windows";
field public static final String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
field public static final String DISALLOW_DATA_ROAMING = "no_data_roaming";
@@ -38955,6 +38966,7 @@
field public static final String ACTION_INTERNET_CONNECTIVITY = "android.settings.panel.action.INTERNET_CONNECTIVITY";
field public static final String ACTION_NFC = "android.settings.panel.action.NFC";
field public static final String ACTION_VOLUME = "android.settings.panel.action.VOLUME";
+ field public static final String ACTION_WIFI = "android.settings.panel.action.WIFI";
}
public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
@@ -39257,13 +39269,13 @@
}
public static final class Telephony.CarrierId implements android.provider.BaseColumns {
- method @NonNull public static android.net.Uri getPreciseCarrierIdUriForSubscriptionId(int);
+ method @NonNull public static android.net.Uri getSpecificCarrierIdUriForSubscriptionId(int);
method public static android.net.Uri getUriForSubscriptionId(int);
field public static final String CARRIER_ID = "carrier_id";
field public static final String CARRIER_NAME = "carrier_name";
field public static final android.net.Uri CONTENT_URI;
- field public static final String PRECISE_CARRIER_ID = "precise_carrier_id";
- field public static final String PRECISE_CARRIER_ID_NAME = "precise_carrier_id_name";
+ field public static final String SPECIFIC_CARRIER_ID = "specific_carrier_id";
+ field public static final String SPECIFIC_CARRIER_ID_NAME = "specific_carrier_id_name";
}
public static final class Telephony.Carriers implements android.provider.BaseColumns {
@@ -41407,7 +41419,7 @@
method @Nullable public String getImsi();
method public String getMcc();
method public String getMnc();
- method public int getPreciseCarrierId();
+ method public int getSpecificCarrierId();
method @Nullable public String getSpn();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.carrier.CarrierIdentifier> CREATOR;
@@ -41763,7 +41775,7 @@
method public int getId();
method public String getKey();
method public android.app.Notification getNotification();
- method public String getOpPkg();
+ method @NonNull public String getOpPkg();
method public String getOverrideGroupKey();
method public String getPackageName();
method public long getPostTime();
@@ -43968,7 +43980,6 @@
field public static final String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS";
field public static final String EXTRA_INCOMING_VIDEO_STATE = "android.telecom.extra.INCOMING_VIDEO_STATE";
field public static final String EXTRA_IS_DEFAULT_CALL_SCREENING_APP = "android.telecom.extra.IS_DEFAULT_CALL_SCREENING_APP";
- field public static final String EXTRA_IS_ENABLED = "android.telecom.extra.IS_ENABLED";
field public static final String EXTRA_NOTIFICATION_COUNT = "android.telecom.extra.NOTIFICATION_COUNT";
field public static final String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
field public static final String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
@@ -44135,9 +44146,10 @@
}
public final class AvailableNetworkInfo implements android.os.Parcelable {
- ctor public AvailableNetworkInfo(int, int, java.util.List<java.lang.String>);
+ ctor public AvailableNetworkInfo(int, int, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.Integer>);
method public int describeContents();
- method public java.util.List<java.lang.String> getMccMncs();
+ method @NonNull public java.util.List<java.lang.Integer> getBands();
+ method @NonNull public java.util.List<java.lang.String> getMccMncs();
method public int getPriority();
method public int getSubId();
method public void writeToParcel(android.os.Parcel, int);
@@ -44307,6 +44319,7 @@
field public static final String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
field public static final String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
field public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
+ field public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
field public static final String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
field public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
@@ -44597,7 +44610,7 @@
public class MbmsGroupCallSession implements java.lang.AutoCloseable {
method public void close();
method @Nullable public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
- method public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
+ method @Nullable public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
method @Nullable public android.telephony.mbms.GroupCall startGroupCall(long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.GroupCallCallback);
}
@@ -44965,9 +44978,9 @@
method public String getIccId();
method public int getIconTint();
method @Deprecated public int getMcc();
- method public String getMccString();
+ method @Nullable public String getMccString();
method @Deprecated public int getMnc();
- method public String getMncString();
+ method @Nullable public String getMncString();
method public String getNumber();
method public int getSimSlotIndex();
method public int getSubscriptionId();
@@ -45076,14 +45089,14 @@
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
method public int getCarrierIdFromSimMccMnc();
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.telephony.CellLocation getCellLocation();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getCurrentEmergencyNumberList();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getCurrentEmergencyNumberList(int);
method public int getDataActivity();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getDataNetworkType();
method public int getDataState();
method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId();
method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId(int);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getDeviceSoftwareVersion();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String[] getForbiddenPlmns();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getGroupIdLevel1();
method public String getIccAuthentication(int, int, String);
@@ -45112,9 +45125,9 @@
method public String getSimCountryIso();
method public String getSimOperator();
method public String getSimOperatorName();
- method public int getSimPreciseCarrierId();
- method @Nullable public CharSequence getSimPreciseCarrierIdName();
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSimSerialNumber();
+ method public int getSimSpecificCarrierId();
+ method @Nullable public CharSequence getSimSpecificCarrierIdName();
method public int getSimState();
method public int getSimState(int);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSubscriberId();
@@ -45135,9 +45148,9 @@
method public String iccTransmitApduBasicChannel(int, int, int, int, int, String);
method public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String);
method public boolean isConcurrentVoiceAndDataSupported();
- method public boolean isCurrentEmergencyNumber(@NonNull String);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled();
+ method public boolean isEmergencyNumber(@NonNull String);
method public boolean isHearingAidCompatibilitySupported();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isMultisimSupported();
method public boolean isNetworkRoaming();
@@ -45166,7 +45179,7 @@
method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
method @Deprecated public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int);
- method public boolean updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>);
+ method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
field public static final String ACTION_CARRIER_MESSAGING_CLIENT_SERVICE = "android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE";
field public static final String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
field public static final String ACTION_NETWORK_COUNTRY_CHANGED = "android.telephony.action.NETWORK_COUNTRY_CHANGED";
@@ -45175,7 +45188,7 @@
field public static final String ACTION_SECRET_CODE = "android.telephony.action.SECRET_CODE";
field public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
field public static final String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED";
- field public static final String ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED";
+ field public static final String ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED";
field public static final int APPTYPE_CSIM = 4; // 0x4
field public static final int APPTYPE_ISIM = 5; // 0x5
field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -45210,8 +45223,8 @@
field public static final String EXTRA_NETWORK_COUNTRY = "android.telephony.extra.NETWORK_COUNTRY";
field public static final String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
field public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telephony.extra.PHONE_ACCOUNT_HANDLE";
- field public static final String EXTRA_PRECISE_CARRIER_ID = "android.telephony.extra.PRECISE_CARRIER_ID";
- field public static final String EXTRA_PRECISE_CARRIER_NAME = "android.telephony.extra.PRECISE_CARRIER_NAME";
+ field public static final String EXTRA_SPECIFIC_CARRIER_ID = "android.telephony.extra.SPECIFIC_CARRIER_ID";
+ field public static final String EXTRA_SPECIFIC_CARRIER_NAME = "android.telephony.extra.SPECIFIC_CARRIER_NAME";
field public static final String EXTRA_STATE = "state";
field public static final String EXTRA_STATE_IDLE;
field public static final String EXTRA_STATE_OFFHOOK;
@@ -45259,6 +45272,11 @@
field public static final int UNINITIALIZED_CARD_ID = -2; // 0xfffffffe
field public static final int UNKNOWN_CARRIER_ID = -1; // 0xffffffff
field public static final int UNSUPPORTED_CARD_ID = -1; // 0xffffffff
+ field public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2; // 0x2
+ field public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3; // 0x3
+ field public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4; // 0x4
+ field public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0; // 0x0
+ field public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1; // 0x1
field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
field public static final String VVM_TYPE_CVVM = "vvm_type_cvvm";
@@ -45452,15 +45470,13 @@
public final class EmergencyNumber implements java.lang.Comparable<android.telephony.emergency.EmergencyNumber> android.os.Parcelable {
method public int compareTo(@NonNull android.telephony.emergency.EmergencyNumber);
method public int describeContents();
- method public String getCountryIso();
+ method @NonNull public String getCountryIso();
method public int getEmergencyCallRouting();
- method public int getEmergencyNumberSourceBitmask();
- method public java.util.List<java.lang.Integer> getEmergencyNumberSources();
- method public java.util.List<java.lang.Integer> getEmergencyServiceCategories();
- method public int getEmergencyServiceCategoryBitmask();
+ method @NonNull public java.util.List<java.lang.Integer> getEmergencyNumberSources();
+ method @NonNull public java.util.List<java.lang.Integer> getEmergencyServiceCategories();
method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
- method public String getMnc();
- method public String getNumber();
+ method @NonNull public String getMnc();
+ method @NonNull public String getNumber();
method public boolean isFromSources(int);
method public boolean isInEmergencyServiceCategories(int);
method public void writeToParcel(android.os.Parcel, int);
@@ -50064,7 +50080,7 @@
}
public class Surface implements android.os.Parcelable {
- ctor public Surface(android.view.SurfaceControl);
+ ctor public Surface(@NonNull android.view.SurfaceControl);
ctor public Surface(android.graphics.SurfaceTexture);
method public int describeContents();
method public boolean isValid();
@@ -50098,10 +50114,10 @@
public static class SurfaceControl.Builder {
ctor public SurfaceControl.Builder();
- method public android.view.SurfaceControl build();
- method public android.view.SurfaceControl.Builder setBufferSize(@IntRange(from=0) int, @IntRange(from=0) int);
+ method @NonNull public android.view.SurfaceControl build();
+ method @NonNull public android.view.SurfaceControl.Builder setBufferSize(@IntRange(from=0) int, @IntRange(from=0) int);
method @NonNull public android.view.SurfaceControl.Builder setFormat(int);
- method public android.view.SurfaceControl.Builder setName(String);
+ method @NonNull public android.view.SurfaceControl.Builder setName(@NonNull String);
method @NonNull public android.view.SurfaceControl.Builder setOpaque(boolean);
method @NonNull public android.view.SurfaceControl.Builder setParent(@Nullable android.view.SurfaceControl);
}
@@ -50333,7 +50349,7 @@
method @android.view.ViewDebug.ExportedProperty(category="drawing") public float getAlpha();
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
- method @NonNull public java.util.List<java.lang.Integer> getAttributeResolutionStack(@AttrRes int);
+ method @NonNull public int[] getAttributeResolutionStack(@AttrRes int);
method @NonNull public java.util.Map<java.lang.Integer,java.lang.Integer> getAttributeSourceResourceMap();
method @android.view.ViewDebug.ExportedProperty @Nullable public String[] getAutofillHints();
method public final android.view.autofill.AutofillId getAutofillId();
@@ -50830,8 +50846,8 @@
method public final boolean startDragAndDrop(android.content.ClipData, android.view.View.DragShadowBuilder, Object, int);
method public boolean startNestedScroll(int);
method public void stopNestedScroll();
- method public void transformMatrixToGlobal(android.graphics.Matrix);
- method public void transformMatrixToLocal(android.graphics.Matrix);
+ method public void transformMatrixToGlobal(@NonNull android.graphics.Matrix);
+ method public void transformMatrixToLocal(@NonNull android.graphics.Matrix);
method public void unscheduleDrawable(@NonNull android.graphics.drawable.Drawable, @NonNull Runnable);
method public void unscheduleDrawable(android.graphics.drawable.Drawable);
method public final void updateDragShadow(android.view.View.DragShadowBuilder);
@@ -53451,11 +53467,6 @@
package android.view.inspector {
- public class GeneratedInspectionCompanionProvider implements android.view.inspector.InspectionCompanionProvider {
- ctor public GeneratedInspectionCompanionProvider();
- method @Nullable public <T> android.view.inspector.InspectionCompanion<T> provide(@NonNull Class<T>);
- }
-
public interface InspectionCompanion<T> {
method @Nullable public default String getNodeName();
method public void mapProperties(@NonNull android.view.inspector.PropertyMapper);
@@ -53536,6 +53547,11 @@
ctor public PropertyReader.PropertyTypeMismatchException(int, @NonNull String, @NonNull String);
}
+ public class StaticInspectionCompanionProvider implements android.view.inspector.InspectionCompanionProvider {
+ ctor public StaticInspectionCompanionProvider();
+ method @Nullable public <T> android.view.inspector.InspectionCompanion<T> provide(@NonNull Class<T>);
+ }
+
public final class WindowInspector {
method @NonNull public static java.util.List<android.view.View> getGlobalWindowViews();
}
@@ -53607,7 +53623,6 @@
method public int describeContents();
method @Nullable public String getCallingPackageName();
method @NonNull public java.util.List<android.view.textclassifier.ConversationActions.Message> getConversation();
- method @Nullable public String getConversationId();
method @Nullable public java.util.List<java.lang.String> getHints();
method @IntRange(from=0xffffffff) public int getMaxSuggestions();
method @NonNull public android.view.textclassifier.TextClassifier.EntityConfig getTypeConfig();
@@ -53620,7 +53635,6 @@
public static final class ConversationActions.Request.Builder {
ctor public ConversationActions.Request.Builder(@NonNull java.util.List<android.view.textclassifier.ConversationActions.Message>);
method @NonNull public android.view.textclassifier.ConversationActions.Request build();
- method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setConversationId(@Nullable String);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setHints(@Nullable java.util.List<java.lang.String>);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(@IntRange(from=0xffffffff) int);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(@Nullable android.view.textclassifier.TextClassifier.EntityConfig);
@@ -54501,7 +54515,7 @@
method public abstract boolean getDomStorageEnabled();
method public abstract String getFantasyFontFamily();
method public abstract String getFixedFontFamily();
- method public int getForceDarkMode();
+ method public int getForceDark();
method public abstract boolean getJavaScriptCanOpenWindowsAutomatically();
method public abstract boolean getJavaScriptEnabled();
method public abstract android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
@@ -54548,7 +54562,7 @@
method @Deprecated public abstract void setEnableSmoothTransition(boolean);
method public abstract void setFantasyFontFamily(String);
method public abstract void setFixedFontFamily(String);
- method public void setForceDarkMode(int);
+ method public void setForceDark(int);
method @Deprecated public abstract void setGeolocationDatabasePath(String);
method public abstract void setGeolocationEnabled(boolean);
method public abstract void setJavaScriptCanOpenWindowsAutomatically(boolean);
@@ -54579,9 +54593,9 @@
method public abstract void setUserAgentString(@Nullable String);
method public abstract boolean supportMultipleWindows();
method public abstract boolean supportZoom();
- field public static final int FORCE_DARK_AUTO = 0; // 0x0
- field public static final int FORCE_DARK_OFF = -1; // 0xffffffff
- field public static final int FORCE_DARK_ON = 1; // 0x1
+ field public static final int FORCE_DARK_AUTO = 1; // 0x1
+ field public static final int FORCE_DARK_OFF = 0; // 0x0
+ field public static final int FORCE_DARK_ON = 2; // 0x2
field public static final int LOAD_CACHE_ELSE_NETWORK = 1; // 0x1
field public static final int LOAD_CACHE_ONLY = 3; // 0x3
field public static final int LOAD_DEFAULT = -1; // 0xffffffff
@@ -54704,8 +54718,8 @@
method @NonNull public static ClassLoader getWebViewClassLoader();
method public android.webkit.WebViewClient getWebViewClient();
method @NonNull public android.os.Looper getWebViewLooper();
- method @Nullable public android.webkit.WebViewRenderer getWebViewRenderer();
- method @Nullable public android.webkit.WebViewRendererClient getWebViewRendererClient();
+ method @Nullable public android.webkit.WebViewRenderProcess getWebViewRenderProcess();
+ method @Nullable public android.webkit.WebViewRenderProcessClient getWebViewRenderProcessClient();
method public void goBack();
method public void goBackOrForward(int);
method public void goForward();
@@ -54755,8 +54769,8 @@
method public void setWebChromeClient(android.webkit.WebChromeClient);
method public static void setWebContentsDebuggingEnabled(boolean);
method public void setWebViewClient(android.webkit.WebViewClient);
- method public void setWebViewRendererClient(@NonNull java.util.concurrent.Executor, @NonNull android.webkit.WebViewRendererClient);
- method public void setWebViewRendererClient(@Nullable android.webkit.WebViewRendererClient);
+ method public void setWebViewRenderProcessClient(@NonNull java.util.concurrent.Executor, @NonNull android.webkit.WebViewRenderProcessClient);
+ method public void setWebViewRenderProcessClient(@Nullable android.webkit.WebViewRenderProcessClient);
method @Deprecated public boolean shouldDelayChildPressedState();
method @Deprecated public boolean showFindDialog(@Nullable String, boolean);
method public static void startSafeBrowsing(@NonNull android.content.Context, @Nullable android.webkit.ValueCallback<java.lang.Boolean>);
@@ -54872,14 +54886,15 @@
method @Deprecated public android.webkit.WebView getWebView();
}
- public abstract class WebViewRenderer {
+ public abstract class WebViewRenderProcess {
+ ctor public WebViewRenderProcess();
method public abstract boolean terminate();
}
- public abstract class WebViewRendererClient {
- ctor public WebViewRendererClient();
- method public abstract void onRendererResponsive(@NonNull android.webkit.WebView, @Nullable android.webkit.WebViewRenderer);
- method public abstract void onRendererUnresponsive(@NonNull android.webkit.WebView, @Nullable android.webkit.WebViewRenderer);
+ public abstract class WebViewRenderProcessClient {
+ ctor public WebViewRenderProcessClient();
+ method public abstract void onRenderProcessResponsive(@NonNull android.webkit.WebView, @Nullable android.webkit.WebViewRenderProcess);
+ method public abstract void onRenderProcessUnresponsive(@NonNull android.webkit.WebView, @Nullable android.webkit.WebViewRenderProcess);
}
}
@@ -56257,7 +56272,7 @@
method public String[] getDisplayedValues();
method public int getMaxValue();
method public int getMinValue();
- method public int getSelectionDividerHeight();
+ method @Px public int getSelectionDividerHeight();
method @ColorInt public int getTextColor();
method @FloatRange(from=0.0, fromInclusive=false) public float getTextSize();
method public int getValue();
@@ -58056,7 +58071,7 @@
public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
ctor public DelegateLastClassLoader(String, ClassLoader);
ctor public DelegateLastClassLoader(String, String, ClassLoader);
- ctor public DelegateLastClassLoader(String, String, ClassLoader, boolean);
+ ctor public DelegateLastClassLoader(@NonNull String, @Nullable String, @Nullable ClassLoader, boolean);
}
public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
diff --git a/api/system-current.txt b/api/system-current.txt
index a0a8fc9..04bddc1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1115,26 +1115,33 @@
method public void onRoleHoldersChanged(@NonNull String, @NonNull android.os.UserHandle);
}
+ public abstract class RoleControllerService extends android.app.Service {
+ ctor public RoleControllerService();
+ method @WorkerThread public abstract boolean onAddRoleHolder(@NonNull String, @NonNull String, int);
+ method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
+ method @WorkerThread public abstract boolean onClearRoleHolders(@NonNull String, int);
+ method @WorkerThread public abstract boolean onGrantDefaultRoles();
+ method public abstract boolean onIsApplicationQualifiedForRole(@NonNull String, @NonNull String);
+ method public abstract boolean onIsRoleVisible(@NonNull String);
+ method @WorkerThread public abstract boolean onRemoveRoleHolder(@NonNull String, @NonNull String, int);
+ field public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService";
+ }
+
public final class RoleManager {
method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void addOnRoleHoldersChangedListenerAsUser(@NonNull java.util.concurrent.Executor, @NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
}
- public interface RoleManagerCallback {
- method public void onFailure();
- method public void onSuccess();
- }
-
}
package android.app.usage {
@@ -1560,23 +1567,26 @@
public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
method public boolean getAllocateAggressive();
- method public boolean getAllowDowngrade();
+ method @Deprecated public boolean getAllowDowngrade();
method public boolean getDontKillApp();
+ method public boolean getEnableRollback();
method @Nullable public String[] getGrantedRuntimePermissions();
method public boolean getInstallAsFullApp(boolean);
method public boolean getInstallAsInstantApp(boolean);
method public boolean getInstallAsVirtualPreload();
+ method public boolean getRequestDowngrade();
}
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
method @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public void setAllocateAggressive(boolean);
- method public void setAllowDowngrade(boolean);
+ method @Deprecated public void setAllowDowngrade(boolean);
method public void setDontKillApp(boolean);
- method public void setEnableRollback();
+ method public void setEnableRollback(boolean);
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
method public void setInstallAsInstantApp(boolean);
method public void setInstallAsVirtualPreload();
+ method public void setRequestDowngrade(boolean);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
}
@@ -1606,7 +1616,7 @@
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_INSTANT_APPS) public abstract java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
method public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(String);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract int getIntentVerificationStatusAsUser(String, int);
- method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle);
+ method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.GET_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] getUnsuspendablePackages(@NonNull String[]);
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @Deprecated public abstract int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -1641,6 +1651,8 @@
field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
field public static final int FLAG_PERMISSION_SYSTEM_FIXED = 16; // 0x10
field public static final int FLAG_PERMISSION_USER_FIXED = 2; // 0x2
+ field public static final int FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED = 512; // 0x200
+ field public static final int FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED = 256; // 0x100
field public static final int FLAG_PERMISSION_USER_SET = 1; // 0x1
field public static final int INSTALL_FAILED_ALREADY_EXISTS = -1; // 0xffffffff
field public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13; // 0xfffffff3
@@ -1686,7 +1698,7 @@
field public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED = 0; // 0x0
field public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1; // 0xffffffff
field public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
- field public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
+ field @Deprecated public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
field public static final int MATCH_ANY_USER = 4194304; // 0x400000
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
field public static final int MATCH_INSTANT = 8388608; // 0x800000
@@ -1704,7 +1716,7 @@
method public void onPermissionsChanged(int);
}
- @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
+ @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
}
public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
@@ -1804,18 +1816,18 @@
public final class PackageRollbackInfo implements android.os.Parcelable {
method public int describeContents();
- method public String getPackageName();
- method public android.content.pm.VersionedPackage getVersionRolledBackFrom();
- method public android.content.pm.VersionedPackage getVersionRolledBackTo();
+ method @NonNull public String getPackageName();
+ method @NonNull public android.content.pm.VersionedPackage getVersionRolledBackFrom();
+ method @NonNull public android.content.pm.VersionedPackage getVersionRolledBackTo();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.rollback.PackageRollbackInfo> CREATOR;
}
public final class RollbackInfo implements android.os.Parcelable {
method public int describeContents();
- method public java.util.List<android.content.pm.VersionedPackage> getCausePackages();
+ method @NonNull public java.util.List<android.content.pm.VersionedPackage> getCausePackages();
method public int getCommittedSessionId();
- method public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
+ method @NonNull public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
method public int getRollbackId();
method public boolean isStaged();
method public void writeToParcel(android.os.Parcel, int);
@@ -1825,7 +1837,7 @@
public final class RollbackManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void reloadPersistedData();
field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS";
@@ -4034,11 +4046,13 @@
method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) public String getCaptivePortalServerUrl();
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
+ method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
+ method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
field public static final int TETHERING_BLUETOOTH = 2; // 0x2
@@ -4059,6 +4073,11 @@
method public void onEntitlementResult(int);
}
+ public abstract static class ConnectivityManager.OnTetheringEventCallback {
+ ctor public ConnectivityManager.OnTetheringEventCallback();
+ method public void onUpstreamChanged(@Nullable android.net.Network);
+ }
+
public final class IpPrefix implements android.os.Parcelable {
ctor public IpPrefix(java.net.InetAddress, int);
ctor public IpPrefix(String);
@@ -4713,18 +4732,16 @@
}
public class WifiInfo implements android.os.Parcelable {
- method @Nullable public String getFqdn();
- method @Nullable public String getProviderFriendlyName();
method public boolean isOsuAp();
method public boolean isPasspointAp();
}
public class WifiManager {
method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void addWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiUsabilityStatsListener);
- method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
- method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(int, android.net.wifi.WifiManager.ActionListener);
- method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disable(int, android.net.wifi.WifiManager.ActionListener);
- method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void forget(int, android.net.wifi.WifiManager.ActionListener);
+ method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
+ method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(int, @Nullable android.net.wifi.WifiManager.ActionListener);
+ method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disable(int, @Nullable android.net.wifi.WifiManager.ActionListener);
+ method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener);
method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>);
method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(@NonNull java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
@@ -4736,7 +4753,7 @@
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void removeWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.WifiUsabilityStatsListener);
- method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
+ method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
method @RequiresPermission("android.permission.WIFI_SET_DEVICE_MOBILITY_STATE") public void setDeviceMobilityState(int);
method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
@@ -4955,8 +4972,8 @@
method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
}
- public static final class WifiAwareManager.NetworkSpecifierBuilder {
- method @NonNull public android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder setPmk(@NonNull byte[]);
+ public static final class WifiAwareNetworkSpecifier.Builder {
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPmk(@NonNull byte[]);
}
public class WifiAwareSession implements java.lang.AutoCloseable {
@@ -5161,10 +5178,10 @@
public static interface Binder.ProxyTransactListener {
method public void onTransactEnded(@Nullable Object);
- method public Object onTransactStarted(android.os.IBinder, int);
+ method @Nullable public Object onTransactStarted(@NonNull android.os.IBinder, int);
}
- public class BugreportManager {
+ public final class BugreportManager {
method @RequiresPermission(android.Manifest.permission.DUMP) public void cancelBugreport();
method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
}
@@ -5173,7 +5190,7 @@
ctor public BugreportManager.BugreportCallback();
method public void onError(int);
method public void onFinished();
- method public void onProgress(float);
+ method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
@@ -5182,7 +5199,7 @@
}
public final class BugreportParams {
- ctor public BugreportParams(@android.os.BugreportParams.BugreportMode int);
+ ctor public BugreportParams(int);
method public int getMode();
field public static final int BUGREPORT_MODE_FULL = 0; // 0x0
field public static final int BUGREPORT_MODE_INTERACTIVE = 1; // 0x1
@@ -5192,9 +5209,6 @@
field public static final int BUGREPORT_MODE_WIFI = 5; // 0x5
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"BUGREPORT_MODE_"}, value={android.os.BugreportParams.BUGREPORT_MODE_FULL, android.os.BugreportParams.BUGREPORT_MODE_INTERACTIVE, android.os.BugreportParams.BUGREPORT_MODE_REMOTE, android.os.BugreportParams.BUGREPORT_MODE_WEAR, android.os.BugreportParams.BUGREPORT_MODE_TELEPHONY, android.os.BugreportParams.BUGREPORT_MODE_WIFI}) public static @interface BugreportParams.BugreportMode {
- }
-
public static class Build.VERSION {
field public static final String PREVIEW_SDK_FINGERPRINT;
}
@@ -5584,7 +5598,6 @@
}
public class UserManager {
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean canSwitchUsers();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearSeedAccountData();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountName();
@@ -5594,6 +5607,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.graphics.Bitmap getUserIcon();
method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
+ method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability();
method public boolean hasRestrictedProfiles();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isAdminUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isGuestUser();
@@ -5601,7 +5615,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedProfile(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isPrimaryUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile();
- method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(android.os.UserHandle);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String);
field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
@@ -5611,6 +5625,10 @@
field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2
field public static final int RESTRICTION_SOURCE_PROFILE_OWNER = 4; // 0x4
field public static final int RESTRICTION_SOURCE_SYSTEM = 1; // 0x1
+ field public static final int SWITCHABILITY_STATUS_OK = 0; // 0x0
+ field public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 4; // 0x4
+ field public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1; // 0x1
+ field public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 2; // 0x2
}
public static final class UserManager.EnforcingUser implements android.os.Parcelable {
@@ -5675,8 +5693,6 @@
method @NonNull public abstract java.util.List<android.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(@NonNull String);
method @NonNull public abstract java.util.List<android.permission.RuntimePermissionUsageInfo> onGetPermissionUsages(boolean, long);
method public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream);
- method public abstract boolean onIsApplicationQualifiedForRole(@NonNull String, @NonNull String);
- method public abstract boolean onIsRoleVisible(@NonNull String);
method @BinderThread public abstract boolean onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle);
method @BinderThread public abstract void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream);
method public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String);
@@ -5829,6 +5845,7 @@
}
public final class DeviceConfig {
+ method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(String, String, boolean);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(String, String, float);
@@ -5836,7 +5853,8 @@
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static long getLong(String, String, long);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(String, String);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(String, String, String);
- method public static void removeOnPropertyChangedListener(android.provider.DeviceConfig.OnPropertyChangedListener);
+ method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
+ method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(String, String, String, boolean);
field public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
@@ -5871,8 +5889,11 @@
field public static final String NAMESPACE = "intelligence_attention";
}
+ public static interface DeviceConfig.OnPropertiesChangedListener {
+ method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
+ }
+
public static interface DeviceConfig.OnPropertyChangedListener {
- method public default void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
method public void onPropertyChanged(String, String, String);
}
@@ -6164,21 +6185,6 @@
}
-package android.rolecontrollerservice {
-
- public abstract class RoleControllerService extends android.app.Service {
- ctor public RoleControllerService();
- method public abstract void onAddRoleHolder(@NonNull String, @NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
- method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
- method public abstract void onClearRoleHolders(@NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
- method public abstract void onGrantDefaultRoles(@NonNull android.app.role.RoleManagerCallback);
- method public abstract void onRemoveRoleHolder(@NonNull String, @NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
- method public abstract void onSmsKillSwitchToggled(boolean);
- field public static final String SERVICE_INTERFACE = "android.rolecontrollerservice.RoleControllerService";
- }
-
-}
-
package android.security.keystore {
public abstract class AttestationUtils {
@@ -6475,10 +6481,14 @@
public abstract class ContentSuggestionsService extends android.app.Service {
ctor public ContentSuggestionsService();
- method public abstract void classifyContentSelections(@NonNull android.app.contentsuggestions.ClassificationsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.ClassificationsCallback);
- method public abstract void notifyInteraction(@NonNull String, @NonNull android.os.Bundle);
- method public abstract void processContextImage(int, @Nullable android.graphics.Bitmap, @NonNull android.os.Bundle);
- method public abstract void suggestContentSelections(@NonNull android.app.contentsuggestions.SelectionsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.SelectionsCallback);
+ method @Deprecated public void classifyContentSelections(@NonNull android.app.contentsuggestions.ClassificationsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.ClassificationsCallback);
+ method @Deprecated public void notifyInteraction(@NonNull String, @NonNull android.os.Bundle);
+ method public void onClassifyContentSelections(@NonNull android.app.contentsuggestions.ClassificationsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.ClassificationsCallback);
+ method public void onNotifyInteraction(@NonNull String, @NonNull android.os.Bundle);
+ method public void onProcessContextImage(int, @Nullable android.graphics.Bitmap, @NonNull android.os.Bundle);
+ method public void onSuggestContentSelections(@NonNull android.app.contentsuggestions.SelectionsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.SelectionsCallback);
+ method @Deprecated public void processContextImage(int, @Nullable android.graphics.Bitmap, @NonNull android.os.Bundle);
+ method @Deprecated public void suggestContentSelections(@NonNull android.app.contentsuggestions.SelectionsRequest, @NonNull android.app.contentsuggestions.ContentSuggestionsManager.SelectionsCallback);
field public static final String SERVICE_INTERFACE = "android.service.contentsuggestions.ContentSuggestionsService";
}
@@ -8054,10 +8064,10 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCurrentPotentialEmergencyNumber(@NonNull String);
method public boolean isDataConnectivityPossible();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isRebootRequiredForModemConfigChange();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
@@ -8199,6 +8209,7 @@
}
public final class DataProfile implements android.os.Parcelable {
+ method public int describeContents();
method @NonNull public String getApn();
method public int getAuthType();
method public int getBearerBitmap();
@@ -8216,6 +8227,8 @@
method public boolean isEnabled();
method public boolean isPersistent();
method public boolean isPreferred();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataProfile> CREATOR;
field public static final int TYPE_3GPP = 1; // 0x1
field public static final int TYPE_3GPP2 = 2; // 0x2
field public static final int TYPE_COMMON = 0; // 0x0
@@ -8447,7 +8460,7 @@
method public static int getCallTypeFromVideoState(int);
method public int getEmergencyCallRouting();
method public int getEmergencyServiceCategories();
- method public java.util.List<java.lang.String> getEmergencyUrns();
+ method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
method public int getRestrictCause();
method public int getServiceType();
@@ -8465,7 +8478,7 @@
method public void setEmergencyCallRouting(int);
method public void setEmergencyCallTesting(boolean);
method public void setEmergencyServiceCategories(int);
- method public void setEmergencyUrns(java.util.List<java.lang.String>);
+ method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
method public void setHasKnownUserIntentEmergency(boolean);
method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
method public void updateCallType(android.telephony.ims.ImsCallProfile);
@@ -9070,7 +9083,7 @@
public static class ProvisioningManager.Callback {
ctor public ProvisioningManager.Callback();
method public void onProvisioningIntChanged(int, int);
- method public void onProvisioningStringChanged(int, String);
+ method public void onProvisioningStringChanged(int, @NonNull String);
}
}
@@ -9833,8 +9846,8 @@
method public int getVisibleTitleHeight();
method public android.webkit.WebChromeClient getWebChromeClient();
method public android.webkit.WebViewClient getWebViewClient();
- method public android.webkit.WebViewRenderer getWebViewRenderer();
- method public android.webkit.WebViewRendererClient getWebViewRendererClient();
+ method @Nullable public android.webkit.WebViewRenderProcess getWebViewRenderProcess();
+ method @Nullable public android.webkit.WebViewRenderProcessClient getWebViewRenderProcessClient();
method public android.view.View getZoomControls();
method public void goBack();
method public void goBackOrForward(int);
@@ -9884,7 +9897,7 @@
method public void setVerticalScrollbarOverlay(boolean);
method public void setWebChromeClient(android.webkit.WebChromeClient);
method public void setWebViewClient(android.webkit.WebViewClient);
- method public void setWebViewRendererClient(@Nullable java.util.concurrent.Executor, @Nullable android.webkit.WebViewRendererClient);
+ method public void setWebViewRenderProcessClient(@Nullable java.util.concurrent.Executor, @Nullable android.webkit.WebViewRenderProcessClient);
method public boolean showFindDialog(String, boolean);
method public void stopLoading();
method public boolean zoomBy(float);
@@ -9966,10 +9979,6 @@
field public final android.content.pm.Signature[] signatures;
}
- public abstract class WebViewRenderer {
- ctor public WebViewRenderer();
- }
-
public final class WebViewUpdateService {
method public static android.webkit.WebViewProviderInfo[] getAllWebViewPackages();
method public static String getCurrentWebViewPackageName();
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 7e04469..18d0ec0 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -60,6 +60,14 @@
}
+package android.content.pm {
+
+ public static class PackageInstaller.SessionParams implements android.os.Parcelable {
+ method @Deprecated public void setEnableRollback();
+ }
+
+}
+
package android.location {
public class LocationManager {
diff --git a/api/test-current.txt b/api/test-current.txt
index 4d1d440..97f5ffe 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -512,24 +512,19 @@
public final class RoleManager {
method @RequiresPermission("android.permission.OBSERVE_ROLE_HOLDERS") public void addOnRoleHoldersChangedListenerAsUser(@NonNull java.util.concurrent.Executor, @NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
- method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
+ method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
- method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
+ method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
method @NonNull @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
method @NonNull @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.OBSERVE_ROLE_HOLDERS") public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
- method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
+ method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
}
- public interface RoleManagerCallback {
- method public void onFailure();
- method public void onSuccess();
- }
-
}
package android.app.usage {
@@ -640,7 +635,7 @@
method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL") public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
method @Nullable public abstract String[] getNamesForUids(int[]);
method public abstract String getPermissionControllerPackageName();
- method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS"}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle);
+ method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS", "android.permission.GET_RUNTIME_PERMISSIONS"}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle);
method @NonNull public abstract String getServicesSystemSharedLibraryPackageName();
method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
method public String getWellbeingPackageName();
@@ -1233,6 +1228,21 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
}
+ public final class TestNetworkInterface implements android.os.Parcelable {
+ ctor public TestNetworkInterface(android.os.ParcelFileDescriptor, String);
+ method public int describeContents();
+ method public android.os.ParcelFileDescriptor getFileDescriptor();
+ method public String getInterfaceName();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.TestNetworkInterface> CREATOR;
+ }
+
+ public class TestNetworkManager {
+ method public android.net.TestNetworkInterface createTunInterface(@NonNull android.net.LinkAddress[]);
+ method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
+ method public void teardownTestNetwork(@NonNull android.net.Network);
+ }
+
public class TrafficStats {
method public static long getLoopbackRxBytes();
method public static long getLoopbackRxPackets();
@@ -1992,6 +2002,7 @@
}
public final class DeviceConfig {
+ method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static boolean getBoolean(String, String, boolean);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static float getFloat(String, String, float);
@@ -1999,15 +2010,19 @@
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static long getLong(String, String, long);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(String, String);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getString(String, String, String);
- method public static void removeOnPropertyChangedListener(android.provider.DeviceConfig.OnPropertyChangedListener);
+ method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
+ method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission("android.permission.WRITE_DEVICE_CONFIG") public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission("android.permission.WRITE_DEVICE_CONFIG") public static boolean setProperty(String, String, String, boolean);
field public static final String NAMESPACE_AUTOFILL = "autofill";
field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
}
+ public static interface DeviceConfig.OnPropertiesChangedListener {
+ method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
+ }
+
public static interface DeviceConfig.OnPropertyChangedListener {
- method public default void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
method public void onPropertyChanged(String, String, String);
}
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index e5f6223..e85f132 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -38,7 +38,10 @@
using android::idmap2::CommandLineOptions;
using android::idmap2::Idmap;
-using android::idmap2::PoliciesToBitmask;
+using android::idmap2::kPolicyProduct;
+using android::idmap2::kPolicyPublic;
+using android::idmap2::kPolicySystem;
+using android::idmap2::kPolicyVendor;
using android::idmap2::PolicyBitmask;
using android::idmap2::PolicyFlags;
using android::idmap2::Result;
@@ -87,20 +90,22 @@
return std::make_unique<std::vector<std::string>>(paths.cbegin(), paths.cend());
}
-PolicyBitmask PolicyForPath(const std::string& apk_path) {
- static const std::vector<std::pair<std::string, PolicyBitmask>> values = {
- {"/product/", PolicyFlags::POLICY_PRODUCT_PARTITION},
- {"/system/", PolicyFlags::POLICY_SYSTEM_PARTITION},
- {"/vendor/", PolicyFlags::POLICY_VENDOR_PARTITION},
+std::vector<std::string> PoliciesForPath(const std::string& apk_path) {
+ static const std::vector<std::pair<std::string, std::string>> values = {
+ {"/product/", kPolicyProduct},
+ {"/system/", kPolicySystem},
+ {"/vendor/", kPolicyVendor},
};
+ std::vector<std::string> fulfilled_policies = {kPolicyPublic};
for (auto const& pair : values) {
if (apk_path.compare(0, pair.first.size(), pair.first) == 0) {
- return pair.second | PolicyFlags::POLICY_PUBLIC;
+ fulfilled_policies.emplace_back(pair.second);
+ break;
}
}
- return PolicyFlags::POLICY_PUBLIC;
+ return fulfilled_policies;
}
} // namespace
@@ -161,21 +166,17 @@
continue;
}
- PolicyBitmask fulfilled_policies;
+ std::vector<std::string> fulfilled_policies;
if (!override_policies.empty()) {
- auto conv_result = PoliciesToBitmask(override_policies);
- if (conv_result) {
- fulfilled_policies = *conv_result;
- } else {
- out_error << "error: " << conv_result.GetErrorMessage() << std::endl;
- return false;
- }
+ fulfilled_policies = override_policies;
} else {
- fulfilled_policies = PolicyForPath(path);
+ fulfilled_policies = PoliciesForPath(path);
}
bool ignore_overlayable = false;
- if ((fulfilled_policies & PolicyFlags::POLICY_VENDOR_PARTITION) != 0 && !VendorIsQOrLater()) {
+ if (std::find(fulfilled_policies.begin(), fulfilled_policies.end(), kPolicyVendor) !=
+ fulfilled_policies.end() &&
+ !VendorIsQOrLater()) {
// If the overlay is on a pre-Q vendor partition, do not enforce overlayable
// restrictions on this overlay because the pre-Q platform has no understanding of
// overlayable.
@@ -185,7 +186,7 @@
std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, path);
// Sort the static overlays in ascending priority order
- InputOverlay input{path, idmap_path, overlay_info->priority, override_policies,
+ InputOverlay input{path, idmap_path, overlay_info->priority, fulfilled_policies,
ignore_overlayable};
interesting_apks.insert(
std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input);
@@ -211,8 +212,8 @@
}
for (const std::string& policy : overlay.policies) {
- verify_args.emplace_back("--policy");
- verify_args.emplace_back(policy);
+ create_args.emplace_back("--policy");
+ create_args.emplace_back(policy);
}
if (!Create(create_args, out_error)) {
diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h
index 911d3f2..cd76b84 100644
--- a/cmds/idmap2/include/idmap2/Policies.h
+++ b/cmds/idmap2/include/idmap2/Policies.h
@@ -27,13 +27,21 @@
namespace android::idmap2 {
+constexpr const char* kPolicyPublic = "public";
+constexpr const char* kPolicyProduct = "product";
+constexpr const char* kPolicySystem = "system";
+constexpr const char* kPolicyVendor = "vendor";
+constexpr const char* kPolicySignature = "signature";
+
using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags;
using PolicyBitmask = uint32_t;
-// Parses a the string representation of a set of policies into a bitmask. The format of the string
-// is the same as for the <policy> element.
+// Parses the string representations of policies into a bitmask.
Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies);
+// Retrieves the string representations of policies in the bitmask.
+std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask);
+
} // namespace android::idmap2
#endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 889d731..a7d180c 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -285,24 +285,58 @@
return std::move(idmap);
}
-bool CheckOverlayable(const LoadedPackage& target_package,
- const utils::OverlayManifestInfo& overlay_info,
- const PolicyBitmask& fulfilled_policies, const ResourceId& resid) {
+std::string ConcatPolicies(const std::vector<std::string>& policies) {
+ std::string message;
+ for (const std::string& policy : policies) {
+ if (message.empty()) {
+ message.append(policy);
+ } else {
+ message.append(policy);
+ message.append("|");
+ }
+ }
+
+ return message;
+}
+
+Result<Unit> CheckOverlayable(const LoadedPackage& target_package,
+ const utils::OverlayManifestInfo& overlay_info,
+ const PolicyBitmask& fulfilled_policies, const ResourceId& resid) {
+ static constexpr const PolicyBitmask sDefaultPolicies =
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION |
+ PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SIGNATURE;
+
+ // If the resource does not have an overlayable definition, allow the resource to be overlaid if
+ // the overlay is preinstalled or signed with the same signature as the target.
+ if (!target_package.DefinesOverlayable()) {
+ return (sDefaultPolicies & fulfilled_policies) != 0
+ ? Result<Unit>({})
+ : Error(
+ "overlay must be preinstalled or signed with the same signature as the "
+ "target");
+ }
+
const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid);
if (overlayable_info == nullptr) {
- // If the resource does not have an overlayable definition, allow the resource to be overlaid.
- // Once overlayable enforcement is turned on, this check will return false.
- return !target_package.DefinesOverlayable();
+ // Do not allow non-overlayable resources to be overlaid.
+ return Error("resource has no overlayable declaration");
}
if (overlay_info.target_name != overlayable_info->name) {
// If the overlay supplies a target overlayable name, the resource must belong to the
// overlayable defined with the specified name to be overlaid.
- return false;
+ return Error("<overlay> android:targetName '%s' does not match overlayable name '%s'",
+ overlay_info.target_name.c_str(), overlayable_info->name.c_str());
}
// Enforce policy restrictions if the resource is declared as overlayable.
- return (overlayable_info->policy_flags & fulfilled_policies) != 0;
+ if ((overlayable_info->policy_flags & fulfilled_policies) == 0) {
+ return Error("overlay with policies '%s' does not fulfill any overlayable policies '%s'",
+ ConcatPolicies(BitmaskToPolicies(fulfilled_policies)).c_str(),
+ ConcatPolicies(BitmaskToPolicies(overlayable_info->policy_flags)).c_str());
+ }
+
+ return Result<Unit>({});
}
std::unique_ptr<const Idmap> Idmap::FromApkAssets(
@@ -418,16 +452,26 @@
continue;
}
- if (enforce_overlayable &&
- !CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid)) {
- LOG(WARNING) << "overlay \"" << overlay_apk_path << "\" is not allowed to overlay resource \""
- << full_name << "\"" << std::endl;
- continue;
+ if (!enforce_overlayable) {
+ Result<Unit> success =
+ CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid);
+ if (!success) {
+ LOG(WARNING) << "overlay \"" << overlay_apk_path
+ << "\" is not allowed to overlay resource \"" << full_name
+ << "\": " << success.GetErrorMessage();
+ continue;
+ }
}
matching_resources.Add(target_resid, overlay_resid);
}
+ if (matching_resources.Map().empty()) {
+ out_error << "overlay \"" << overlay_apk_path << "\" does not successfully overlay any resource"
+ << std::endl;
+ return nullptr;
+ }
+
// encode idmap data
std::unique_ptr<IdmapData> data(new IdmapData());
const auto types_end = matching_resources.Map().cend();
diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp
index c6ba87d..7c45556 100644
--- a/cmds/idmap2/libidmap2/Policies.cpp
+++ b/cmds/idmap2/libidmap2/Policies.cpp
@@ -30,12 +30,13 @@
namespace {
const std::map<android::StringPiece, PolicyFlags> kStringToFlag = {
- {"public", PolicyFlags::POLICY_PUBLIC},
- {"product", PolicyFlags::POLICY_PRODUCT_PARTITION},
- {"system", PolicyFlags::POLICY_SYSTEM_PARTITION},
- {"vendor", PolicyFlags::POLICY_VENDOR_PARTITION},
- {"signature", PolicyFlags::POLICY_SIGNATURE},
+ {kPolicyPublic, PolicyFlags::POLICY_PUBLIC},
+ {kPolicyProduct, PolicyFlags::POLICY_PRODUCT_PARTITION},
+ {kPolicySystem, PolicyFlags::POLICY_SYSTEM_PARTITION},
+ {kPolicyVendor, PolicyFlags::POLICY_VENDOR_PARTITION},
+ {kPolicySignature, PolicyFlags::POLICY_SIGNATURE},
};
+
} // namespace
Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies) {
@@ -52,4 +53,29 @@
return Result<PolicyBitmask>(bitmask);
}
+std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) {
+ std::vector<std::string> policies;
+ if ((bitmask & PolicyFlags::POLICY_PUBLIC) != 0) {
+ policies.emplace_back(kPolicyPublic);
+ }
+
+ if ((bitmask & PolicyFlags::POLICY_PRODUCT_PARTITION) != 0) {
+ policies.emplace_back(kPolicyProduct);
+ }
+
+ if ((bitmask & PolicyFlags::POLICY_SYSTEM_PARTITION) != 0) {
+ policies.emplace_back(kPolicySystem);
+ }
+
+ if ((bitmask & PolicyFlags::POLICY_VENDOR_PARTITION) != 0) {
+ policies.emplace_back(kPolicyVendor);
+ }
+
+ if ((bitmask & PolicyFlags::POLICY_SIGNATURE) != 0) {
+ policies.emplace_back(kPolicySignature);
+ }
+
+ return policies;
+}
+
} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index bbfbad9..8d65428 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -173,20 +173,27 @@
ASSERT_THAT(idmap, IsNull());
}
-TEST(IdmapTests, CreateIdmapFromApkAssets) {
- const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path,
+ const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
+ std::unique_ptr<const Idmap>* out_idmap) {
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path.to_string());
ASSERT_THAT(target_apk, NotNull());
- const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string());
ASSERT_THAT(overlay_apk, NotNull());
std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
- PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
- ASSERT_THAT(idmap, NotNull());
+ *out_idmap =
+ Idmap::FromApkAssets(target_apk_path.to_string(), *target_apk, overlay_apk_path.to_string(),
+ *overlay_apk, fulfilled_policies, enforce_overlayable, error);
+}
+
+TEST(IdmapTests, CreateIdmapFromApkAssets) {
+ std::unique_ptr<const Idmap> idmap;
+ std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+ std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
+ CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, &idmap);
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
@@ -226,19 +233,12 @@
// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
- const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
-
- const std::string overlay_apk_path(GetTestDataPath() + "/system-overlay/system-overlay.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
-
- std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
- PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
- /* enforce_overlayable */ true, error);
+ std::unique_ptr<const Idmap> idmap;
+ std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+ std::string overlay_apk_path = GetTestDataPath() + "/system-overlay/system-overlay.apk";
+ CreateIdmap(target_apk_path, overlay_apk_path,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, &idmap);
ASSERT_THAT(idmap, NotNull());
const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -263,21 +263,12 @@
}
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
- const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
-
- const std::string overlay_apk_path(GetTestDataPath() +
- "/signature-overlay/signature-overlay.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
-
- uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE;
-
- std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
- policy_flags, /* enforce_overlayable */ true, error);
+ std::unique_ptr<const Idmap> idmap;
+ std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+ std::string overlay_apk_path = GetTestDataPath() + "/signature-overlay/signature-overlay.apk";
+ CreateIdmap(target_apk_path, overlay_apk_path,
+ PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE,
+ /* enforce_overlayable */ true, &idmap);
ASSERT_THAT(idmap, NotNull());
const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -298,52 +289,15 @@
ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_signature
}
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignatureNotFulfilled) {
- const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
-
- const std::string overlay_apk_path(GetTestDataPath() +
- "/signature-overlay/signature-overlay.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
-
- uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC;
-
- std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
- policy_flags, /* enforce_overlayable */ true, error);
- ASSERT_THAT(idmap, NotNull());
-
- const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
- ASSERT_EQ(dataBlocks.size(), 1U);
-
- const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
- ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
- ASSERT_EQ(data->GetHeader()->GetTypeCount(), 0U);
-
- const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
- ASSERT_EQ(types.size(), 0U); // can't overlay, so contains nothing
-}
-
// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
- const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
-
- const std::string overlay_apk_path(GetTestDataPath() +
- "/system-overlay-invalid/system-overlay-invalid.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
-
- std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
- PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
- /* enforce_overlayable */ true, error);
+ std::unique_ptr<const Idmap> idmap;
+ std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+ std::string overlay_apk_path =
+ GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+ CreateIdmap(target_apk_path, overlay_apk_path,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, &idmap);
ASSERT_THAT(idmap, NotNull());
const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -369,20 +323,13 @@
// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
- const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
-
- const std::string overlay_apk_path(GetTestDataPath() +
- "/system-overlay-invalid/system-overlay-invalid.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
-
- std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
- PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
- /* enforce_overlayable */ false, error);
+ std::unique_ptr<const Idmap> idmap;
+ std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+ std::string overlay_apk_path =
+ GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+ CreateIdmap(target_apk_path, overlay_apk_path,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ false, &idmap);
ASSERT_THAT(idmap, NotNull());
const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -409,63 +356,13 @@
ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
}
-// The resources of APKs that do not include an overlayable declaration should not restrict what
-// resources can be overlaid.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayable) {
- const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
-
- const std::string overlay_apk_path(GetTestDataPath() +
- "/system-overlay-invalid/system-overlay-invalid.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
-
- std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
- PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
- ASSERT_THAT(idmap, NotNull());
-
- const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
- ASSERT_EQ(dataBlocks.size(), 1U);
-
- const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
- ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
- ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
- const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
- ASSERT_EQ(types.size(), 1U);
-
- ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
- ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
- ASSERT_EQ(types[0]->GetEntryCount(), 7U);
- ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
- ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
- ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other
- ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product
- ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public
- ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/string/policy_signature
- ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system
- ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
-}
-
-// The resources of APKs that do not include an overlayable declaration should not restrict what
-// resources can be overlaid.
+// Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable.
TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
- const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
-
- const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay-no-name.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
-
- std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
- PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
+ std::unique_ptr<const Idmap> idmap;
+ std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+ std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
+ CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ false, &idmap);
ASSERT_THAT(idmap, NotNull());
const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -483,16 +380,81 @@
ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
ASSERT_EQ(types[0]->GetEntryCount(), 1U);
ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
- ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/int1
ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetEntryCount(), 4U);
ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
- ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
- ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
- ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
- ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
+ ASSERT_EQ(types[1]->GetEntry(0), 0x0000U); // string/str1
+ ASSERT_EQ(types[1]->GetEntry(1), kNoEntry); // string/str2
+ ASSERT_EQ(types[1]->GetEntry(2), 0x0001U); // string/str3
+ ASSERT_EQ(types[1]->GetEntry(3), 0x0002U); // string/str4
+}
+
+// Overlays that are not pre-installed and are not signed with the same signature as the target
+// cannot overlay packages that have not defined overlayable resources.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPoliciesPublicFail) {
+ std::unique_ptr<const Idmap> idmap;
+ std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+ std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
+ CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, &idmap);
+ ASSERT_THAT(idmap, IsNull());
+}
+
+// Overlays that are pre-installed or are signed with the same signature as the target can overlay
+// packages that have not defined overlayable resources.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) {
+ std::unique_ptr<const Idmap> idmap;
+ std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+ std::string overlay_apk_path =
+ GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+
+ auto CheckEntries = [&]() -> void {
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 1U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 7U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
+ ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product
+ ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public
+ ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/string/policy_signature
+ ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
+ };
+
+ CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE,
+ /* enforce_overlayable */ true, &idmap);
+ ASSERT_THAT(idmap, NotNull());
+ CheckEntries();
+
+ CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PRODUCT_PARTITION,
+ /* enforce_overlayable */ true, &idmap);
+ ASSERT_THAT(idmap, NotNull());
+ CheckEntries();
+
+ CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SYSTEM_PARTITION,
+ /* enforce_overlayable */ true, &idmap);
+ ASSERT_THAT(idmap, NotNull());
+ CheckEntries();
+
+ CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_VENDOR_PARTITION,
+ /* enforce_overlayable */ true, &idmap);
+ ASSERT_THAT(idmap, NotNull());
+ CheckEntries();
}
TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build
index e879f44..68b9f50 100755
--- a/cmds/idmap2/tests/data/overlay/build
+++ b/cmds/idmap2/tests/data/overlay/build
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-FRAMEWORK_RES_APK="${ANDROID_BUILD_TOP}/out/target/common/obj/APPS/framework-res_intermediates/package-export.apk"
+FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
aapt2 compile --dir res -o compiled.flata
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
index 7d23c09..6425190 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
Binary files differ
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index c067f9d..023371d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2018,7 +2018,8 @@
* @return {@code true} if a call to start an activity on the target display is allowed for the
* provided context and no {@link SecurityException} will be thrown, {@code false} otherwise.
*/
- public boolean isActivityStartAllowedOnDisplay(Context context, int displayId, Intent intent) {
+ public boolean isActivityStartAllowedOnDisplay(@NonNull Context context, int displayId,
+ @NonNull Intent intent) {
try {
return getTaskService().isActivityStartAllowedOnDisplay(displayId, intent,
intent.resolveTypeIfNeeded(context.getContentResolver()), context.getUserId());
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 010a900..ec2825e 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -136,7 +136,7 @@
* Returns the {@link ComponentName} of the activity that shows configuration options
* for this rule.
*/
- public ComponentName getConfigurationActivity() {
+ public @Nullable ComponentName getConfigurationActivity() {
return configurationActivity;
}
@@ -237,9 +237,10 @@
/**
* Sets the configuration activity - an activity that handles
* {@link NotificationManager#ACTION_AUTOMATIC_ZEN_RULE} that shows the user more information
- * about this rule and/or allows them to configure it.
+ * about this rule and/or allows them to configure it. This is required to be non-null for rules
+ * that are not backed by {@link android.service.notification.ConditionProviderService}.
*/
- public void setConfigurationActivity(ComponentName componentName) {
+ public void setConfigurationActivity(@Nullable ComponentName componentName) {
this.configurationActivity = componentName;
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index e1da08b..29e6807 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -192,7 +192,6 @@
ParceledListSlice getAppActiveNotifications(String callingPkg, int userId);
void setNotificationDelegate(String callingPkg, String delegate);
- void revokeNotificationDelegate(String callingPkg);
String getNotificationDelegate(String callingPkg);
boolean canNotifyAsPackage(String callingPkg, String targetPkg);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 03806fa..a8a34d2 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3177,6 +3177,7 @@
* Returns the bubble metadata that will be used to display app content in a floating window
* over the existing foreground activity.
*/
+ @Nullable
public BubbleMetadata getBubbleMetadata() {
return mBubbleMetadata;
}
@@ -3568,7 +3569,7 @@
* collapsed state, the bubble intent will be invoked and displayed.</b>
*/
@NonNull
- public Builder setBubbleMetadata(BubbleMetadata data) {
+ public Builder setBubbleMetadata(@Nullable BubbleMetadata data) {
mN.mBubbleMetadata = data;
return this;
}
@@ -8562,6 +8563,7 @@
/**
* @return the pending intent used to populate the floating window for this bubble.
*/
+ @NonNull
public PendingIntent getIntent() {
return mPendingIntent;
}
@@ -8569,6 +8571,7 @@
/**
* @return the pending intent to send when the bubble is dismissed by a user, if one exists.
*/
+ @Nullable
public PendingIntent getDeleteIntent() {
return mDeleteIntent;
}
@@ -8583,9 +8586,11 @@
public CharSequence getTitle() {
return "";
}
+
/**
* @return the icon that will be displayed for this bubble when it is collapsed.
*/
+ @NonNull
public Icon getIcon() {
return mIcon;
}
@@ -8654,7 +8659,7 @@
/**
* Builder to construct a {@link BubbleMetadata} object.
*/
- public static class Builder {
+ public static final class Builder {
private PendingIntent mPendingIntent;
private Icon mIcon;
@@ -8672,7 +8677,8 @@
* Sets the intent that will be used when the bubble is expanded. This will display the
* app content in a floating window over the existing foreground activity.
*/
- public BubbleMetadata.Builder setIntent(PendingIntent intent) {
+ @NonNull
+ public BubbleMetadata.Builder setIntent(@NonNull PendingIntent intent) {
if (intent == null) {
throw new IllegalArgumentException("Bubble requires non-null pending intent");
}
@@ -8700,7 +8706,8 @@
* If your app produces multiple bubbles, the image should be unique for each of them.
* </p>
*/
- public BubbleMetadata.Builder setIcon(Icon icon) {
+ @NonNull
+ public BubbleMetadata.Builder setIcon(@NonNull Icon icon) {
if (icon == null) {
throw new IllegalArgumentException("Bubbles require non-null icon");
}
@@ -8713,6 +8720,7 @@
* {@link #setIntent(PendingIntent)}, this height may not be respected if there is not
* enough space on the screen or if the provided height is too small to be useful.
*/
+ @NonNull
public BubbleMetadata.Builder setDesiredHeight(int height) {
mDesiredHeight = Math.max(height, 0);
return this;
@@ -8729,6 +8737,7 @@
* <p>Generally this flag should only be set if the user has performed an action to
* request or create a bubble.</p>
*/
+ @NonNull
public BubbleMetadata.Builder setAutoExpandBubble(boolean shouldExpand) {
setFlag(FLAG_AUTO_EXPAND_BUBBLE, shouldExpand);
return this;
@@ -8745,6 +8754,7 @@
* <p>Generally this flag should only be set if the user has performed an action to
* request or create a bubble.</p>
*/
+ @NonNull
public BubbleMetadata.Builder setSuppressInitialNotification(
boolean shouldSupressNotif) {
setFlag(FLAG_SUPPRESS_INITIAL_NOTIFICATION, shouldSupressNotif);
@@ -8754,7 +8764,8 @@
/**
* Sets an optional intent to send when this bubble is explicitly removed by the user.
*/
- public BubbleMetadata.Builder setDeleteIntent(PendingIntent deleteIntent) {
+ @NonNull
+ public BubbleMetadata.Builder setDeleteIntent(@Nullable PendingIntent deleteIntent) {
mDeleteIntent = deleteIntent;
return this;
}
@@ -8764,6 +8775,7 @@
* <p>Will throw {@link IllegalStateException} if required fields have not been set
* on this builder.</p>
*/
+ @NonNull
public BubbleMetadata build() {
if (mPendingIntent == null) {
throw new IllegalStateException("Must supply pending intent to bubble");
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index edf86f9..ed7aa4a 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -589,11 +589,11 @@
* received on your behalf from the cloud, without your process having to wake up.
*
* You can check if you have an allowed delegate with {@link #getNotificationDelegate()} and
- * revoke your delegate with {@link #revokeNotificationDelegate()}.
+ * revoke your delegate by passing null to this method.
*
* @param delegate Package name of the app which can send notifications on your behalf.
*/
- public void setNotificationDelegate(@NonNull String delegate) {
+ public void setNotificationDelegate(@Nullable String delegate) {
INotificationManager service = getService();
String pkg = mContext.getPackageName();
if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
@@ -605,20 +605,6 @@
}
/**
- * Revokes permission for your {@link #setNotificationDelegate(String) notification delegate}
- * to post notifications on your behalf.
- */
- public void revokeNotificationDelegate() {
- INotificationManager service = getService();
- String pkg = mContext.getPackageName();
- try {
- service.revokeNotificationDelegate(pkg);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Returns the {@link #setNotificationDelegate(String) delegate} that can post notifications on
* your behalf, if there currently is one.
*/
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 1faa2ac..90bc0a6 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -26,6 +26,7 @@
import android.app.job.IJobScheduler;
import android.app.job.JobScheduler;
import android.app.prediction.AppPredictionManager;
+import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.app.slice.SliceManager;
import android.app.timedetector.TimeDetector;
@@ -1243,6 +1244,14 @@
return new RoleManager(ctx.getOuterContext());
}});
+ registerService(Context.ROLE_CONTROLLER_SERVICE, RoleControllerManager.class,
+ new CachedServiceFetcher<RoleControllerManager>() {
+ @Override
+ public RoleControllerManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ return new RoleControllerManager(ctx.getOuterContext());
+ }});
+
registerService(Context.ROLLBACK_SERVICE, RollbackManager.class,
new CachedServiceFetcher<RollbackManager>() {
@Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 095d014..7cdd227 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -84,7 +84,6 @@
import android.service.restrictions.RestrictionsReceiver;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
-import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -2210,7 +2209,7 @@
PRIVATE_DNS_SET_ERROR_FAILURE_SETTING
})
@Retention(RetentionPolicy.SOURCE)
- public @interface SetPrivateDnsModeResultConstants {}
+ public @interface PrivateDnsModeErrorCodes {}
/**
* Activity action: Starts the administrator to get the mode for the provisioning.
@@ -10450,13 +10449,41 @@
}
/**
- * Sets the global Private DNS mode and host to be used.
+ * Sets the global Private DNS mode to opportunistic.
* May only be called by the device owner.
*
- * <p>Note that in case a Private DNS resolver is specified, the method is blocking as it
- * will perform a connectivity check to the resolver, to ensure it is valid. Because of that,
- * the method should not be called on any thread that relates to user interaction, such as the
- * UI thread.
+ * <p>In this mode, the DNS subsystem will attempt a TLS handshake to the network-supplied
+ * resolver prior to attempting name resolution in cleartext.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ *
+ * @return {@code PRIVATE_DNS_SET_SUCCESS} if the mode was set successfully, or
+ * {@code PRIVATE_DNS_SET_ERROR_FAILURE_SETTING} if it could not be set.
+ *
+ * @throws SecurityException if the caller is not the device owner.
+ */
+ public @PrivateDnsModeErrorCodes int setGlobalPrivateDnsModeOpportunistic(
+ @NonNull ComponentName admin) {
+ throwIfParentInstance("setGlobalPrivateDnsModeOpportunistic");
+
+ if (mService == null) {
+ return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
+ }
+
+ try {
+ return mService.setGlobalPrivateDns(admin, PRIVATE_DNS_MODE_OPPORTUNISTIC, null);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sets the global Private DNS host to be used.
+ * May only be called by the device owner.
+ *
+ * <p>Note that the method is blocking as it will perform a connectivity check to the resolver,
+ * to ensure it is valid. Because of that, the method should not be called on any thread that
+ * relates to user interaction, such as the UI thread.
*
* <p>In case a VPN is used in conjunction with Private DNS resolver, the Private DNS resolver
* must be reachable both from within and outside the VPN. Otherwise, the device may lose
@@ -10464,41 +10491,35 @@
* VPN.
*
* @param admin which {@link DeviceAdminReceiver} this request is associated with.
- * @param mode Which mode to set - either {@code PRIVATE_DNS_MODE_OPPORTUNISTIC} or
- * {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME}.
- * Since the opportunistic mode defaults to ordinary DNS lookups, the
- * option to turn it completely off is not available, so this method
- * may not be called with {@code PRIVATE_DNS_MODE_OFF}.
- * @param privateDnsHost The hostname of a server that implements DNS over TLS (RFC7858), if
- * {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} was specified as the mode,
- * null otherwise.
+ * @param privateDnsHost The hostname of a server that implements DNS over TLS (RFC7858).
*
- * @return One of the values in {@link SetPrivateDnsModeResultConstants}.
+ * @return {@code PRIVATE_DNS_SET_SUCCESS} if the mode was set successfully,
+ * {@code PRIVATE_DNS_SET_ERROR_FAILURE_SETTING} if it could not be set or
+ * {@code PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING} if the specified host does not
+ * implement RFC7858.
*
- * @throws IllegalArgumentException in the following cases: if a {@code privateDnsHost} was
- * provided but the mode was not {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME}, if the mode
- * specified was {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} but {@code privateDnsHost} does
- * not look like a valid hostname, or if the mode specified is not one of the two valid modes.
+ * @throws IllegalArgumentException if the {@code privateDnsHost} is not a valid hostname.
*
* @throws SecurityException if the caller is not the device owner.
*/
- public int setGlobalPrivateDns(@NonNull ComponentName admin,
- @PrivateDnsMode int mode, @Nullable String privateDnsHost) {
- throwIfParentInstance("setGlobalPrivateDns");
+ @WorkerThread public @PrivateDnsModeErrorCodes int setGlobalPrivateDnsModeSpecifiedHost(
+ @NonNull ComponentName admin, @NonNull String privateDnsHost) {
+ throwIfParentInstance("setGlobalPrivateDnsModeSpecifiedHost");
+ Preconditions.checkNotNull(privateDnsHost, "dns resolver is null");
if (mService == null) {
return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
}
- if (mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME && !TextUtils.isEmpty(privateDnsHost)
- && NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
+ if (NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
if (!PrivateDnsConnectivityChecker.canConnectToPrivateDnsServer(privateDnsHost)) {
return PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING;
}
}
try {
- return mService.setGlobalPrivateDns(admin, mode, privateDnsHost);
+ return mService.setGlobalPrivateDns(
+ admin, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, privateDnsHost);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/role/IRoleController.aidl b/core/java/android/app/role/IRoleController.aidl
new file mode 100644
index 0000000..a472eac
--- /dev/null
+++ b/core/java/android/app/role/IRoleController.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.role;
+
+import android.os.RemoteCallback;
+
+/**
+ * @hide
+ */
+oneway interface IRoleController {
+
+ void grantDefaultRoles(in RemoteCallback callback);
+
+ void onAddRoleHolder(in String roleName, in String packageName, int flags,
+ in RemoteCallback callback);
+
+ void onRemoveRoleHolder(in String roleName, in String packageName, int flags,
+ in RemoteCallback callback);
+
+ void onClearRoleHolders(in String roleName, int flags, in RemoteCallback callback);
+
+ void onSmsKillSwitchToggled(boolean enabled);
+
+ void isApplicationQualifiedForRole(in String roleName, in String packageName,
+ in RemoteCallback callback);
+
+ void isRoleVisible(in String roleName, in RemoteCallback callback);
+}
diff --git a/core/java/android/app/role/IRoleManager.aidl b/core/java/android/app/role/IRoleManager.aidl
index 76dbf7e..d8cea28 100644
--- a/core/java/android/app/role/IRoleManager.aidl
+++ b/core/java/android/app/role/IRoleManager.aidl
@@ -17,8 +17,8 @@
package android.app.role;
import android.app.role.IOnRoleHoldersChangedListener;
-import android.app.role.IRoleManagerCallback;
import android.os.Bundle;
+import android.os.RemoteCallback;
import android.telephony.IFinancialSmsCallback;
/**
@@ -33,13 +33,13 @@
List<String> getRoleHoldersAsUser(in String roleName, int userId);
void addRoleHolderAsUser(in String roleName, in String packageName, int flags, int userId,
- in IRoleManagerCallback callback);
+ in RemoteCallback callback);
void removeRoleHolderAsUser(in String roleName, in String packageName, int flags, int userId,
- in IRoleManagerCallback callback);
+ in RemoteCallback callback);
void clearRoleHoldersAsUser(in String roleName, int flags, int userId,
- in IRoleManagerCallback callback);
+ in RemoteCallback callback);
void addOnRoleHoldersChangedListenerAsUser(IOnRoleHoldersChangedListener listener, int userId);
@@ -55,6 +55,7 @@
List<String> getHeldRolesFromController(in String packageName);
String getDefaultSmsPackage(int userId);
+
/**
* Get filtered SMS messages for financial app.
*/
diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java
new file mode 100644
index 0000000..e96c9a5
--- /dev/null
+++ b/core/java/android/app/role/RoleControllerManager.java
@@ -0,0 +1,546 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.role;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
+import com.android.internal.infra.AbstractRemoteService;
+
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * Interface for communicating with the role controller.
+ *
+ * @hide
+ */
+@SystemService(Context.ROLE_CONTROLLER_SERVICE)
+public class RoleControllerManager {
+
+ private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();
+
+ private static final Object sRemoteServicesLock = new Object();
+ /**
+ * Global remote services (per user) used by all {@link RoleControllerManager managers}.
+ */
+ @GuardedBy("sRemoteServicesLock")
+ private static final SparseArray<RemoteService> sRemoteServices = new SparseArray<>();
+
+ @NonNull
+ private final RemoteService mRemoteService;
+
+ public RoleControllerManager(@NonNull Context context, @NonNull Handler handler) {
+ synchronized (sRemoteServicesLock) {
+ int userId = context.getUserId();
+ RemoteService remoteService = sRemoteServices.get(userId);
+ if (remoteService == null) {
+ Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
+ PackageManager packageManager = context.getPackageManager();
+ intent.setPackage(packageManager.getPermissionControllerPackageName());
+ ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
+
+ remoteService = new RemoteService(context.getApplicationContext(),
+ resolveInfo.getComponentInfo().getComponentName(), handler, userId);
+ sRemoteServices.put(userId, remoteService);
+ }
+ mRemoteService = remoteService;
+ }
+ }
+
+ public RoleControllerManager(@NonNull Context context) {
+ this(context, context.getMainThreadHandler());
+ }
+
+ /**
+ * @see RoleControllerService#onGrantDefaultRoles()
+ */
+ public void grantDefaultRoles(@NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> callback) {
+ mRemoteService.scheduleRequest(new GrantDefaultRolesRequest(mRemoteService, executor,
+ callback));
+ }
+
+ /**
+ * @see RoleControllerService#onAddRoleHolder(String, String, int)
+ */
+ public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
+ mRemoteService.scheduleRequest(new OnAddRoleHolderRequest(mRemoteService, roleName,
+ packageName, flags, callback));
+ }
+
+ /**
+ * @see RoleControllerService#onRemoveRoleHolder(String, String, int)
+ */
+ public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
+ mRemoteService.scheduleRequest(new OnRemoveRoleHolderRequest(mRemoteService, roleName,
+ packageName, flags, callback));
+ }
+
+ /**
+ * @see RoleControllerService#onClearRoleHolders(String, int)
+ */
+ public void onClearRoleHolders(@NonNull String roleName,
+ @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
+ mRemoteService.scheduleRequest(new OnClearRoleHoldersRequest(mRemoteService, roleName,
+ flags, callback));
+ }
+
+ /**
+ * @see RoleControllerService#onSmsKillSwitchToggled(boolean)
+ */
+ public void onSmsKillSwitchToggled(boolean enabled) {
+ mRemoteService.scheduleAsyncRequest(new OnSmsKillSwitchToggledRequest(enabled));
+ }
+
+ /**
+ * @see RoleControllerService#onIsApplicationQualifiedForRole(String, String)
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+ public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ mRemoteService.scheduleRequest(new IsApplicationQualifiedForRoleRequest(mRemoteService,
+ roleName, packageName, executor, callback));
+ }
+
+ /**
+ * @see RoleControllerService#onIsRoleVisible(String)
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+ public void isRoleVisible(@NonNull String roleName,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ mRemoteService.scheduleRequest(new IsRoleVisibleRequest(mRemoteService, roleName, executor,
+ callback));
+ }
+
+ /**
+ * Connection to the remote service.
+ */
+ private static final class RemoteService extends AbstractMultiplePendingRequestsRemoteService<
+ RemoteService, IRoleController> {
+
+ private static final long UNBIND_DELAY_MILLIS = 15 * 1000;
+ private static final long REQUEST_TIMEOUT_MILLIS = 15 * 1000;
+
+ /**
+ * Create a connection to the remote service
+ *
+ * @param context the context to use
+ * @param componentName the component of the service to connect to
+ * @param handler the handler for binding service and callbacks
+ * @param userId the user whom remote service should be connected as
+ */
+ RemoteService(@NonNull Context context, @NonNull ComponentName componentName,
+ @NonNull Handler handler, @UserIdInt int userId) {
+ super(context, RoleControllerService.SERVICE_INTERFACE, componentName, userId,
+ service -> Log.e(LOG_TAG, "RemoteService " + service + " died"), handler, false,
+ false, 1);
+ }
+
+ /**
+ * @return The default handler used by this service.
+ */
+ @NonNull
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ @Override
+ protected @NonNull IRoleController getServiceInterface(@NonNull IBinder binder) {
+ return IRoleController.Stub.asInterface(binder);
+ }
+
+ @Override
+ protected long getTimeoutIdleBindMillis() {
+ return UNBIND_DELAY_MILLIS;
+ }
+
+ @Override
+ protected long getRemoteRequestMillis() {
+ return REQUEST_TIMEOUT_MILLIS;
+ }
+
+ @Override
+ public void scheduleRequest(
+ @NonNull BasePendingRequest<RemoteService, IRoleController> pendingRequest) {
+ super.scheduleRequest(pendingRequest);
+ }
+
+ @Override
+ public void scheduleAsyncRequest(@NonNull AsyncRequest<IRoleController> request) {
+ super.scheduleAsyncRequest(request);
+ }
+ }
+
+ /**
+ * Request for {@link #grantDefaultRoles(Executor, Consumer)}.
+ */
+ private static final class GrantDefaultRolesRequest
+ extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
+
+ @NonNull
+ private final Executor mExecutor;
+ @NonNull
+ private final Consumer<Boolean> mCallback;
+
+ @NonNull
+ private final RemoteCallback mRemoteCallback;
+
+ private GrantDefaultRolesRequest(@NonNull RemoteService service,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ super(service);
+
+ mExecutor = executor;
+ mCallback = callback;
+
+ mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
+ boolean successful = result != null;
+ mCallback.accept(successful);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ finish();
+ }
+ }));
+ }
+
+ @Override
+ protected void onTimeout(@NonNull RemoteService remoteService) {
+ mExecutor.execute(() -> mCallback.accept(false));
+ }
+
+ @Override
+ public void run() {
+ try {
+ getService().getServiceInterface().grantDefaultRoles(mRemoteCallback);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Error calling grantDefaultRoles()", e);
+ }
+ }
+ }
+
+ /**
+ * Request for {@link #onAddRoleHolder(String, String, int, RemoteCallback)}.
+ */
+ private static final class OnAddRoleHolderRequest
+ extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
+
+ @NonNull
+ private final String mRoleName;
+ @NonNull
+ private final String mPackageName;
+ @RoleManager.ManageHoldersFlags
+ private final int mFlags;
+ @NonNull
+ private final RemoteCallback mCallback;
+
+ @NonNull
+ private final RemoteCallback mRemoteCallback;
+
+ private OnAddRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName,
+ @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags,
+ @NonNull RemoteCallback callback) {
+ super(service);
+
+ mRoleName = roleName;
+ mPackageName = packageName;
+ mFlags = flags;
+ mCallback = callback;
+
+ mRemoteCallback = new RemoteCallback(result -> {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mCallback.sendResult(result);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ finish();
+ }
+ });
+ }
+
+ @Override
+ protected void onTimeout(@NonNull RemoteService remoteService) {
+ mCallback.sendResult(null);
+ }
+
+ @Override
+ public void run() {
+ try {
+ getService().getServiceInterface().onAddRoleHolder(mRoleName, mPackageName, mFlags,
+ mRemoteCallback);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Error calling onAddRoleHolder()", e);
+ }
+ }
+ }
+
+ /**
+ * Request for {@link #onRemoveRoleHolder(String, String, int, RemoteCallback)}.
+ */
+ private static final class OnRemoveRoleHolderRequest
+ extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
+
+ @NonNull
+ private final String mRoleName;
+ @NonNull
+ private final String mPackageName;
+ @RoleManager.ManageHoldersFlags
+ private final int mFlags;
+ @NonNull
+ private final RemoteCallback mCallback;
+
+ @NonNull
+ private final RemoteCallback mRemoteCallback;
+
+ private OnRemoveRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName,
+ @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags,
+ @NonNull RemoteCallback callback) {
+ super(service);
+
+ mRoleName = roleName;
+ mPackageName = packageName;
+ mFlags = flags;
+ mCallback = callback;
+
+ mRemoteCallback = new RemoteCallback(result -> {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mCallback.sendResult(result);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ finish();
+ }
+ });
+ }
+
+ @Override
+ protected void onTimeout(@NonNull RemoteService remoteService) {
+ mCallback.sendResult(null);
+ }
+
+ @Override
+ public void run() {
+ try {
+ getService().getServiceInterface().onRemoveRoleHolder(mRoleName, mPackageName,
+ mFlags, mRemoteCallback);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Error calling onRemoveRoleHolder()", e);
+ }
+ }
+ }
+
+ /**
+ * Request for {@link #onClearRoleHolders(String, int, RemoteCallback)}.
+ */
+ private static final class OnClearRoleHoldersRequest
+ extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
+
+ @NonNull
+ private final String mRoleName;
+ @RoleManager.ManageHoldersFlags
+ private final int mFlags;
+ @NonNull
+ private final RemoteCallback mCallback;
+
+ @NonNull
+ private final RemoteCallback mRemoteCallback;
+
+ private OnClearRoleHoldersRequest(@NonNull RemoteService service, @NonNull String roleName,
+ @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
+ super(service);
+
+ mRoleName = roleName;
+ mFlags = flags;
+ mCallback = callback;
+
+ mRemoteCallback = new RemoteCallback(result -> {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mCallback.sendResult(result);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ finish();
+ }
+ });
+ }
+
+ @Override
+ protected void onTimeout(@NonNull RemoteService remoteService) {
+ mCallback.sendResult(null);
+ }
+
+ @Override
+ public void run() {
+ try {
+ getService().getServiceInterface().onClearRoleHolders(mRoleName, mFlags,
+ mRemoteCallback);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Error calling onClearRoleHolders()", e);
+ }
+ }
+ }
+
+ /**
+ * Request for {@link #onSmsKillSwitchToggled(boolean)}
+ */
+ private static final class OnSmsKillSwitchToggledRequest
+ implements AbstractRemoteService.AsyncRequest<IRoleController> {
+
+ private final boolean mEnabled;
+
+ private OnSmsKillSwitchToggledRequest(boolean enabled) {
+ mEnabled = enabled;
+ }
+
+ @Override
+ public void run(@NonNull IRoleController service) {
+ try {
+ service.onSmsKillSwitchToggled(mEnabled);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Error calling onSmsKillSwitchToggled()", e);
+ }
+ }
+ }
+
+ /**
+ * Request for {@link #isApplicationQualifiedForRole(String, String, Executor, Consumer)}
+ */
+ private static final class IsApplicationQualifiedForRoleRequest extends
+ AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
+
+ @NonNull
+ private final String mRoleName;
+ @NonNull
+ private final String mPackageName;
+ @NonNull
+ private final Executor mExecutor;
+ @NonNull
+ private final Consumer<Boolean> mCallback;
+
+ @NonNull
+ private final RemoteCallback mRemoteCallback;
+
+ private IsApplicationQualifiedForRoleRequest(@NonNull RemoteService service,
+ @NonNull String roleName, @NonNull String packageName,
+ @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
+ super(service);
+
+ mRoleName = roleName;
+ mPackageName = packageName;
+ mExecutor = executor;
+ mCallback = callback;
+
+ mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
+ boolean qualified = result != null;
+ mCallback.accept(qualified);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ finish();
+ }
+ }));
+ }
+
+ @Override
+ protected void onTimeout(RemoteService remoteService) {
+ mExecutor.execute(() -> mCallback.accept(false));
+ }
+
+ @Override
+ public void run() {
+ try {
+ getService().getServiceInterface().isApplicationQualifiedForRole(mRoleName,
+ mPackageName, mRemoteCallback);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Error calling isApplicationQualifiedForRole()", e);
+ }
+ }
+ }
+
+ /**
+ * Request for {@link #isRoleVisible(String, Executor, Consumer)}
+ */
+ private static final class IsRoleVisibleRequest
+ extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {
+
+ @NonNull
+ private final String mRoleName;
+ @NonNull
+ private final Executor mExecutor;
+ @NonNull
+ private final Consumer<Boolean> mCallback;
+
+ @NonNull
+ private final RemoteCallback mRemoteCallback;
+
+ private IsRoleVisibleRequest(@NonNull RemoteService service, @NonNull String roleName,
+ @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
+ super(service);
+
+ mRoleName = roleName;
+ mExecutor = executor;
+ mCallback = callback;
+
+ mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
+ boolean visible = result != null;
+ mCallback.accept(visible);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ finish();
+ }
+ }));
+ }
+
+ @Override
+ protected void onTimeout(RemoteService remoteService) {
+ mExecutor.execute(() -> mCallback.accept(false));
+ }
+
+ @Override
+ public void run() {
+ try {
+ getService().getServiceInterface().isRoleVisible(mRoleName, mRemoteCallback);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Error calling isRoleVisible()", e);
+ }
+ }
+ }
+}
diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java
new file mode 100644
index 0000000..312761d
--- /dev/null
+++ b/core/java/android/app/role/RoleControllerService.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.role;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.WorkerThread;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteCallback;
+import android.os.UserHandle;
+
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Abstract base class for the role controller service.
+ * <p>
+ * Subclass should implement the business logic for role management, including enforcing role
+ * requirements and granting or revoking relevant privileges of roles. This class can only be
+ * implemented by the permission controller app which is registered in {@code PackageManager}.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class RoleControllerService extends Service {
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ */
+ public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService";
+
+ private HandlerThread mWorkerThread;
+ private Handler mWorkerHandler;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ mWorkerThread = new HandlerThread(RoleControllerService.class.getSimpleName());
+ mWorkerThread.start();
+ mWorkerHandler = new Handler(mWorkerThread.getLooper());
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ mWorkerThread.quitSafely();
+ }
+
+ @Nullable
+ @Override
+ public final IBinder onBind(@Nullable Intent intent) {
+ return new IRoleController.Stub() {
+
+ @Override
+ public void grantDefaultRoles(RemoteCallback callback) {
+ enforceCallerSystemUid("grantDefaultRoles");
+
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
+ mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
+ RoleControllerService::grantDefaultRoles, RoleControllerService.this,
+ callback));
+ }
+
+ @Override
+ public void onAddRoleHolder(String roleName, String packageName, int flags,
+ RemoteCallback callback) {
+ enforceCallerSystemUid("onAddRoleHolder");
+
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkStringNotEmpty(packageName,
+ "packageName cannot be null or empty");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
+ mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
+ RoleControllerService::onAddRoleHolder, RoleControllerService.this,
+ roleName, packageName, flags, callback));
+ }
+
+ @Override
+ public void onRemoveRoleHolder(String roleName, String packageName, int flags,
+ RemoteCallback callback) {
+ enforceCallerSystemUid("onRemoveRoleHolder");
+
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkStringNotEmpty(packageName,
+ "packageName cannot be null or empty");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
+ mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
+ RoleControllerService::onRemoveRoleHolder, RoleControllerService.this,
+ roleName, packageName, flags, callback));
+ }
+
+ @Override
+ public void onClearRoleHolders(String roleName, int flags, RemoteCallback callback) {
+ enforceCallerSystemUid("onClearRoleHolders");
+
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
+ mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
+ RoleControllerService::onClearRoleHolders, RoleControllerService.this,
+ roleName, flags, callback));
+ }
+
+ @Override
+ public void onSmsKillSwitchToggled(boolean enabled) {
+ enforceCallerSystemUid("onSmsKillSwitchToggled");
+
+ mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
+ RoleControllerService::onSmsKillSwitchToggled, RoleControllerService.this,
+ enabled));
+ }
+
+ private void enforceCallerSystemUid(@NonNull String methodName) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Only the system process can call " + methodName
+ + "()");
+ }
+ }
+
+ @Override
+ public void isApplicationQualifiedForRole(String roleName, String packageName,
+ RemoteCallback callback) {
+ enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
+
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkStringNotEmpty(packageName,
+ "packageName cannot be null or empty");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
+ boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName);
+ callback.sendResult(qualified ? Bundle.EMPTY : null);
+ }
+
+ @Override
+ public void isRoleVisible(String roleName, RemoteCallback callback) {
+ enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
+
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
+ boolean visible = onIsRoleVisible(roleName);
+ callback.sendResult(visible ? Bundle.EMPTY : null);
+ }
+ };
+ }
+
+ private void grantDefaultRoles(@NonNull RemoteCallback callback) {
+ boolean successful = onGrantDefaultRoles();
+ callback.sendResult(successful ? Bundle.EMPTY : null);
+ }
+
+ private void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
+ boolean successful = onAddRoleHolder(roleName, packageName, flags);
+ callback.sendResult(successful ? Bundle.EMPTY : null);
+ }
+
+ private void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
+ boolean successful = onRemoveRoleHolder(roleName, packageName, flags);
+ callback.sendResult(successful ? Bundle.EMPTY : null);
+ }
+
+ private void onClearRoleHolders(@NonNull String roleName,
+ @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) {
+ boolean successful = onClearRoleHolders(roleName, flags);
+ callback.sendResult(successful ? Bundle.EMPTY : null);
+ }
+
+ /**
+ * Called by system to grant default permissions and roles.
+ * <p>
+ * This is typically when creating a new user or upgrading either system or
+ * permission controller package
+ *
+ * @return whether this call was successful
+ */
+ @WorkerThread
+ public abstract boolean onGrantDefaultRoles();
+
+ /**
+ * Add a specific application to the holders of a role. If the role is exclusive, the previous
+ * holder will be replaced.
+ * <p>
+ * Implementation should enforce the role requirements and grant or revoke the relevant
+ * privileges of roles.
+ *
+ * @param roleName the name of the role to add the role holder for
+ * @param packageName the package name of the application to add to the role holders
+ * @param flags optional behavior flags
+ *
+ * @return whether this call was successful
+ *
+ * @see RoleManager#addRoleHolderAsUser(String, String, int, UserHandle, Executor,
+ * RemoteCallback)
+ */
+ @WorkerThread
+ public abstract boolean onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ @RoleManager.ManageHoldersFlags int flags);
+
+ /**
+ * Remove a specific application from the holders of a role.
+ *
+ * @param roleName the name of the role to remove the role holder for
+ * @param packageName the package name of the application to remove from the role holders
+ * @param flags optional behavior flags
+ *
+ * @return whether this call was successful
+ *
+ * @see RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, Executor,
+ * RemoteCallback)
+ */
+ @WorkerThread
+ public abstract boolean onRemoveRoleHolder(@NonNull String roleName,
+ @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags);
+
+ /**
+ * Remove all holders of a role.
+ *
+ * @param roleName the name of the role to remove role holders for
+ * @param flags optional behavior flags
+ *
+ * @return whether this call was successful
+ *
+ * @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor, RemoteCallback)
+ */
+ @WorkerThread
+ public abstract boolean onClearRoleHolders(@NonNull String roleName,
+ @RoleManager.ManageHoldersFlags int flags);
+
+ /**
+ * Cleanup appop/permissions state in response to sms kill switch toggle
+ *
+ * @param enabled whether kill switch was turned on
+ *
+ * @hide
+ */
+ //STOPSHIP: remove this api before shipping a final version
+ @WorkerThread
+ public abstract void onSmsKillSwitchToggled(boolean enabled);
+
+ /**
+ * Check whether an application is qualified for a role.
+ *
+ * @param roleName name of the role to check for
+ * @param packageName package name of the application to check for
+ *
+ * @return whether the application is qualified for the role
+ */
+ public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
+ @NonNull String packageName);
+
+ /**
+ * Check whether a role should be visible to user.
+ *
+ * @param roleName name of the role to check for
+ *
+ * @return whether the role should be visible to user
+ */
+ public abstract boolean onIsRoleVisible(@NonNull String roleName);
+}
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index f91d878..d1f8ed2 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -30,6 +30,7 @@
import android.content.Intent;
import android.os.Binder;
import android.os.Process;
+import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -42,6 +43,7 @@
import java.util.List;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* This class provides information about and manages roles.
@@ -315,9 +317,9 @@
*
* @return a list of package names of the role holders, or an empty list if none.
*
- * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
- * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
- * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, RoleManagerCallback)
+ * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
+ * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
+ * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer)
*
* @hide
*/
@@ -351,8 +353,8 @@
* @param callback the callback for whether this call is successful
*
* @see #getRoleHoldersAsUser(String, UserHandle)
- * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
- * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, RoleManagerCallback)
+ * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
+ * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer)
*
* @hide
*/
@@ -361,7 +363,7 @@
@TestApi
public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@ManageHoldersFlags int flags, @NonNull UserHandle user,
- @CallbackExecutor @NonNull Executor executor, @NonNull RoleManagerCallback callback) {
+ @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Preconditions.checkNotNull(user, "user cannot be null");
@@ -369,7 +371,7 @@
Preconditions.checkNotNull(callback, "callback cannot be null");
try {
mService.addRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(),
- new RoleManagerCallbackDelegate(executor, callback));
+ createRemoteCallback(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -390,8 +392,8 @@
* @param callback the callback for whether this call is successful
*
* @see #getRoleHoldersAsUser(String, UserHandle)
- * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
- * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, RoleManagerCallback)
+ * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
+ * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer)
*
* @hide
*/
@@ -400,7 +402,7 @@
@TestApi
public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@ManageHoldersFlags int flags, @NonNull UserHandle user,
- @CallbackExecutor @NonNull Executor executor, @NonNull RoleManagerCallback callback) {
+ @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Preconditions.checkNotNull(user, "user cannot be null");
@@ -408,7 +410,7 @@
Preconditions.checkNotNull(callback, "callback cannot be null");
try {
mService.removeRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(),
- new RoleManagerCallbackDelegate(executor, callback));
+ createRemoteCallback(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -428,8 +430,8 @@
* @param callback the callback for whether this call is successful
*
* @see #getRoleHoldersAsUser(String, UserHandle)
- * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
- * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, RoleManagerCallback)
+ * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
+ * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer)
*
* @hide
*/
@@ -438,19 +440,33 @@
@TestApi
public void clearRoleHoldersAsUser(@NonNull String roleName, @ManageHoldersFlags int flags,
@NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor,
- @NonNull RoleManagerCallback callback) {
+ @NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkNotNull(user, "user cannot be null");
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
try {
mService.clearRoleHoldersAsUser(roleName, flags, user.getIdentifier(),
- new RoleManagerCallbackDelegate(executor, callback));
+ createRemoteCallback(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
+ @NonNull
+ private static RemoteCallback createRemoteCallback(@NonNull Executor executor,
+ @NonNull Consumer<Boolean> callback) {
+ return new RemoteCallback(result -> executor.execute(() -> {
+ boolean successful = result != null;
+ long token = Binder.clearCallingIdentity();
+ try {
+ callback.accept(successful);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }));
+ }
+
/**
* Add a listener to observe role holder changes
* <p>
@@ -545,7 +561,7 @@
/**
* Set the names of all the available roles. Should only be called from
- * {@link android.rolecontrollerservice.RoleControllerService}.
+ * {@link android.app.role.RoleControllerService}.
* <p>
* <strong>Note:</strong> Using this API requires holding
* {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}.
@@ -569,7 +585,7 @@
/**
* Add a specific application to the holders of a role, only modifying records inside
* {@link RoleManager}. Should only be called from
- * {@link android.rolecontrollerservice.RoleControllerService}.
+ * {@link android.app.role.RoleControllerService}.
* <p>
* <strong>Note:</strong> Using this API requires holding
* {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}.
@@ -602,7 +618,7 @@
/**
* Remove a specific application from the holders of a role, only modifying records inside
* {@link RoleManager}. Should only be called from
- * {@link android.rolecontrollerservice.RoleControllerService}.
+ * {@link android.app.role.RoleControllerService}.
* <p>
* <strong>Note:</strong> Using this API requires holding
* {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}.
@@ -669,40 +685,6 @@
}
}
- private static class RoleManagerCallbackDelegate extends IRoleManagerCallback.Stub {
-
- @NonNull
- private final Executor mExecutor;
- @NonNull
- private final RoleManagerCallback mCallback;
-
- RoleManagerCallbackDelegate(@NonNull Executor executor,
- @NonNull RoleManagerCallback callback) {
- mExecutor = executor;
- mCallback = callback;
- }
-
- @Override
- public void onSuccess() {
- long token = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(mCallback::onSuccess);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void onFailure() {
- long token = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(mCallback::onFailure);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-
private static class OnRoleHoldersChangedListenerDelegate
extends IOnRoleHoldersChangedListener.Stub {
diff --git a/core/java/android/app/role/RoleManagerCallback.java b/core/java/android/app/role/RoleManagerCallback.java
deleted file mode 100644
index a92ef32..0000000
--- a/core/java/android/app/role/RoleManagerCallback.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.role;
-
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
-
-import java.util.concurrent.CompletableFuture;
-
-/**
- * Callback for a {@link RoleManager} request.
- *
- * @hide
- */
-@SystemApi
-@TestApi
-public interface RoleManagerCallback {
-
- /**
- * Signals a success.
- */
- void onSuccess();
-
- /**
- * Signals a failure.
- */
- void onFailure();
-
- /** @hide */
- class Future extends CompletableFuture<Void> implements RoleManagerCallback {
-
- @Override
- public void onSuccess() {
- complete(null);
- }
-
- @Override
- public void onFailure() {
- completeExceptionally(new RuntimeException());
- }
- }
-}
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 0d0e466..b3d01fd 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -254,18 +254,32 @@
public static final int FLUSH_TO_DISK = 25;
/**
- * An event type denoting that the device underwent a shutdown process.
+ * An event type denoting that the Android runtime underwent a shutdown process.
* A DEVICE_SHUTDOWN event should be treated as if all started activities and foreground
* services are now stopped and no explicit {@link #ACTIVITY_STOPPED} and
* {@link #FOREGROUND_SERVICE_STOP} events will be generated for them.
+ *
+ * <p>The DEVICE_SHUTDOWN timestamp is actually the last time UsageStats database is
+ * persisted before the actual shutdown. Events (if there are any) between this timestamp
+ * and the actual shutdown is not persisted in the database. So any open events without
+ * matching close events between DEVICE_SHUTDOWN and {@link #DEVICE_STARTUP} should be
+ * ignored because the closing time is unknown.</p>
*/
public static final int DEVICE_SHUTDOWN = 26;
/**
+ * An event type denoting that the Android runtime started up. This could be after a
+ * shutdown or a runtime restart. Any open events without matching close events between
+ * {@link #DEVICE_SHUTDOWN} and DEVICE_STARTUP should be ignored because the closing time is
+ * unknown.
+ */
+ public static final int DEVICE_STARTUP = 27;
+
+ /**
* Keep in sync with the greatest event type value.
* @hide
*/
- public static final int MAX_EVENT_TYPE = 26;
+ public static final int MAX_EVENT_TYPE = 27;
/** @hide */
public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 8eae2b4..58b6aea 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -75,8 +75,8 @@
* @param c2 the second array of capabilities to compare
* @return true if both arrays contain same capabilities
*/
- private static boolean sameCapabilities(BluetoothCodecConfig[] c1,
- BluetoothCodecConfig[] c2) {
+ public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
+ BluetoothCodecConfig[] c2) {
if (c1 == null) {
return (c2 == null);
}
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 82cc1bc..b4eaab2 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -303,7 +304,7 @@
* {@inheritDoc}
*/
@Override
- public List<BluetoothDevice> getConnectedDevices() {
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
try {
mServiceLock.readLock().lock();
@@ -323,8 +324,8 @@
/**
* {@inheritDoc}
*/
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ @Override public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ @NonNull int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
try {
mServiceLock.readLock().lock();
@@ -345,7 +346,7 @@
* {@inheritDoc}
*/
@Override
- public int getConnectionState(BluetoothDevice device) {
+ public int getConnectionState(@NonNull BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
try {
mServiceLock.readLock().lock();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f28718c..f896274 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3176,6 +3176,7 @@
RESTRICTIONS_SERVICE,
APP_OPS_SERVICE,
ROLE_SERVICE,
+ //@hide ROLE_CONTROLLER_SERVICE,
CAMERA_SERVICE,
PRINT_SERVICE,
CONSUMER_IR_SERVICE,
@@ -4285,6 +4286,16 @@
public static final String ROLE_SERVICE = "role";
/**
+ * Official published name of the (internal) role controller service.
+ *
+ * @see #getSystemService(String)
+ * @see android.app.role.RoleControllerService
+ *
+ * @hide
+ */
+ public static final String ROLE_CONTROLLER_SERVICE = "role_controller";
+
+ /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.camera2.CameraManager} for interacting with
* camera devices.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 4f09d5a..706cbbf 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -43,6 +43,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.text.Collator;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
@@ -2028,6 +2029,27 @@
return this;
}
+ /**
+ * Return all the APK paths that may be required to load this application, including all
+ * splits, shared libraries, and resource overlays.
+ * @hide
+ */
+ public String[] getAllApkPaths() {
+ final String[][] inputLists = { splitSourceDirs, sharedLibraryFiles, resourceDirs };
+ final List<String> output = new ArrayList<>(10);
+ if (sourceDir != null) {
+ output.add(sourceDir);
+ }
+ for (String[] inputList : inputLists) {
+ if (inputList != null) {
+ for (String input : inputList) {
+ output.add(input);
+ }
+ }
+ }
+ return output.toArray(new String[output.size()]);
+ }
+
/** {@hide} */ public void setCodePath(String codePath) { scanSourceDir = codePath; }
/** {@hide} */ public void setBaseCodePath(String baseCodePath) { sourceDir = baseCodePath; }
/** {@hide} */ public void setSplitCodePaths(String[] splitCodePaths) { splitSourceDirs = splitCodePaths; }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 7de8105..7b4dd19 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1342,8 +1342,8 @@
* @hide
*/
public boolean areHiddenOptionsSet() {
- return (installFlags & (PackageManager.INSTALL_ALLOW_DOWNGRADE
- | PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE
+ return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE
+ | PackageManager.INSTALL_ALLOW_DOWNGRADE
| PackageManager.INSTALL_DONT_KILL_APP
| PackageManager.INSTALL_INSTANT_APP
| PackageManager.INSTALL_FULL_APP
@@ -1448,20 +1448,49 @@
/**
* Request that rollbacks be enabled for the given upgrade.
+ *
+ * @removed
+ * @deprecated use {@link #setEnableRollback(boolean)} instead.
* @hide
*/
+ @Deprecated
@SystemApi
public void setEnableRollback() {
installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
}
+ /**
+ * Request that rollbacks be enabled or disabled for the given upgrade.
+ *
+ * @param enable set to {@code true} to enable, {@code false} to disable
+ * @hide
+ */
+ @SystemApi
+ public void setEnableRollback(boolean enable) {
+ if (enable) {
+ installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
+ } else {
+ installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
+ }
+ }
+
+ /**
+ * @deprecated use {@link #setRequestDowngrade(boolean)}.
+ * {@hide}
+ */
+ @SystemApi
+ @Deprecated
+ public void setAllowDowngrade(boolean allowDowngrade) {
+ setRequestDowngrade(allowDowngrade);
+ }
+
/** {@hide} */
@SystemApi
- public void setAllowDowngrade(boolean allowDowngrade) {
- if (allowDowngrade) {
- installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
+ public void setRequestDowngrade(boolean requestDowngrade) {
+ if (requestDowngrade) {
+ installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
} else {
- installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;
+ installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
}
}
@@ -1982,11 +2011,23 @@
/**
* Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
*
+ * @deprecated use {@link #getRequestDowngrade()}.
* @hide
*/
@SystemApi
+ @Deprecated
public boolean getAllowDowngrade() {
- return (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+ return getRequestDowngrade();
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getRequestDowngrade() {
+ return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
}
/**
@@ -2036,6 +2077,16 @@
}
/**
+ * Return whether rollback is enabled or disabled for the given upgrade.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getEnableRollback() {
+ return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
+ }
+
+ /**
* Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
*
* @hide
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c133fba..d1ebcfd 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -710,7 +710,7 @@
INSTALL_INTERNAL,
INSTALL_FROM_ADB,
INSTALL_ALL_USERS,
- INSTALL_ALLOW_DOWNGRADE,
+ INSTALL_REQUEST_DOWNGRADE,
INSTALL_GRANT_RUNTIME_PERMISSIONS,
INSTALL_FORCE_VOLUME_UUID,
INSTALL_FORCE_PERMISSION_PROMPT,
@@ -721,7 +721,7 @@
INSTALL_VIRTUAL_PRELOAD,
INSTALL_APEX,
INSTALL_ENABLE_ROLLBACK,
- INSTALL_RESPECT_ALLOW_DOWNGRADE,
+ INSTALL_ALLOW_DOWNGRADE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -768,14 +768,21 @@
public static final int INSTALL_ALL_USERS = 0x00000040;
/**
- * Flag parameter for {@link #installPackage} to indicate that it is okay
- * to install an update to an app where the newly installed app has a lower
- * version code than the currently installed app. This is permitted only if
- * the currently installed app is marked debuggable.
+ * Flag parameter for {@link #installPackage} to indicate that an upgrade to a lower version
+ * of a package than currently installed has been requested.
+ *
+ * <p>Note that this flag doesn't guarantee that downgrade will be performed. That decision
+ * depends
+ * on whenever:
+ * <ul>
+ * <li>An app is debuggable.
+ * <li>Or a build is debuggable.
+ * <li>Or {@link #INSTALL_ALLOW_DOWNGRADE} is set.
+ * </ul>
*
* @hide
*/
- public static final int INSTALL_ALLOW_DOWNGRADE = 0x00000080;
+ public static final int INSTALL_REQUEST_DOWNGRADE = 0x00000080;
/**
* Flag parameter for {@link #installPackage} to indicate that all runtime
@@ -868,12 +875,11 @@
/**
* Flag parameter for {@link #installPackage} to indicate that
- * {@link #INSTALL_ALLOW_DOWNGRADE} should be respected.
+ * {@link #INSTALL_REQUEST_DOWNGRADE} should be allowed.
*
* @hide
*/
- // TODO(b/127322579): rename
- public static final int INSTALL_RESPECT_ALLOW_DOWNGRADE = 0x00100000;
+ public static final int INSTALL_ALLOW_DOWNGRADE = 0x00100000;
/** @hide */
@IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = {
@@ -3041,14 +3047,44 @@
public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 1 << 7;
/**
- * Mask for all permission flags.
+ * Permission flag: The permission's usage should be made highly visible to the user
+ * when granted.
*
* @hide
*/
@SystemApi
+ public static final int FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED = 1 << 8;
+
+ /**
+ * Permission flag: The permission's usage should be made highly visible to the user
+ * when denied.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED = 1 << 9;
+
+ /**
+ * Mask for all permission flags present in Android P
+ *
+ * @deprecated This constant does not contain useful information and should never have been
+ * exposed. When checking permission flags always flag each flag explicitly and ignore all
+ * flags that do not matter for this particular code.
+ *
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
public static final int MASK_PERMISSION_FLAGS = 0xFF;
/**
+ * Mask for all permission flags.
+ *
+ * @hide
+ */
+ public static final int MASK_PERMISSION_FLAGS_ALL = 0x3FF;
+
+ /**
* Injected activity in app that forwards user to setting activity of that app.
*
* @hide
@@ -3755,6 +3791,8 @@
FLAG_PERMISSION_REVOKE_ON_UPGRADE,
FLAG_PERMISSION_SYSTEM_FIXED,
FLAG_PERMISSION_GRANTED_BY_DEFAULT,
+ FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED,
+ FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED,
/*
FLAG_PERMISSION_REVOKE_WHEN_REQUESED
*/
@@ -3829,7 +3867,8 @@
@TestApi
@RequiresPermission(anyOf = {
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
- android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+ android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ android.Manifest.permission.GET_RUNTIME_PERMISSIONS
})
public abstract @PermissionFlags int getPermissionFlags(String permissionName,
String packageName, @NonNull UserHandle user);
@@ -6542,6 +6581,8 @@
case FLAG_PERMISSION_USER_FIXED: return "USER_FIXED";
case FLAG_PERMISSION_REVIEW_REQUIRED: return "REVIEW_REQUIRED";
case FLAG_PERMISSION_REVOKE_WHEN_REQUESTED: return "REVOKE_WHEN_REQUESTED";
+ case FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED: return "USER_SENSITIVE_WHEN_GRANTED";
+ case FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED: return "USER_SENSITIVE_WHEN_DENIED";
default: return Integer.toString(flag);
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index c4a574a..89c0690 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1843,7 +1843,8 @@
}
}
- final boolean extractNativeLibsDefault = targetSdkVersion < Build.VERSION_CODES.Q;
+ // TODO: flip the default based on targetSdkVersion when possible. See b/128335904.
+ final boolean extractNativeLibsDefault = true;
final boolean extractNativeLibs = (extractNativeLibsProvided != null)
? extractNativeLibsProvided : extractNativeLibsDefault;
@@ -3718,11 +3719,10 @@
ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
}
- final boolean extractNativeLibsDefault =
- owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q;
+ // TODO: flip the default based on targetSdkVersion when possible. See b/128335904.
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
- extractNativeLibsDefault)) {
+ true)) {
ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c855d45..6729242 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1396,9 +1396,11 @@
/**
+ * Returns the resource ID of the resource that was used to create this AttributeSet.
+ *
* @param set AttributeSet for which we want to find the source.
- * @return The resource id for the source that is backing the given AttributeSet
- * @hide
+ * @return The resource ID for the source that is backing the given AttributeSet or
+ * {@link Resources#ID_NULL} if the AttributeSet is {@code null}.
*/
@AnyRes
public static int getAttributeSetSourceResId(@Nullable AttributeSet set) {
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 565cd33..633966c 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1303,7 +1303,7 @@
@AnyRes
static int getAttributeSetSourceResId(@Nullable AttributeSet set) {
- if (set == null) {
+ if (set == null || !(set instanceof XmlBlock.Parser)) {
return ID_NULL;
}
return ((XmlBlock.Parser) set).getSourceResId();
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index d36e076..b79cf65 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -19,7 +19,6 @@
import android.annotation.AnyRes;
import android.annotation.ColorInt;
import android.annotation.Nullable;
-import android.annotation.StyleRes;
import android.annotation.StyleableRes;
import android.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
@@ -72,7 +71,7 @@
static final int STYLE_RESOURCE_ID = 3;
static final int STYLE_CHANGING_CONFIGURATIONS = 4;
static final int STYLE_DENSITY = 5;
- static final int SYTLE_SOURCE_RESOURCE_ID = 6;
+ static final int STYLE_SOURCE_RESOURCE_ID = 6;
@UnsupportedAppUsage
private final Resources mResources;
@@ -1134,14 +1133,14 @@
* resolved in a style or layout.
* @throws RuntimeException if the TypedArray has already been recycled.
*/
- @StyleRes
- public int getSourceResourceId(@StyleableRes int index, @StyleRes int defaultValue) {
+ @AnyRes
+ public int getSourceResourceId(@StyleableRes int index, @AnyRes int defaultValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= STYLE_NUM_ENTRIES;
- final int resid = mData[index + SYTLE_SOURCE_RESOURCE_ID];
+ final int resid = mData[index + STYLE_SOURCE_RESOURCE_ID];
if (resid != 0) {
return resid;
}
@@ -1360,7 +1359,7 @@
data[index + STYLE_CHANGING_CONFIGURATIONS]);
outValue.density = data[index + STYLE_DENSITY];
outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
- outValue.sourceResourceId = data[index + SYTLE_SOURCE_RESOURCE_ID];
+ outValue.sourceResourceId = data[index + STYLE_SOURCE_RESOURCE_ID];
return true;
}
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 03810f5..c0414fc 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -89,6 +89,7 @@
/**
* Returns the name of the package to roll back from.
*/
+ @NonNull
public String getPackageName() {
return mVersionRolledBackFrom.getPackageName();
}
@@ -96,6 +97,7 @@
/**
* Returns the version of the package rolled back from.
*/
+ @NonNull
public VersionedPackage getVersionRolledBackFrom() {
return mVersionRolledBackFrom;
}
@@ -103,6 +105,7 @@
/**
* Returns the version of the package rolled back to.
*/
+ @NonNull
public VersionedPackage getVersionRolledBackTo() {
return mVersionRolledBackTo;
}
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index 29b99e0..a363718 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -16,6 +16,7 @@
package android.content.rollback;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.pm.VersionedPackage;
import android.os.Parcel;
@@ -72,6 +73,7 @@
/**
* Returns the list of package that are rolled back.
*/
+ @NonNull
public List<PackageRollbackInfo> getPackages() {
return mPackages;
}
@@ -105,6 +107,7 @@
* As provided to {@link #commitRollback} when the rollback was committed.
* This is only applicable for rollbacks that have been committed.
*/
+ @NonNull
public List<VersionedPackage> getCausePackages() {
return mCausePackages;
}
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index c043491..4e8c254 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -57,6 +57,7 @@
* MANAGE_ROLLBACKS permission.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+ @NonNull
public List<RollbackInfo> getAvailableRollbacks() {
try {
return mBinder.getAvailableRollbacks().getList();
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index ac863b2..81abdea0 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1174,6 +1174,7 @@
{
private final Camera mCamera;
+ @UnsupportedAppUsage
public EventHandler(Camera c, Looper looper) {
super(looper);
mCamera = c;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 0497f8c..fb0821e 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -56,6 +56,7 @@
import android.util.Log;
import android.util.SparseIntArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.Preconditions;
@@ -2542,6 +2543,94 @@
}
/**
+ * Callback for use with {@link registerTetheringEventCallback} to find out tethering
+ * upstream status.
+ *
+ *@hide
+ */
+ @SystemApi
+ public abstract static class OnTetheringEventCallback {
+
+ /**
+ * Called when tethering upstream changed. This can be called multiple times and can be
+ * called any time.
+ *
+ * @param network the {@link Network} of tethering upstream. Null means tethering doesn't
+ * have any upstream.
+ */
+ public void onUpstreamChanged(@Nullable Network network) {}
+ }
+
+ @GuardedBy("mTetheringEventCallbacks")
+ private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
+ mTetheringEventCallbacks = new ArrayMap<>();
+
+ /**
+ * Start listening to tethering change events. Any new added callback will receive the last
+ * tethering status right away. If callback is registered when tethering loses its upstream or
+ * disabled, {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called
+ * with a null argument. The same callback object cannot be registered twice.
+ *
+ * @param executor the executor on which callback will be invoked.
+ * @param callback the callback to be called when tethering has change events.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+ public void registerTetheringEventCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull final OnTetheringEventCallback callback) {
+ Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
+
+ synchronized (mTetheringEventCallbacks) {
+ Preconditions.checkArgument(!mTetheringEventCallbacks.containsKey(callback),
+ "callback was already registered.");
+ ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
+ @Override
+ public void onUpstreamChanged(Network network) throws RemoteException {
+ Binder.withCleanCallingIdentity(() ->
+ executor.execute(() -> {
+ callback.onUpstreamChanged(network);
+ }));
+ }
+ };
+ try {
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "registerTetheringUpstreamCallback:" + pkgName);
+ mService.registerTetheringEventCallback(remoteCallback, pkgName);
+ mTetheringEventCallbacks.put(callback, remoteCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Remove tethering event callback previously registered with
+ * {@link #registerTetheringEventCallback}.
+ *
+ * @param callback previously registered callback.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+ public void unregisterTetheringEventCallback(
+ @NonNull final OnTetheringEventCallback callback) {
+ synchronized (mTetheringEventCallbacks) {
+ ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
+ Preconditions.checkNotNull(remoteCallback, "callback was not registered.");
+ try {
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName);
+ mService.unregisterTetheringEventCallback(remoteCallback, pkgName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+
+ /**
* Get the list of regular expressions that define any tetherable
* USB network interfaces. If USB tethering is not supported by the
* device, this list should be empty.
diff --git a/core/java/android/net/DnsPacket.java b/core/java/android/net/DnsPacket.java
index 458fb34..0ac02b1 100644
--- a/core/java/android/net/DnsPacket.java
+++ b/core/java/android/net/DnsPacket.java
@@ -28,7 +28,6 @@
import java.text.FieldPosition;
import java.util.ArrayList;
import java.util.List;
-import java.util.StringJoiner;
/**
* Defines basic data for DNS protocol based on RFC 1035.
@@ -42,7 +41,7 @@
public final int id;
public final int flags;
public final int rcode;
- private final int[] mSectionCount;
+ private final int[] mRecordCount;
/**
* Create a new DnsHeader from a positioned ByteBuffer.
@@ -52,27 +51,32 @@
* When this constructor returns, the reading position of the ByteBuffer has been
* advanced to the end of the DNS header record.
* This is meant to chain with other methods reading a DNS response in sequence.
- *
*/
DnsHeader(@NonNull ByteBuffer buf) throws BufferUnderflowException {
id = BitUtils.uint16(buf.getShort());
flags = BitUtils.uint16(buf.getShort());
rcode = flags & 0xF;
- mSectionCount = new int[NUM_SECTIONS];
+ mRecordCount = new int[NUM_SECTIONS];
for (int i = 0; i < NUM_SECTIONS; ++i) {
- mSectionCount[i] = BitUtils.uint16(buf.getShort());
+ mRecordCount[i] = BitUtils.uint16(buf.getShort());
}
}
/**
- * Get section count by section type.
+ * Get record count by type.
*/
- public int getSectionCount(int sectionType) {
- return mSectionCount[sectionType];
+ public int getRecordCount(int type) {
+ return mRecordCount[type];
}
}
- public class DnsSection {
+ /**
+ * It's used both for DNS questions and DNS resource records.
+ *
+ * DNS questions (No TTL/RDATA)
+ * DNS resource records (With TTL/RDATA)
+ */
+ public class DnsRecord {
private static final int MAXNAMESIZE = 255;
private static final int MAXLABELSIZE = 63;
private static final int MAXLABELCOUNT = 128;
@@ -81,57 +85,57 @@
private final DecimalFormat byteFormat = new DecimalFormat();
private final FieldPosition pos = new FieldPosition(0);
- private static final String TAG = "DnsSection";
+ private static final String TAG = "DnsRecord";
public final String dName;
public final int nsType;
public final int nsClass;
public final long ttl;
- private final byte[] mRR;
+ private final byte[] mRdata;
/**
- * Create a new DnsSection from a positioned ByteBuffer.
+ * Create a new DnsRecord from a positioned ByteBuffer.
*
- * The ByteBuffer must be in network byte order (which is the default).
- * Reads the passed ByteBuffer from its current position and decodes a DNS section.
+ * @param ByteBuffer input of record, must be in network byte order
+ * (which is the default).
+ * Reads the passed ByteBuffer from its current position and decodes a DNS record.
* When this constructor returns, the reading position of the ByteBuffer has been
* advanced to the end of the DNS header record.
* This is meant to chain with other methods reading a DNS response in sequence.
- *
*/
- DnsSection(int sectionType, @NonNull ByteBuffer buf)
+ DnsRecord(int recordType, @NonNull ByteBuffer buf)
throws BufferUnderflowException, ParseException {
dName = parseName(buf, 0 /* Parse depth */);
if (dName.length() > MAXNAMESIZE) {
- throw new ParseException("Parse name fail, name size is too long");
+ throw new ParseException(
+ "Parse name fail, name size is too long: " + dName.length());
}
nsType = BitUtils.uint16(buf.getShort());
nsClass = BitUtils.uint16(buf.getShort());
- if (sectionType != QDSECTION) {
+ if (recordType != QDSECTION) {
ttl = BitUtils.uint32(buf.getInt());
final int length = BitUtils.uint16(buf.getShort());
- mRR = new byte[length];
- buf.get(mRR);
+ mRdata = new byte[length];
+ buf.get(mRdata);
} else {
ttl = 0;
- mRR = null;
+ mRdata = null;
}
}
/**
- * Get a copy of rr.
+ * Get a copy of rdata.
*/
- @Nullable public byte[] getRR() {
- return (mRR == null) ? null : mRR.clone();
+ @Nullable
+ public byte[] getRR() {
+ return (mRdata == null) ? null : mRdata.clone();
}
/**
* Convert label from {@code byte[]} to {@code String}
*
- * It follows the same converting rule as native layer.
- * (See ns_name.c in libc)
- *
+ * Follows the same conversion rules of the native code (ns_name.c in libc)
*/
private String labelToString(@NonNull byte[] label) {
final StringBuffer sb = new StringBuffer();
@@ -139,13 +143,16 @@
int b = BitUtils.uint8(label[i]);
// Control characters and non-ASCII characters.
if (b <= 0x20 || b >= 0x7f) {
+ // Append the byte as an escaped decimal number, e.g., "\19" for 0x13.
sb.append('\\');
byteFormat.format(b, sb, pos);
} else if (b == '"' || b == '.' || b == ';' || b == '\\'
|| b == '(' || b == ')' || b == '@' || b == '$') {
+ // Append the byte as an escaped character, e.g., "\:" for 0x3a.
sb.append('\\');
sb.append((char) b);
} else {
+ // Append the byte as a character, e.g., "a" for 0x61.
sb.append((char) b);
}
}
@@ -154,7 +161,9 @@
private String parseName(@NonNull ByteBuffer buf, int depth) throws
BufferUnderflowException, ParseException {
- if (depth > MAXLABELCOUNT) throw new ParseException("Parse name fails, too many labels");
+ if (depth > MAXLABELCOUNT) {
+ throw new ParseException("Failed to parse name, too many labels");
+ }
final int len = BitUtils.uint8(buf.get());
final int mask = len & NAME_COMPRESSION;
if (0 == len) {
@@ -194,7 +203,7 @@
private static final String TAG = DnsPacket.class.getSimpleName();
protected final DnsHeader mHeader;
- protected final List<DnsSection>[] mSections;
+ protected final List<DnsRecord>[] mRecords;
public static class ParseException extends Exception {
public ParseException(String msg) {
@@ -216,18 +225,18 @@
throw new ParseException("Parse Header fail, bad input data", e);
}
- mSections = new ArrayList[NUM_SECTIONS];
+ mRecords = new ArrayList[NUM_SECTIONS];
for (int i = 0; i < NUM_SECTIONS; ++i) {
- final int count = mHeader.getSectionCount(i);
+ final int count = mHeader.getRecordCount(i);
if (count > 0) {
- mSections[i] = new ArrayList(count);
+ mRecords[i] = new ArrayList(count);
}
for (int j = 0; j < count; ++j) {
try {
- mSections[i].add(new DnsSection(i, buffer));
+ mRecords[i].add(new DnsRecord(i, buffer));
} catch (BufferUnderflowException e) {
- throw new ParseException("Parse section fail", e);
+ throw new ParseException("Parse record fail", e);
}
}
}
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index 6d54264..d3bc3e6 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -43,6 +43,9 @@
/**
* Dns resolver class for asynchronous dns querying
*
+ * Note that if a client sends a query with more than 1 record in the question section but
+ * the remote dns server does not support this, it may not respond at all, leading to a timeout.
+ *
*/
public final class DnsResolver {
private static final String TAG = "DnsResolver";
@@ -226,19 +229,19 @@
if (mHeader.rcode != 0) {
throw new ParseException("Response error, rcode:" + mHeader.rcode);
}
- if (mHeader.getSectionCount(ANSECTION) == 0) {
+ if (mHeader.getRecordCount(ANSECTION) == 0) {
throw new ParseException("No available answer");
}
- if (mHeader.getSectionCount(QDSECTION) == 0) {
+ if (mHeader.getRecordCount(QDSECTION) == 0) {
throw new ParseException("No question found");
}
- // Assume only one question per answer packet. (RFC1035)
- mQueryType = mSections[QDSECTION].get(0).nsType;
+ // Expect only one question in question section.
+ mQueryType = mRecords[QDSECTION].get(0).nsType;
}
public @NonNull List<InetAddress> getAddresses() {
final List<InetAddress> results = new ArrayList<InetAddress>();
- for (final DnsSection ansSec : mSections[ANSECTION]) {
+ for (final DnsRecord ansSec : mRecords[ANSECTION]) {
// Only support A and AAAA, also ignore answers if query type != answer type.
int nsType = ansSec.nsType;
if (nsType != mQueryType || (nsType != TYPE_A && nsType != TYPE_AAAA)) {
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index fd44fc8..a425a91 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -19,6 +19,7 @@
import android.app.PendingIntent;
import android.net.ConnectionInfo;
import android.net.LinkProperties;
+import android.net.ITetheringEventCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
@@ -214,4 +215,7 @@
void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
boolean showEntitlementUi, String callerPkg);
+
+ void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+ void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
}
diff --git a/core/java/android/net/ITestNetworkManager.aidl b/core/java/android/net/ITestNetworkManager.aidl
new file mode 100644
index 0000000..119a30c
--- /dev/null
+++ b/core/java/android/net/ITestNetworkManager.aidl
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2018, 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.LinkAddress;
+import android.net.TestNetworkInterface;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Interface that allows for creation and management of test-only networks.
+ *
+ * @hide
+ */
+interface ITestNetworkManager
+{
+ TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs);
+
+ void setupTestNetwork(in String iface, in IBinder binder);
+
+ void teardownTestNetwork(int netId);
+}
diff --git a/core/java/android/app/role/IRoleManagerCallback.aidl b/core/java/android/net/ITetheringEventCallback.aidl
similarity index 69%
copy from core/java/android/app/role/IRoleManagerCallback.aidl
copy to core/java/android/net/ITetheringEventCallback.aidl
index c0f8eea..d502088 100644
--- a/core/java/android/app/role/IRoleManagerCallback.aidl
+++ b/core/java/android/net/ITetheringEventCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-package android.app.role;
+package android.net;
+
+import android.net.Network;
/**
+ * Callback class for receiving tethering changed events
* @hide
*/
-oneway interface IRoleManagerCallback {
-
- void onSuccess();
-
- void onFailure();
+oneway interface ITetheringEventCallback
+{
+ void onUpstreamChanged(in Network network);
}
diff --git a/core/java/android/net/IpMemoryStore.java b/core/java/android/net/IpMemoryStore.java
index b35f097..2f4d9bc 100644
--- a/core/java/android/net/IpMemoryStore.java
+++ b/core/java/android/net/IpMemoryStore.java
@@ -171,4 +171,9 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /** Gets an instance of the memory store */
+ public static IpMemoryStore getMemoryStore(final Context context) {
+ return (IpMemoryStore) context.getSystemService(Context.IP_MEMORY_STORE_SERVICE);
+ }
}
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 15f4913..a1c7fce 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -1,12 +1,11 @@
set noparent
codewiz@google.com
-ek@google.com
-jsharkey@android.com
jchalard@google.com
+jsharkey@android.com
+junyulai@google.com
lorenzo@google.com
reminv@google.com
satk@google.com
-silberst@google.com
per-file SSL*, Uri*, Url* = flooey@google.com, narayan@google.com, tobiast@google.com
diff --git a/core/java/android/net/ParseException.java b/core/java/android/net/ParseException.java
index 68b209b..2380e86 100644
--- a/core/java/android/net/ParseException.java
+++ b/core/java/android/net/ParseException.java
@@ -24,6 +24,7 @@
public String response;
ParseException(String response) {
+ super(response);
this.response = response;
}
}
diff --git a/core/java/android/app/role/IRoleManagerCallback.aidl b/core/java/android/net/TestNetworkInterface.aidl
similarity index 74%
rename from core/java/android/app/role/IRoleManagerCallback.aidl
rename to core/java/android/net/TestNetworkInterface.aidl
index c0f8eea..e1f4f9f 100644
--- a/core/java/android/app/role/IRoleManagerCallback.aidl
+++ b/core/java/android/net/TestNetworkInterface.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,7 @@
* limitations under the License.
*/
-package android.app.role;
+package android.net;
-/**
- * @hide
- */
-oneway interface IRoleManagerCallback {
-
- void onSuccess();
-
- void onFailure();
-}
+/** @hide */
+parcelable TestNetworkInterface;
diff --git a/core/java/android/net/TestNetworkInterface.java b/core/java/android/net/TestNetworkInterface.java
new file mode 100644
index 0000000..30e68f5
--- /dev/null
+++ b/core/java/android/net/TestNetworkInterface.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 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.TestApi;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+
+/**
+ * This class is used to return the interface name and fd of the test interface
+ *
+ * @hide
+ */
+@TestApi
+public final class TestNetworkInterface implements Parcelable {
+ private static final String TAG = "TestNetworkInterface";
+
+ private final ParcelFileDescriptor mFileDescriptor;
+ private final String mInterfaceName;
+
+ @Override
+ public int describeContents() {
+ return (mFileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(mFileDescriptor, PARCELABLE_WRITE_RETURN_VALUE);
+ out.writeString(mInterfaceName);
+ }
+
+ public TestNetworkInterface(ParcelFileDescriptor pfd, String intf) {
+ mFileDescriptor = pfd;
+ mInterfaceName = intf;
+ }
+
+ private TestNetworkInterface(Parcel in) {
+ mFileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
+ mInterfaceName = in.readString();
+ }
+
+ public ParcelFileDescriptor getFileDescriptor() {
+ return mFileDescriptor;
+ }
+
+ public String getInterfaceName() {
+ return mInterfaceName;
+ }
+
+ public static final Parcelable.Creator<TestNetworkInterface> CREATOR =
+ new Parcelable.Creator<TestNetworkInterface>() {
+ public TestNetworkInterface createFromParcel(Parcel in) {
+ return new TestNetworkInterface(in);
+ }
+
+ public TestNetworkInterface[] newArray(int size) {
+ return new TestNetworkInterface[size];
+ }
+ };
+}
diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java
new file mode 100644
index 0000000..cd58e66
--- /dev/null
+++ b/core/java/android/net/TestNetworkManager.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 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.TestApi;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Class that allows creation and management of per-app, test-only networks
+ *
+ * @hide
+ */
+@TestApi
+public class TestNetworkManager {
+ @NonNull private static final String TAG = TestNetworkManager.class.getSimpleName();
+
+ @NonNull private final ITestNetworkManager mService;
+ @NonNull private final Context mContext;
+
+ /** @hide */
+ public TestNetworkManager(@NonNull Context context, @NonNull ITestNetworkManager service) {
+ mContext = Preconditions.checkNotNull(context, "missing Context");
+ mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager");
+ }
+
+ /**
+ * Teardown the capability-limited, testing-only network for a given interface
+ *
+ * @param network The test network that should be torn down
+ * @hide
+ */
+ @TestApi
+ public void teardownTestNetwork(@NonNull Network network) {
+ try {
+ mService.teardownTestNetwork(network.netId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sets up a capability-limited, testing-only network for a given interface
+ *
+ * @param iface the name of the interface to be used for the Network LinkProperties.
+ * @param binder A binder object guarding the lifecycle of this test network.
+ * @hide
+ */
+ @TestApi
+ public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
+ try {
+ mService.setupTestNetwork(iface, binder);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Create a tun interface for testing purposes
+ *
+ * @param linkAddrs an array of LinkAddresses to assign to the TUN interface
+ * @return A ParcelFileDescriptor of the underlying TUN interface. Close this to tear down the
+ * TUN interface.
+ * @hide
+ */
+ @TestApi
+ public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
+ try {
+ return mService.createTunInterface(linkAddrs);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 01932ab..f23dc2d 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -16,6 +16,7 @@
package android.nfc.cardemulation;
+import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Activity;
@@ -359,7 +360,7 @@
* @param service The component name of the service
* @return whether the registration was successful.
*/
- public boolean unsetOffHostForService(ComponentName service) {
+ public boolean unsetOffHostForService(@NonNull ComponentName service) {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
if (adapter == null) {
return false;
@@ -405,7 +406,8 @@
* @param offHostSecureElement Secure Element to register the AID to
* @return whether the registration was successful.
*/
- public boolean setOffHostForService(ComponentName service, String offHostSecureElement) {
+ public boolean setOffHostForService(@NonNull ComponentName service,
+ @NonNull String offHostSecureElement) {
boolean validSecureElement = false;
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
diff --git a/core/java/android/os/BatterySaverPolicyConfig.java b/core/java/android/os/BatterySaverPolicyConfig.java
index af7d11d..bda4e27 100644
--- a/core/java/android/os/BatterySaverPolicyConfig.java
+++ b/core/java/android/os/BatterySaverPolicyConfig.java
@@ -476,10 +476,6 @@
*/
@NonNull
public BatterySaverPolicyConfig build() {
- if (!mEnableAdjustBrightness && Float.compare(1f, mAdjustBrightnessFactor) != 0) {
- throw new IllegalArgumentException("Brightness adjustment factor changed without "
- + "enabling brightness adjustment");
- }
return new BatterySaverPolicyConfig(this);
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b7e65b9..e4277e4 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -4761,6 +4761,9 @@
sb.append(")");
pw.println(sb.toString());
+ printControllerActivity(pw, sb, prefix, CELLULAR_CONTROLLER_NAME,
+ getModemControllerActivity(), which);
+
pw.print(" Cellular data received: "); pw.println(formatBytesLocked(mobileRxTotalBytes));
pw.print(" Cellular data sent: "); pw.println(formatBytesLocked(mobileTxTotalBytes));
pw.print(" Cellular packets received: "); pw.println(mobileRxTotalPackets);
@@ -4818,9 +4821,6 @@
if (!didOne) sb.append(" (no activity)");
pw.println(sb.toString());
- printControllerActivity(pw, sb, prefix, CELLULAR_CONTROLLER_NAME,
- getModemControllerActivity(), which);
-
pw.print(prefix);
sb.setLength(0);
sb.append(prefix);
@@ -4837,6 +4837,9 @@
sb.append(")");
pw.println(sb.toString());
+ printControllerActivity(pw, sb, prefix, WIFI_CONTROLLER_NAME,
+ getWifiControllerActivity(), which);
+
pw.print(" Wifi data received: "); pw.println(formatBytesLocked(wifiRxTotalBytes));
pw.print(" Wifi data sent: "); pw.println(formatBytesLocked(wifiTxTotalBytes));
pw.print(" Wifi packets received: "); pw.println(wifiRxTotalPackets);
@@ -4914,9 +4917,6 @@
if (!didOne) sb.append(" (no activity)");
pw.println(sb.toString());
- printControllerActivity(pw, sb, prefix, WIFI_CONTROLLER_NAME,
- getWifiControllerActivity(), which);
-
pw.print(prefix);
sb.setLength(0);
sb.append(prefix);
@@ -4949,8 +4949,10 @@
pw.print(prefix);
sb.setLength(0);
sb.append(prefix);
- sb.append(" Battery Drain (mAh): ");
- sb.append(Double.toString(((double) gpsBatteryDrainMaMs)/(3600 * 1000)));
+ sb.append(" GPS Battery Drain: ");
+ sb.append(new DecimalFormat("#.##").format(
+ ((double) gpsBatteryDrainMaMs) / (3600 * 1000)));
+ sb.append("mAh");
pw.println(sb.toString());
}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index b28c2f4..d5ef249 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -653,7 +653,8 @@
*
* @return an object that will be passed back to #onTransactEnded (or null).
*/
- Object onTransactStarted(IBinder binder, int transactionCode);
+ @Nullable
+ Object onTransactStarted(@NonNull IBinder binder, int transactionCode);
/**
* Called after onTranact (even when an exception is thrown).
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 684369a..672624c 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.CallbackExecutor;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -39,7 +40,7 @@
*/
@SystemApi
@SystemService(Context.BUGREPORT_SERVICE)
-public class BugreportManager {
+public final class BugreportManager {
private final Context mContext;
private final IDumpstate mBinder;
@@ -90,7 +91,7 @@
* Called when there is a progress update.
* @param progress the progress in [0.0, 100.0]
*/
- public void onProgress(float progress) {}
+ public void onProgress(@FloatRange(from = 0f, to = 100f) float progress) {}
/**
* Called when taking bugreport resulted in an error.
diff --git a/core/java/android/os/BugreportParams.java b/core/java/android/os/BugreportParams.java
index 3871375..279ccae 100644
--- a/core/java/android/os/BugreportParams.java
+++ b/core/java/android/os/BugreportParams.java
@@ -41,6 +41,7 @@
/**
* Defines acceptable types of bugreports.
+ * @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "BUGREPORT_MODE_" }, value = {
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index b3e35b6..fea69c0 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -389,7 +389,7 @@
/** {@hide} */
public static File getDataStagingDirectory(String volumeUuid) {
- return new File(getDataDirectory(volumeUuid), "pkg_staging");
+ return new File(getDataDirectory(volumeUuid), "app-staging");
}
/** {@hide} */
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index e6c12c7..a039742 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -82,19 +82,19 @@
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
- public boolean handleMessage(Message msg);
+ boolean handleMessage(@NonNull Message msg);
}
/**
* Subclasses must implement this to receive messages.
*/
- public void handleMessage(Message msg) {
+ public void handleMessage(@NonNull Message msg) {
}
/**
* Handle system messages here.
*/
- public void dispatchMessage(Message msg) {
+ public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
@@ -128,7 +128,7 @@
*
* @param callback The callback interface in which to handle messages, or null.
*/
- public Handler(Callback callback) {
+ public Handler(@Nullable Callback callback) {
this(callback, false);
}
@@ -137,7 +137,7 @@
*
* @param looper The looper, must not be null.
*/
- public Handler(Looper looper) {
+ public Handler(@NonNull Looper looper) {
this(looper, null, false);
}
@@ -148,7 +148,7 @@
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
*/
- public Handler(Looper looper, Callback callback) {
+ public Handler(@NonNull Looper looper, @Nullable Callback callback) {
this(looper, callback, false);
}
@@ -189,7 +189,7 @@
*
* @hide
*/
- public Handler(Callback callback, boolean async) {
+ public Handler(@Nullable Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
@@ -229,7 +229,7 @@
*
* @hide
*/
- public Handler(Looper looper, Callback callback, boolean async) {
+ public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
@@ -289,7 +289,8 @@
}
/** {@hide} */
- public String getTraceName(Message message) {
+ @NonNull
+ public String getTraceName(@NonNull Message message) {
final StringBuilder sb = new StringBuilder();
sb.append(getClass().getName()).append(": ");
if (message.callback != null) {
@@ -308,7 +309,8 @@
*
* @param message The message whose name is being queried
*/
- public String getMessageName(Message message) {
+ @NonNull
+ public String getMessageName(@NonNull Message message) {
if (message.callback != null) {
return message.callback.getClass().getName();
}
@@ -320,6 +322,7 @@
* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
* If you don't want that facility, just call Message.obtain() instead.
*/
+ @NonNull
public final Message obtainMessage()
{
return Message.obtain(this);
@@ -331,6 +334,7 @@
* @param what Value to assign to the returned Message.what field.
* @return A Message from the global message pool.
*/
+ @NonNull
public final Message obtainMessage(int what)
{
return Message.obtain(this, what);
@@ -345,8 +349,8 @@
* @param obj Value to assign to the returned Message.obj field.
* @return A Message from the global message pool.
*/
- public final Message obtainMessage(int what, Object obj)
- {
+ @NonNull
+ public final Message obtainMessage(int what, @Nullable Object obj) {
return Message.obtain(this, what, obj);
}
@@ -359,6 +363,7 @@
* @param arg2 Value to assign to the returned Message.arg2 field.
* @return A Message from the global message pool.
*/
+ @NonNull
public final Message obtainMessage(int what, int arg1, int arg2)
{
return Message.obtain(this, what, arg1, arg2);
@@ -374,8 +379,8 @@
* @param obj Value to assign to the returned Message.obj field.
* @return A Message from the global message pool.
*/
- public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
- {
+ @NonNull
+ public final Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
return Message.obtain(this, what, arg1, arg2, obj);
}
@@ -390,8 +395,7 @@
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
- public final boolean post(Runnable r)
- {
+ public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
@@ -413,8 +417,7 @@
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
- public final boolean postAtTime(Runnable r, long uptimeMillis)
- {
+ public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
@@ -440,8 +443,8 @@
*
* @see android.os.SystemClock#uptimeMillis
*/
- public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
- {
+ public final boolean postAtTime(
+ @NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
@@ -464,8 +467,7 @@
* if the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
- public final boolean postDelayed(Runnable r, long delayMillis)
- {
+ public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
@@ -495,8 +497,8 @@
* if the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
- public final boolean postDelayed(Runnable r, Object token, long delayMillis)
- {
+ public final boolean postDelayed(
+ @NonNull Runnable r, @Nullable Object token, long delayMillis) {
return sendMessageDelayed(getPostMessage(r, token), delayMillis);
}
@@ -515,8 +517,7 @@
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
- public final boolean postAtFrontOfQueue(Runnable r)
- {
+ public final boolean postAtFrontOfQueue(@NonNull Runnable r) {
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
@@ -560,7 +561,7 @@
* If we ever do make it part of the API, we might want to rename it to something
* less funny like runUnsafe().
*/
- public final boolean runWithScissors(final Runnable r, long timeout) {
+ public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
@@ -580,8 +581,7 @@
/**
* Remove any pending posts of Runnable r that are in the message queue.
*/
- public final void removeCallbacks(Runnable r)
- {
+ public final void removeCallbacks(@NonNull Runnable r) {
mQueue.removeMessages(this, r, null);
}
@@ -590,8 +590,7 @@
* <var>token</var> that are in the message queue. If <var>token</var> is null,
* all callbacks will be removed.
*/
- public final void removeCallbacks(Runnable r, Object token)
- {
+ public final void removeCallbacks(@NonNull Runnable r, @Nullable Object token) {
mQueue.removeMessages(this, r, token);
}
@@ -604,8 +603,7 @@
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
- public final boolean sendMessage(Message msg)
- {
+ public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
@@ -664,8 +662,7 @@
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
- public final boolean sendMessageDelayed(Message msg, long delayMillis)
- {
+ public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
@@ -691,7 +688,7 @@
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
- public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+ public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
@@ -714,7 +711,7 @@
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
- public final boolean sendMessageAtFrontOfQueue(Message msg) {
+ public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
@@ -734,7 +731,7 @@
* looper processing the message queue is exiting.
* @hide
*/
- public final boolean executeOrSendMessage(Message msg) {
+ public final boolean executeOrSendMessage(@NonNull Message msg) {
if (mLooper == Looper.myLooper()) {
dispatchMessage(msg);
return true;
@@ -742,7 +739,8 @@
return sendMessage(msg);
}
- private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
+ private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
+ long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
@@ -765,7 +763,7 @@
* 'object' that are in the message queue. If <var>object</var> is null,
* all messages will be removed.
*/
- public final void removeMessages(int what, Object object) {
+ public final void removeMessages(int what, @Nullable Object object) {
mQueue.removeMessages(this, what, object);
}
@@ -774,7 +772,7 @@
* <var>obj</var> is <var>token</var>. If <var>token</var> is null,
* all callbacks and messages will be removed.
*/
- public final void removeCallbacksAndMessages(Object token) {
+ public final void removeCallbacksAndMessages(@Nullable Object token) {
mQueue.removeCallbacksAndMessages(this, token);
}
@@ -798,7 +796,7 @@
* Check if there are any pending posts of messages with code 'what' and
* whose obj is 'object' in the message queue.
*/
- public final boolean hasMessages(int what, Object object) {
+ public final boolean hasMessages(int what, @Nullable Object object) {
return mQueue.hasMessages(this, what, object);
}
@@ -806,17 +804,18 @@
* Check if there are any pending posts of messages with callback r in
* the message queue.
*/
- public final boolean hasCallbacks(Runnable r) {
+ public final boolean hasCallbacks(@NonNull Runnable r) {
return mQueue.hasMessages(this, r, null);
}
// if we can get rid of this method, the handler need not remember its loop
// we could instead export a getMessageQueue() method...
+ @NonNull
public final Looper getLooper() {
return mLooper;
}
- public final void dump(Printer pw, String prefix) {
+ public final void dump(@NonNull Printer pw, @NonNull String prefix) {
pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
if (mLooper == null) {
pw.println(prefix + "looper uninitialized");
@@ -828,7 +827,7 @@
/**
* @hide
*/
- public final void dumpMine(Printer pw, String prefix) {
+ public final void dumpMine(@NonNull Printer pw, @NonNull String prefix) {
pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
if (mLooper == null) {
pw.println(prefix + "looper uninitialized");
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index 1df3dad..5cf3b97 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -39,8 +39,9 @@
*
* The APIs defined in this class and UpdateEngineCallback class must be in
* sync with the ones in
- * system/update_engine/binder_bindings/android/os/IUpdateEngine.aidl and
- * system/update_engine/binder_bindings/android/os/IUpdateEngineCallback.aidl.
+ * {@code system/update_engine/binder_bindings/android/os/IUpdateEngine.aidl}
+ * and
+ * {@code system/update_engine/binder_bindings/android/os/IUpdateEngineCallback.aidl}.
*
* {@hide}
*/
@@ -51,39 +52,150 @@
private static final String UPDATE_ENGINE_SERVICE = "android.os.UpdateEngineService";
/**
- * Error code from the update engine. Values must agree with the ones in
- * system/update_engine/common/error_code.h.
+ * Error codes from update engine upon finishing a call to
+ * {@link applyPayload}. Values will be passed via the callback function
+ * {@link UpdateEngineCallback#onPayloadApplicationComplete}. Values must
+ * agree with the ones in {@code system/update_engine/common/error_code.h}.
*/
public static final class ErrorCodeConstants {
+ /**
+ * Error code: a request finished successfully.
+ */
public static final int SUCCESS = 0;
+ /**
+ * Error code: a request failed due to a generic error.
+ */
public static final int ERROR = 1;
+ /**
+ * Error code: an update failed to apply due to filesystem copier
+ * error.
+ */
public static final int FILESYSTEM_COPIER_ERROR = 4;
+ /**
+ * Error code: an update failed to apply due to an error in running
+ * post-install hooks.
+ */
public static final int POST_INSTALL_RUNNER_ERROR = 5;
+ /**
+ * Error code: an update failed to apply due to a mismatching payload.
+ *
+ * <p>For example, the given payload uses a feature that's not
+ * supported by the current update engine.
+ */
public static final int PAYLOAD_MISMATCHED_TYPE_ERROR = 6;
+ /**
+ * Error code: an update failed to apply due to an error in opening
+ * devices.
+ */
public static final int INSTALL_DEVICE_OPEN_ERROR = 7;
+ /**
+ * Error code: an update failed to apply due to an error in opening
+ * kernel device.
+ */
public static final int KERNEL_DEVICE_OPEN_ERROR = 8;
+ /**
+ * Error code: an update failed to apply due to an error in fetching
+ * the payload.
+ *
+ * <p>For example, this could be a result of bad network connection
+ * when streaming an update.
+ */
public static final int DOWNLOAD_TRANSFER_ERROR = 9;
+ /**
+ * Error code: an update failed to apply due to a mismatch in payload
+ * hash.
+ *
+ * <p>Update engine does sanity checks for the given payload and its
+ * metadata.
+ */
public static final int PAYLOAD_HASH_MISMATCH_ERROR = 10;
+
+ /**
+ * Error code: an update failed to apply due to a mismatch in payload
+ * size.
+ */
public static final int PAYLOAD_SIZE_MISMATCH_ERROR = 11;
+
+ /**
+ * Error code: an update failed to apply due to failing to verify
+ * payload signatures.
+ */
public static final int DOWNLOAD_PAYLOAD_VERIFICATION_ERROR = 12;
+
+ /**
+ * Error code: an update failed to apply due to a downgrade in payload
+ * timestamp.
+ *
+ * <p>The timestamp of a build is encoded into the payload, which will
+ * be enforced during install to prevent downgrading a device.
+ */
public static final int PAYLOAD_TIMESTAMP_ERROR = 51;
+
+ /**
+ * Error code: an update has been applied successfully but the new slot
+ * hasn't been set to active.
+ *
+ * <p>It indicates a successful finish of calling {@link #applyPayload} with
+ * {@code SWITCH_SLOT_ON_REBOOT=0}. See {@link #applyPayload}.
+ */
public static final int UPDATED_BUT_NOT_ACTIVE = 52;
}
/**
- * Update status code from the update engine. Values must agree with the
- * ones in system/update_engine/client_library/include/update_engine/update_status.h.
+ * Status codes for update engine. Values must agree with the ones in
+ * {@code system/update_engine/client_library/include/update_engine/update_status.h}.
*/
public static final class UpdateStatusConstants {
+ /**
+ * Update status code: update engine is in idle state.
+ */
public static final int IDLE = 0;
+
+ /**
+ * Update status code: update engine is checking for update.
+ */
public static final int CHECKING_FOR_UPDATE = 1;
+
+ /**
+ * Update status code: an update is available.
+ */
public static final int UPDATE_AVAILABLE = 2;
+
+ /**
+ * Update status code: update engine is downloading an update.
+ */
public static final int DOWNLOADING = 3;
+
+ /**
+ * Update status code: update engine is verifying an update.
+ */
public static final int VERIFYING = 4;
+
+ /**
+ * Update status code: update engine is finalizing an update.
+ */
public static final int FINALIZING = 5;
+
+ /**
+ * Update status code: an update has been applied and is pending for
+ * reboot.
+ */
public static final int UPDATED_NEED_REBOOT = 6;
+
+ /**
+ * Update status code: update engine is reporting an error event.
+ */
public static final int REPORTING_ERROR_EVENT = 7;
+
+ /**
+ * Update status code: update engine is attempting to rollback an
+ * update.
+ */
public static final int ATTEMPTING_ROLLBACK = 8;
+
+ /**
+ * Update status code: update engine is in disabled state.
+ */
public static final int DISABLED = 9;
}
@@ -178,6 +290,18 @@
* "METADATA_SIZE=70604"
* };
* </pre>
+ *
+ * <p>The callback functions registered via {@code #bind} will be called
+ * during and at the end of the payload application.
+ *
+ * <p>By default the newly updated slot will be set active upon
+ * successfully finishing an update. Device will attempt to boot into the
+ * new slot on next reboot. This behavior can be customized by specifying
+ * {@code SWITCH_SLOT_ON_REBOOT=0} in {@code headerKeyValuePairs}, which
+ * allows the caller to later determine a good time to boot into the new
+ * slot. Calling {@code applyPayload} again with the same payload but with
+ * {@code SWITCH_SLOT_ON_REBOOT=1} will do the minimal work to set the new
+ * slot active, after verifying its integrity.
*/
public void applyPayload(String url, long offset, long size, String[] headerKeyValuePairs) {
try {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 4263377..185df5e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -25,6 +25,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Activity;
@@ -954,6 +955,21 @@
public static final String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
/**
+ * Specifies if the current user is able to receive content suggestions for selections based on
+ * the contents of their screen.
+ *
+ * <p>Device owner and profile owner can set this restriction. When it is set by device owner,
+ * only the target user will be affected.
+ *
+ * <p>The default value is <code>false</code>.
+ *
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_CONTENT_SUGGESTIONS = "no_content_suggestions";
+
+ /**
* Specifies if user switching is blocked on the current user.
*
* <p> This restriction can only be set by the device owner, it will be applied to all users.
@@ -1102,6 +1118,47 @@
public static final int USER_CREATION_FAILED_NO_MORE_USERS = Activity.RESULT_FIRST_USER + 1;
/**
+ * Indicates that users are switchable.
+ * @hide
+ */
+ @SystemApi
+ public static final int SWITCHABILITY_STATUS_OK = 0;
+
+ /**
+ * Indicated that the user is in a phone call.
+ * @hide
+ */
+ @SystemApi
+ public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1 << 0;
+
+ /**
+ * Indicates that user switching is disallowed ({@link #DISALLOW_USER_SWITCH} is set).
+ * @hide
+ */
+ @SystemApi
+ public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 1 << 1;
+
+ /**
+ * Indicates that the system user is locked and user switching is not allowed.
+ * @hide
+ */
+ @SystemApi
+ public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 1 << 2;
+
+ /**
+ * Result returned in {@link #getUserSwitchability()} indicating user swichability.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "SWITCHABILITY_STATUS_" }, value = {
+ SWITCHABILITY_STATUS_OK,
+ SWITCHABILITY_STATUS_USER_IN_CALL,
+ SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED,
+ SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED
+ })
+ public @interface UserSwitchabilityResult {}
+
+ /**
* Indicates user operation is successful.
*/
public static final int USER_OPERATION_SUCCESS = 0;
@@ -1223,14 +1280,13 @@
}
/**
- * Returns whether switching users is currently allowed.
- * <p>For instance switching users is not allowed if the current user is in a phone call,
- * system user hasn't been unlocked yet, or {@link #DISALLOW_USER_SWITCH} is set.
+ * @deprecated use {@link #getUserSwitchability()} instead.
+ *
+ * @removed
* @hide
*/
- @SystemApi
- @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
- android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+ @Deprecated
+ @UnsupportedAppUsage
public boolean canSwitchUsers() {
boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
mContext.getContentResolver(),
@@ -1244,6 +1300,42 @@
}
/**
+ * Returns whether switching users is currently allowed.
+ * <p>
+ * Switching users is not allowed in the following cases:
+ * <li>the user is in a phone call</li>
+ * <li>{@link #DISALLOW_USER_SWITCH} is set</li>
+ * <li>system user hasn't been unlocked yet</li>
+ *
+ * @return A {@link UserSwitchabilityResult} flag indicating if the user is switchable.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+ public @UserSwitchabilityResult int getUserSwitchability() {
+ final boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
+ final boolean systemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM);
+ final TelephonyManager tm =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+
+ int flags = SWITCHABILITY_STATUS_OK;
+ if (tm.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+ flags |= SWITCHABILITY_STATUS_USER_IN_CALL;
+ }
+ if (hasUserRestriction(DISALLOW_USER_SWITCH)) {
+ flags |= SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
+ }
+ if (!allowUserSwitchingWhenSystemUserLocked && !systemUserUnlocked) {
+ flags |= SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED;
+ }
+ return flags;
+ }
+
+ /**
* Returns the user handle for the user that this process is running under.
*
* @return the user handle of this process.
@@ -2655,11 +2747,16 @@
* Removes a user and all associated data.
*
* @param user the user that needs to be removed.
+ * @return {@code true} if the user was successfully removed, {@code false} otherwise.
+ * @throws IllegalArgumentException if {@code user} is {@code null}
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
- public boolean removeUser(UserHandle user) {
+ public boolean removeUser(@NonNull UserHandle user) {
+ if (user == null) {
+ throw new IllegalArgumentException("user cannot be null");
+ }
return removeUser(user.getIdentifier());
}
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index 76e911d..4f65d24 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -38,9 +38,6 @@
void countPermissionApps(in List<String> permissionNames, int flags,
in RemoteCallback callback);
void getPermissionUsages(boolean countSystem, long numMillis, in RemoteCallback callback);
- void isApplicationQualifiedForRole(String roleName, String packageName,
- in RemoteCallback callback);
- void isRoleVisible(String roleName, in RemoteCallback callback);
void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName,
String permission, int grantState, in RemoteCallback callback);
}
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 5695e42..61511aa 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -454,48 +454,6 @@
}
/**
- * Check whether an application is qualified for a role.
- *
- * @param roleName name of the role to check for
- * @param packageName package name of the application to check for
- * @param executor Executor on which to invoke the callback
- * @param callback Callback to receive the result
- *
- * @hide
- */
- @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName,
- @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
- checkStringNotEmpty(roleName);
- checkStringNotEmpty(packageName);
- checkNotNull(executor);
- checkNotNull(callback);
-
- mRemoteService.scheduleRequest(new PendingIsApplicationQualifiedForRoleRequest(
- mRemoteService, roleName, packageName, executor, callback));
- }
-
- /**
- * Check whether a role should be visible to user.
- *
- * @param roleName name of the role to check for
- * @param executor Executor on which to invoke the callback
- * @param callback Callback to receive the result
- *
- * @hide
- */
- @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- public void isRoleVisible(@NonNull String roleName,
- @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
- checkStringNotEmpty(roleName);
- checkNotNull(executor);
- checkNotNull(callback);
-
- mRemoteService.scheduleRequest(new PendingIsRoleVisibleRequest(mRemoteService, roleName,
- executor, callback));
- }
-
- /**
* A connection to the remote service
*/
static final class RemoteService extends
@@ -513,7 +471,8 @@
RemoteService(@NonNull Context context, @NonNull ComponentName componentName,
@NonNull UserHandle user) {
super(context, SERVICE_INTERFACE, componentName, user.getIdentifier(),
- service -> Log.e(TAG, "RemoteService " + service + " died"), false, false, 1);
+ service -> Log.e(TAG, "RemoteService " + service + " died"),
+ context.getMainThreadHandler(), false, false, 1);
}
/**
@@ -1188,109 +1147,4 @@
}
}
}
-
- /**
- * Request for {@link #isApplicationQualifiedForRole}.
- */
- private static final class PendingIsApplicationQualifiedForRoleRequest extends
- AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
-
- private final @NonNull String mRoleName;
- private final @NonNull String mPackageName;
- private final @NonNull Consumer<Boolean> mCallback;
-
- private final @NonNull RemoteCallback mRemoteCallback;
-
- private PendingIsApplicationQualifiedForRoleRequest(@NonNull RemoteService service,
- @NonNull String roleName, @NonNull String packageName,
- @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
- super(service);
-
- mRoleName = roleName;
- mPackageName = packageName;
- mCallback = callback;
-
- mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
- long token = Binder.clearCallingIdentity();
- try {
- boolean qualified;
- if (result != null) {
- qualified = result.getBoolean(KEY_RESULT);
- } else {
- qualified = false;
- }
- callback.accept(qualified);
- } finally {
- Binder.restoreCallingIdentity(token);
- finish();
- }
- }), null);
- }
-
- @Override
- protected void onTimeout(RemoteService remoteService) {
- mCallback.accept(false);
- }
-
- @Override
- public void run() {
- try {
- getService().getServiceInterface().isApplicationQualifiedForRole(mRoleName,
- mPackageName, mRemoteCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "Error checking whether application qualifies for role", e);
- }
- }
- }
-
- /**
- * Request for {@link #isRoleVisible}.
- */
- private static final class PendingIsRoleVisibleRequest extends
- AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
-
- private final @NonNull String mRoleName;
- private final @NonNull Consumer<Boolean> mCallback;
-
- private final @NonNull RemoteCallback mRemoteCallback;
-
- private PendingIsRoleVisibleRequest(@NonNull RemoteService service,
- @NonNull String roleName, @NonNull @CallbackExecutor Executor executor,
- @NonNull Consumer<Boolean> callback) {
- super(service);
-
- mRoleName = roleName;
- mCallback = callback;
-
- mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
- long token = Binder.clearCallingIdentity();
- try {
- boolean visible;
- if (result != null) {
- visible = result.getBoolean(KEY_RESULT);
- } else {
- visible = false;
- }
- callback.accept(visible);
- } finally {
- Binder.restoreCallingIdentity(token);
- finish();
- }
- }), null);
- }
-
- @Override
- protected void onTimeout(RemoteService remoteService) {
- mCallback.accept(false);
- }
-
- @Override
- public void run() {
- try {
- getService().getServiceInterface().isRoleVisible(mRoleName, mRemoteCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "Error checking whether role should be visible", e);
- }
- }
- }
}
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index d375c10..2313d59 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -112,6 +112,9 @@
/**
* Restore a backup of the runtime permissions.
*
+ * <p>If an app mentioned in the backup is not installed the state should be saved to later
+ * be restored via {@link #onRestoreDelayedRuntimePermissionsBackup}.
+ *
* @param user The user to restore
* @param backup The stream to read the backup from
*/
@@ -120,7 +123,8 @@
@NonNull InputStream backup);
/**
- * Restore a delayed backup of the runtime permissions.
+ * Restore the permission state of an app that was provided in
+ * {@link #onRestoreRuntimePermissionsBackup} but could not be restored back then.
*
* @param packageName The app to restore
* @param user The user to restore
@@ -174,26 +178,6 @@
boolean countSystem, long numMillis);
/**
- * Check whether an application is qualified for a role.
- *
- * @param roleName name of the role to check for
- * @param packageName package name of the application to check for
- *
- * @return whether the application is qualified for the role
- */
- public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
- @NonNull String packageName);
-
- /**
- * Check whether a role should be visible to user.
- *
- * @param roleName name of the role to check for
- *
- * @return whether the role should be visible to user
- */
- public abstract boolean onIsRoleVisible(@NonNull String roleName);
-
- /**
* Set the runtime permission state from a device admin.
*
* @param callerPackageName The package name of the admin requesting the change
@@ -339,32 +323,6 @@
}
@Override
- public void isApplicationQualifiedForRole(String roleName, String packageName,
- RemoteCallback callback) {
- checkStringNotEmpty(roleName);
- checkStringNotEmpty(packageName);
- checkNotNull(callback, "callback");
-
- enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
-
- mHandler.sendMessage(obtainMessage(
- PermissionControllerService::isApplicationQualifiedForRole,
- PermissionControllerService.this, roleName, packageName, callback));
- }
-
- @Override
- public void isRoleVisible(String roleName, RemoteCallback callback) {
- checkStringNotEmpty(roleName);
- checkNotNull(callback, "callback");
-
- enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
-
- mHandler.sendMessage(obtainMessage(
- PermissionControllerService::isRoleVisible,
- PermissionControllerService.this, roleName, callback));
- }
-
- @Override
public void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName,
String packageName, String permission, int grantState,
RemoteCallback callback) {
@@ -458,21 +416,6 @@
}
}
- private void isApplicationQualifiedForRole(@NonNull String roleName,
- @NonNull String packageName, @NonNull RemoteCallback callback) {
- boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName);
- Bundle result = new Bundle();
- result.putBoolean(PermissionControllerManager.KEY_RESULT, qualified);
- callback.sendResult(result);
- }
-
- private void isRoleVisible(@NonNull String roleName, @NonNull RemoteCallback callback) {
- boolean visible = onIsRoleVisible(roleName);
- Bundle result = new Bundle();
- result.putBoolean(PermissionControllerManager.KEY_RESULT, visible);
- callback.sendResult(result);
- }
-
private void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
@NonNull String packageName, @NonNull String permission,
@PermissionGrantState int grantState, @NonNull RemoteCallback callback) {
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index 8880296..e656466 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -349,16 +349,31 @@
dialog.show();
}
+ /**
+ * Get the DecorView.
+ * @return the DecorView for the current dialog window, if it exists.
+ * If the window does not exist, null is returned.
+ */
+ private View getDecorView() {
+ if (mDialog != null && mDialog.getWindow() != null) {
+ return mDialog.getWindow().getDecorView();
+ }
+ return null;
+ }
+
void postDismiss() {
removeDismissCallbacks();
- View decorView = mDialog.getWindow().getDecorView();
- decorView.post(mDismissRunnable);
+ View decorView = getDecorView();
+ if (decorView != null) {
+ // If decorView is null, dialog was already dismissed
+ decorView.post(mDismissRunnable);
+ }
}
private void removeDismissCallbacks() {
- if (mDialog != null && mDialog.getWindow() != null
- && mDialog.getWindow().getDecorView() != null) {
- mDialog.getWindow().getDecorView().removeCallbacks(mDismissRunnable);
+ View decorView = getDecorView();
+ if (decorView != null) {
+ decorView.removeCallbacks(mDismissRunnable);
}
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 60c8d36..e4593e5 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -30,6 +30,7 @@
import android.database.ContentObserver;
import android.net.Uri;
import android.provider.Settings.ResetMode;
+import android.util.ArrayMap;
import android.util.Pair;
import com.android.internal.annotations.GuardedBy;
@@ -323,18 +324,40 @@
*/
@SystemApi
public interface Rollback {
+
+ /**
+ * Namespace for flags that can be changed immediately after becoming available on device.
+ */
String NAMESPACE = "rollback";
+ /**
+ * Namespace for flags that can be changed only after reboot.
+ */
String BOOT_NAMESPACE = "rollback_boot";
/**
- * Timeout in milliseconds for enabling package rollback.
+ * Timeout duration in milliseconds for enabling package rollback. If we fail to enable
+ * rollback within that period, the install will proceed without rollback enabled.
+ *
+ * <p>If flag value is negative, the default value will be assigned.
+ *
+ * Flag type: {@code long}
+ * Namespace: Rollback.NAMESPACE
*/
String ENABLE_ROLLBACK_TIMEOUT = "enable_rollback_timeout";
- /**
- * The lifetime duration of rollback packages in millis
- */
+ /**
+ * Lifetime duration of rollback packages in millis. A rollback will be available for
+ * at most that duration of time after a package is installed with
+ * {@link PackageInstaller.SessionParams#setEnableRollback()}.
+ *
+ * <p>If flag value is negative, the default value will be assigned.
+ *
+ * @see RollbackManager
+ *
+ * Flag type: {@code long}
+ * Namespace: Rollback.BOOT_NAMESPACE
+ */
String ROLLBACK_LIFETIME_IN_MILLIS = "rollback_lifetime_in_millis";
}
@@ -376,8 +399,11 @@
private static final Object sLock = new Object();
@GuardedBy("sLock")
- private static Map<OnPropertyChangedListener, Pair<String, Executor>> sListeners =
- new HashMap<>();
+ private static ArrayMap<OnPropertyChangedListener, Pair<String, Executor>> sSingleListeners =
+ new ArrayMap<>();
+ @GuardedBy("sLock")
+ private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
+ new ArrayMap<>();
@GuardedBy("sLock")
private static Map<String, Pair<ContentObserver, Integer>> sNamespaces = new HashMap<>();
@@ -575,20 +601,58 @@
@NonNull String namespace,
@NonNull @CallbackExecutor Executor executor,
@NonNull OnPropertyChangedListener onPropertyChangedListener) {
- // TODO enforce READ_DEVICE_CONFIG permission
synchronized (sLock) {
- Pair<String, Executor> oldNamespace = sListeners.get(onPropertyChangedListener);
+ Pair<String, Executor> oldNamespace = sSingleListeners.get(onPropertyChangedListener);
if (oldNamespace == null) {
// Brand new listener, add it to the list.
- sListeners.put(onPropertyChangedListener, new Pair<>(namespace, executor));
+ sSingleListeners.put(onPropertyChangedListener, new Pair<>(namespace, executor));
incrementNamespace(namespace);
} else if (namespace.equals(oldNamespace.first)) {
// Listener is already registered for this namespace, update executor just in case.
- sListeners.put(onPropertyChangedListener, new Pair<>(namespace, executor));
+ sSingleListeners.put(onPropertyChangedListener, new Pair<>(namespace, executor));
} else {
// Update this listener from an old namespace to the new one.
- decrementNamespace(sListeners.get(onPropertyChangedListener).first);
- sListeners.put(onPropertyChangedListener, new Pair<>(namespace, executor));
+ decrementNamespace(sSingleListeners.get(onPropertyChangedListener).first);
+ sSingleListeners.put(onPropertyChangedListener, new Pair<>(namespace, executor));
+ incrementNamespace(namespace);
+ }
+ }
+ }
+
+ /**
+ * Add a listener for property changes.
+ * <p>
+ * This listener will be called whenever properties in the specified namespace change. Callbacks
+ * will be made on the specified executor. Future calls to this method with the same listener
+ * will replace the old namespace and executor. Remove the listener entirely by calling
+ * {@link #removeOnPropertiesChangedListener(OnPropertiesChangedListener)}.
+ *
+ * @param namespace The namespace containing properties to monitor.
+ * @param executor The executor which will be used to run callbacks.
+ * @param onPropertiesChangedListener The listener to add.
+ * @hide
+ * @see #removeOnPropertiesChangedListener(OnPropertiesChangedListener)
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(READ_DEVICE_CONFIG)
+ public static void addOnPropertiesChangedListener(
+ @NonNull String namespace,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnPropertiesChangedListener onPropertiesChangedListener) {
+ synchronized (sLock) {
+ Pair<String, Executor> oldNamespace = sListeners.get(onPropertiesChangedListener);
+ if (oldNamespace == null) {
+ // Brand new listener, add it to the list.
+ sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor));
+ incrementNamespace(namespace);
+ } else if (namespace.equals(oldNamespace.first)) {
+ // Listener is already registered for this namespace, update executor just in case.
+ sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor));
+ } else {
+ // Update this listener from an old namespace to the new one.
+ decrementNamespace(sListeners.get(onPropertiesChangedListener).first);
+ sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor));
incrementNamespace(namespace);
}
}
@@ -605,11 +669,33 @@
@SystemApi
@TestApi
public static void removeOnPropertyChangedListener(
- OnPropertyChangedListener onPropertyChangedListener) {
+ @NonNull OnPropertyChangedListener onPropertyChangedListener) {
+ Preconditions.checkNotNull(onPropertyChangedListener);
synchronized (sLock) {
- if (sListeners.containsKey(onPropertyChangedListener)) {
- decrementNamespace(sListeners.get(onPropertyChangedListener).first);
- sListeners.remove(onPropertyChangedListener);
+ if (sSingleListeners.containsKey(onPropertyChangedListener)) {
+ decrementNamespace(sSingleListeners.get(onPropertyChangedListener).first);
+ sSingleListeners.remove(onPropertyChangedListener);
+ }
+ }
+ }
+
+ /**
+ * Remove a listener for property changes. The listener will receive no further notification of
+ * property changes.
+ *
+ * @param onPropertiesChangedListener The listener to remove.
+ * @hide
+ * @see #addOnPropertiesChangedListener(String, Executor, OnPropertiesChangedListener)
+ */
+ @SystemApi
+ @TestApi
+ public static void removeOnPropertiesChangedListener(
+ @NonNull OnPropertiesChangedListener onPropertiesChangedListener) {
+ Preconditions.checkNotNull(onPropertiesChangedListener);
+ synchronized (sLock) {
+ if (sListeners.containsKey(onPropertiesChangedListener)) {
+ decrementNamespace(sListeners.get(onPropertiesChangedListener).first);
+ sListeners.remove(onPropertiesChangedListener);
}
}
}
@@ -678,14 +764,30 @@
final String name = pathSegments.get(2);
final String value = getProperty(namespace, name);
synchronized (sLock) {
- for (final OnPropertyChangedListener listener : sListeners.keySet()) {
- if (namespace.equals(sListeners.get(listener).first)) {
- sListeners.get(listener).second.execute(new Runnable() {
+ // OnPropertiesChangedListeners
+ for (int i = 0; i < sListeners.size(); i++) {
+ if (namespace.equals(sListeners.valueAt(i).first)) {
+ final int j = i;
+ sListeners.valueAt(i).second.execute(new Runnable() {
@Override
public void run() {
Map<String, String> propertyMap = new HashMap(1);
propertyMap.put(name, value);
- listener.onPropertiesChanged(new Properties(namespace, propertyMap));
+ sListeners.keyAt(j)
+ .onPropertiesChanged(new Properties(namespace, propertyMap));
+ }
+
+ });
+ }
+ }
+ // OnPropertyChangedListeners
+ for (int i = 0; i < sSingleListeners.size(); i++) {
+ if (namespace.equals(sSingleListeners.valueAt(i).first)) {
+ final int j = i;
+ sSingleListeners.valueAt(i).second.execute(new Runnable() {
+ @Override
+ public void run() {
+ sSingleListeners.keyAt(j).onPropertyChanged(namespace, name, value);
}
});
@@ -695,7 +797,7 @@
}
/**
- * Interface for monitoring to properties.
+ * Interface for monitoring single property changes.
* <p>
* Override {@link #onPropertyChanged(String, String, String)} to handle callbacks for changes.
*
@@ -712,22 +814,25 @@
* @param value The new value of the property which has changed.
*/
void onPropertyChanged(String namespace, String name, String value);
+ }
+ /**
+ * Interface for monitoring changes to properties.
+ * <p>
+ * Override {@link #onPropertiesChanged(Properties)} to handle callbacks for changes.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public interface OnPropertiesChangedListener {
/**
* Called when one or more properties have changed.
*
* @param properties Contains the complete collection of properties which have changed for a
- * single namespace.
+ * single namespace.
*/
- default void onPropertiesChanged(@NonNull Properties properties) {
- // During the transitional period, this method calls the old one to ensure legacy
- // callers continue to function as expected. Ignore this if you are implementing it for
- // yourself.
- String namespace = properties.getNamespace();
- for (String name : properties.getKeyset()) {
- onPropertyChanged(namespace, name, properties.getString(name, null));
- }
- }
+ void onPropertiesChanged(@NonNull Properties properties);
}
/**
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index cb794ad..2143a0d 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -471,10 +471,12 @@
* the most recently modified documents.
* <p>
* If this method is overriden by the concrete DocumentsProvider and
- * QUERY_ARGS_LIMIT is specified with a nonnegative int under queryArgs, the
- * result will be limited by that number and QUERY_ARG_LIMIT will be
- * specified under EXTRA_HONORED_ARGS. Otherwise, a default 64 limit will
- * be used and no QUERY_ARG* will be specified under EXTRA_HONORED_ARGS.
+ * {@link ContentResolver#QUERY_ARG_LIMIT} is specified with a nonnegative
+ * int under queryArgs, the result will be limited by that number and
+ * {@link ContentResolver#QUERY_ARG_LIMIT} will be specified under
+ * {@link ContentResolver#EXTRA_HONORED_ARGS}. Otherwise, a default 64 limit
+ * will be used and no QUERY_ARG* will be specified under
+ * {@link ContentResolver#EXTRA_HONORED_ARGS}.
* <p>
* Recent documents do not support change notifications.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ecbd673..4836e6c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1686,14 +1686,7 @@
* Input: Nothing.
*
* <p>
- * Output: {@link android.app.Activity#RESULT_OK} if user enabled Content Capture,
- * {@link android.app.Activity#RESULT_CANCELED} if user disabled it, cancelled, or if the caller
- * is not the Content Capture service associated with the user.
- *
- * <p>
- * <b>NOTE: </b> Caller should call
- * {@link android.view.contentcapture.ContentCaptureManager#isContentCaptureFeatureEnabled()}
- * first to check whether the feature is already enabled.
+ * Output: Nothing
*
* @hide
*/
@@ -7557,6 +7550,15 @@
private static final Validator SKIP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
/**
+ * Count of successful gestures.
+ * @hide
+ */
+ public static final String SKIP_GESTURE_COUNT = "skip_gesture_count";
+
+ private static final Validator SKIP_GESTURE_COUNT_VALIDATOR =
+ NON_NEGATIVE_INTEGER_VALIDATOR;
+
+ /**
* Gesture that silences sound (alarms, notification, calls).
* @hide
*/
@@ -7565,6 +7567,34 @@
private static final Validator SILENCE_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
/**
+ * Count of successful silence alarms gestures.
+ * @hide
+ */
+ public static final String SILENCE_ALARMS_GESTURE_COUNT = "silence_alarms_gesture_count";
+
+ /**
+ * Count of successful silence timer gestures.
+ * @hide
+ */
+ public static final String SILENCE_TIMER_GESTURE_COUNT = "silence_timer_gesture_count";
+
+ /**
+ * Count of successful silence call gestures.
+ * @hide
+ */
+ public static final String SILENCE_CALL_GESTURE_COUNT = "silence_call_gesture_count";
+
+ /**
+ * Count of successful silence notification gestures.
+ * @hide
+ */
+ public static final String SILENCE_NOTIFICATION_GESTURE_COUNT =
+ "silence_notification_gesture_count";
+
+ private static final Validator SILENCE_GESTURE_COUNT_VALIDATOR =
+ NON_NEGATIVE_INTEGER_VALIDATOR;
+
+ /**
* The current night mode that has been selected by the user. Owned
* and controlled by UiModeManagerService. Constants are as per
* UiModeManager.
@@ -8011,6 +8041,16 @@
BOOLEAN_VALIDATOR;
/**
+ * Whether or not face unlock dismisses the keyguard.
+ * @hide
+ */
+ public static final String FACE_UNLOCK_DISMISSES_KEYGUARD =
+ "face_unlock_dismisses_keyguard";
+
+ private static final Validator FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
+ /**
* Whether or not face unlock is allowed for apps (through BiometricPrompt).
* @hide
*/
@@ -8684,6 +8724,7 @@
NFC_PAYMENT_DEFAULT_COMPONENT,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
FACE_UNLOCK_KEYGUARD_ENABLED,
+ FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_APP_ENABLED,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
ASSIST_GESTURE_ENABLED,
@@ -8723,6 +8764,11 @@
SILENCE_GESTURE,
THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
AWARE_ENABLED,
+ SKIP_GESTURE_COUNT,
+ SILENCE_ALARMS_GESTURE_COUNT,
+ SILENCE_NOTIFICATION_GESTURE_COUNT,
+ SILENCE_CALL_GESTURE_COUNT,
+ SILENCE_TIMER_GESTURE_COUNT,
};
/**
@@ -8845,6 +8891,8 @@
VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
+ VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
+ FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
@@ -8897,6 +8945,11 @@
VALIDATORS.put(THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
THEME_CUSTOMIZATION_OVERLAY_PACKAGES_VALIDATOR);
VALIDATORS.put(AWARE_ENABLED, AWARE_ENABLED_VALIDATOR);
+ VALIDATORS.put(SKIP_GESTURE_COUNT, SKIP_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_ALARMS_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_TIMER_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
}
/**
@@ -14952,6 +15005,17 @@
"android.settings.panel.action.NFC";
/**
+ * Activity Action: Show a settings dialog containing controls for Wifi.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_WIFI =
+ "android.settings.panel.action.WIFI";
+
+ /**
* Activity Action: Show a settings dialog containing all volume streams.
* <p>
* Input: Nothing.
diff --git a/core/java/android/provider/TEST_MAPPING b/core/java/android/provider/TEST_MAPPING
deleted file mode 100644
index 7486f7f..0000000
--- a/core/java/android/provider/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "FrameworksCoreTests",
- "options": [
- {
- "include-filter": "android.provider.SettingsBackupTest"
- }
- ]
- }
- ]
-}
diff --git a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
deleted file mode 100644
index 40852ea..0000000
--- a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2018 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.rolecontrollerservice;
-
-import android.app.role.IRoleManagerCallback;
-
-/**
- * @hide
- */
-oneway interface IRoleControllerService {
-
- void onAddRoleHolder(in String roleName, in String packageName, int flags,
- in IRoleManagerCallback callback);
-
- void onRemoveRoleHolder(in String roleName, in String packageName, int flags,
- in IRoleManagerCallback callback);
-
- void onClearRoleHolders(in String roleName, int flags, in IRoleManagerCallback callback);
-
- void onGrantDefaultRoles(in IRoleManagerCallback callback);
-
- void onSmsKillSwitchToggled(boolean smsRestrictionEnabled);
-}
diff --git a/core/java/android/rolecontrollerservice/RoleControllerService.java b/core/java/android/rolecontrollerservice/RoleControllerService.java
deleted file mode 100644
index c846b07..0000000
--- a/core/java/android/rolecontrollerservice/RoleControllerService.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2018 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.rolecontrollerservice;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.app.role.IRoleManagerCallback;
-import android.app.role.RoleManager;
-import android.app.role.RoleManagerCallback;
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.Log;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.concurrent.Executor;
-
-/**
- * Abstract base class for the role controller service.
- * <p>
- * Subclass should implement the business logic for role management, including enforcing role
- * requirements and granting or revoking relevant privileges of roles. This class can only be
- * implemented by the permission controller app which is registered in {@code PackageManager}.
- *
- * @hide
- */
-@SystemApi
-public abstract class RoleControllerService extends Service {
-
- private static final String LOG_TAG = RoleControllerService.class.getSimpleName();
-
- /**
- * The {@link Intent} that must be declared as handled by the service. The service should also
- * require the {@link android.Manifest.permission#BIND_ROLE_CONTROLLER_SERVICE} permission so
- * that other applications can not abuse it.
- */
- public static final String SERVICE_INTERFACE =
- "android.rolecontrollerservice.RoleControllerService";
-
- @Nullable
- @Override
- public final IBinder onBind(@Nullable Intent intent) {
- return new IRoleControllerService.Stub() {
-
- @Override
- public void onAddRoleHolder(String roleName, String packageName, int flags,
- IRoleManagerCallback callback) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName,
- "packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
- RoleControllerService.this.onAddRoleHolder(roleName, packageName, flags,
- new RoleManagerCallbackDelegate(callback));
- }
-
- @Override
- public void onRemoveRoleHolder(String roleName, String packageName, int flags,
- IRoleManagerCallback callback) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName,
- "packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
- RoleControllerService.this.onRemoveRoleHolder(roleName, packageName, flags,
- new RoleManagerCallbackDelegate(callback));
- }
-
- @Override
- public void onClearRoleHolders(String roleName, int flags,
- IRoleManagerCallback callback) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
- RoleControllerService.this.onClearRoleHolders(roleName, flags,
- new RoleManagerCallbackDelegate(callback));
- }
-
- @Override
- public void onGrantDefaultRoles(IRoleManagerCallback callback) {
- Preconditions.checkNotNull(callback, "callback cannot be null");
- RoleControllerService.this.onGrantDefaultRoles(new RoleManagerCallbackDelegate(
- callback));
- }
-
- @Override
- public void onSmsKillSwitchToggled(boolean smsRestrictionEnabled) {
- RoleControllerService.this.onSmsKillSwitchToggled(smsRestrictionEnabled);
- }
- };
- }
-
- /**
- * Add a specific application to the holders of a role. If the role is exclusive, the previous
- * holder will be replaced.
- * <p>
- * Implementation should enforce the role requirements and grant or revoke the relevant
- * privileges of roles.
- *
- * @param roleName the name of the role to add the role holder for
- * @param packageName the package name of the application to add to the role holders
- * @param flags optional behavior flags
- * @param callback the callback for whether this call is successful
- *
- * @see RoleManager#addRoleHolderAsUser(String, String, int, UserHandle, Executor,
- * RoleManagerCallback)
- */
- public abstract void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
- @RoleManager.ManageHoldersFlags int flags, @NonNull RoleManagerCallback callback);
-
- /**
- * Remove a specific application from the holders of a role.
- *
- * @param roleName the name of the role to remove the role holder for
- * @param packageName the package name of the application to remove from the role holders
- * @param flags optional behavior flags
- * @param callback the callback for whether this call is successful
- *
- * @see RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, Executor,
- * RoleManagerCallback)
- */
- public abstract void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
- @RoleManager.ManageHoldersFlags int flags, @NonNull RoleManagerCallback callback);
-
- /**
- * Remove all holders of a role.
- *
- * @param roleName the name of the role to remove role holders for
- * @param flags optional behavior flags
- * @param callback the callback for whether this call is successful
- *
- * @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor,
- * RoleManagerCallback)
- */
- public abstract void onClearRoleHolders(@NonNull String roleName,
- @RoleManager.ManageHoldersFlags int flags, @NonNull RoleManagerCallback callback);
-
- /**
- * Cleanup appop/permissions state in response to sms kill switch toggle
- *
- * @param smsRestrictionEnabled whether kill switch was turned on
- */
- //STOPSHIP: remove this api before shipping a final version
- public abstract void onSmsKillSwitchToggled(boolean smsRestrictionEnabled);
-
- /**
- * Called by system to grant default permissions and roles.
- * <p>
- * This is typically when creating a new user or upgrading either system or
- * permission controller package
- *
- * @param callback the callback for whether this call is successful
- */
- public abstract void onGrantDefaultRoles(@NonNull RoleManagerCallback callback);
-
- private static class RoleManagerCallbackDelegate implements RoleManagerCallback {
-
- private IRoleManagerCallback mCallback;
-
- RoleManagerCallbackDelegate(IRoleManagerCallback callback) {
- mCallback = callback;
- }
-
- @Override
- public void onSuccess() {
- try {
- mCallback.onSuccess();
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Error calling onSuccess() callback");
- }
- }
-
- @Override
- public void onFailure() {
- try {
- mCallback.onFailure();
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Error calling onFailure() callback");
- }
- }
- }
-}
diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java
index 3b7392f..6629233 100644
--- a/core/java/android/service/carrier/CarrierIdentifier.java
+++ b/core/java/android/service/carrier/CarrierIdentifier.java
@@ -55,7 +55,7 @@
private @Nullable String mGid1;
private @Nullable String mGid2;
private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
- private int mPreciseCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+ private int mSpecificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi,
@Nullable String gid1, @Nullable String gid2) {
@@ -72,12 +72,12 @@
* @param gid2 group id level 2
* @param carrierid carrier unique identifier {@link TelephonyManager#getSimCarrierId()}, used
* to uniquely identify the carrier and look up the carrier configurations.
- * @param preciseCarrierId precise carrier identifier
- * {@link TelephonyManager#getSimPreciseCarrierId()}
+ * @param specificCarrierId specific carrier identifier
+ * {@link TelephonyManager#getSimSpecificCarrierId()}
*/
public CarrierIdentifier(@NonNull String mcc, @NonNull String mnc, @Nullable String spn,
@Nullable String imsi, @Nullable String gid1, @Nullable String gid2,
- int carrierid, int preciseCarrierId) {
+ int carrierid, int specificCarrierId) {
mMcc = mcc;
mMnc = mnc;
mSpn = spn;
@@ -85,7 +85,7 @@
mGid1 = gid1;
mGid2 = gid2;
mCarrierId = carrierid;
- mPreciseCarrierId = preciseCarrierId;
+ mSpecificCarrierId = specificCarrierId;
}
/**
@@ -162,11 +162,17 @@
}
/**
- * Returns the precise carrier id.
- * @see TelephonyManager#getSimPreciseCarrierId()
+ * A specific carrier ID returns the fine-grained carrier ID of the current subscription.
+ * It can represent the fact that a carrier may be in effect an aggregation of other carriers
+ * (ie in an MVNO type scenario) where each of these specific carriers which are used to make
+ * up the actual carrier service may have different carrier configurations.
+ * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
+ * different carrier configuration for different service offering such as a prepaid plan.
+ *
+ * @see TelephonyManager#getSimSpecificCarrierId()
*/
- public int getPreciseCarrierId() {
- return mPreciseCarrierId;
+ public int getSpecificCarrierId() {
+ return mSpecificCarrierId;
}
@Override
@@ -186,12 +192,12 @@
&& Objects.equals(mGid1, that.mGid1)
&& Objects.equals(mGid2, that.mGid2)
&& Objects.equals(mCarrierId, that.mCarrierId)
- && Objects.equals(mPreciseCarrierId, that.mPreciseCarrierId);
+ && Objects.equals(mSpecificCarrierId, that.mSpecificCarrierId);
}
@Override
public int hashCode(){
- return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mCarrierId, mPreciseCarrierId);
+ return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mCarrierId, mSpecificCarrierId);
}
@Override
@@ -208,7 +214,7 @@
out.writeString(mGid1);
out.writeString(mGid2);
out.writeInt(mCarrierId);
- out.writeInt(mPreciseCarrierId);
+ out.writeInt(mSpecificCarrierId);
}
@Override
@@ -221,7 +227,7 @@
+ ",gid1=" + mGid1
+ ",gid2=" + mGid2
+ ",carrierid=" + mCarrierId
- + ",mPreciseCarrierId=" + mPreciseCarrierId
+ + ",specificCarrierId=" + mSpecificCarrierId
+ "}";
}
@@ -234,7 +240,7 @@
mGid1 = in.readString();
mGid2 = in.readString();
mCarrierId = in.readInt();
- mPreciseCarrierId = in.readInt();
+ mSpecificCarrierId = in.readInt();
}
/** @hide */
diff --git a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
index 2814300..45a8466 100644
--- a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
+++ b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
@@ -54,8 +54,8 @@
* The action for the intent used to define the content suggestions service.
*
* <p>To be supported, the service must also require the
- * * {@link android.Manifest.permission#BIND_CONTENT_SUGGESTIONS_SERVICE} permission so
- * * that other applications can not abuse it.
+ * * {@link android.Manifest.permission#BIND_CONTENT_SUGGESTIONS_SERVICE} permission so
+ * * that other applications can not abuse it.
*/
public static final String SERVICE_INTERFACE =
"android.service.contentsuggestions.ContentSuggestionsService";
@@ -72,7 +72,7 @@
}
mHandler.sendMessage(
- obtainMessage(ContentSuggestionsService::processContextImage,
+ obtainMessage(ContentSuggestionsService::onProcessContextImage,
ContentSuggestionsService.this, taskId,
wrappedBuffer,
imageContextRequestExtras));
@@ -81,7 +81,8 @@
@Override
public void suggestContentSelections(SelectionsRequest request,
ISelectionsCallback callback) {
- mHandler.sendMessage(obtainMessage(ContentSuggestionsService::suggestContentSelections,
+ mHandler.sendMessage(obtainMessage(
+ ContentSuggestionsService::onSuggestContentSelections,
ContentSuggestionsService.this, request, wrapSelectionsCallback(callback)));
}
@@ -89,14 +90,15 @@
@Override
public void classifyContentSelections(ClassificationsRequest request,
IClassificationsCallback callback) {
- mHandler.sendMessage(obtainMessage(ContentSuggestionsService::classifyContentSelections,
+ mHandler.sendMessage(obtainMessage(
+ ContentSuggestionsService::onClassifyContentSelections,
ContentSuggestionsService.this, request, wrapClassificationCallback(callback)));
}
@Override
public void notifyInteraction(String requestId, Bundle interaction) {
mHandler.sendMessage(
- obtainMessage(ContentSuggestionsService::notifyInteraction,
+ obtainMessage(ContentSuggestionsService::onNotifyInteraction,
ContentSuggestionsService.this, requestId, interaction));
}
};
@@ -122,25 +124,41 @@
* Called by the system to provide the snapshot for the task associated with the given
* {@param taskId}.
*/
- public abstract void processContextImage(
- int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras);
+ public void onProcessContextImage(
+ int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras) {
+ // TODO(b/127532182): remove after next prebuilt drop.
+ processContextImage(taskId, contextImage, extras);
+ }
/**
- * Called by a client app to make a request for content selections.
+ * Content selections have been request through {@link ContentSuggestionsManager}, implementer
+ * should reply on the callback with selections.
*/
- public abstract void suggestContentSelections(@NonNull SelectionsRequest request,
- @NonNull ContentSuggestionsManager.SelectionsCallback callback);
+ public void onSuggestContentSelections(@NonNull SelectionsRequest request,
+ @NonNull ContentSuggestionsManager.SelectionsCallback callback) {
+ // TODO(b/127532182): remove after next prebuilt drop.
+ suggestContentSelections(request, callback);
+ }
/**
- * Called by a client app to classify the provided content selections.
+ * Content classifications have been request through {@link ContentSuggestionsManager},
+ * implementer should reply on the callback with classifications.
*/
- public abstract void classifyContentSelections(@NonNull ClassificationsRequest request,
- @NonNull ContentSuggestionsManager.ClassificationsCallback callback);
+ public void onClassifyContentSelections(@NonNull ClassificationsRequest request,
+ @NonNull ContentSuggestionsManager.ClassificationsCallback callback) {
+ // TODO(b/127532182): remove after next prebuilt drop.
+ classifyContentSelections(request, callback);
+ }
/**
- * Called by a client app to report an interaction.
+ * User interactions have been reported through {@link ContentSuggestionsManager}, implementer
+ * should handle those interactions.
*/
- public abstract void notifyInteraction(@NonNull String requestId, @NonNull Bundle interaction);
+ public void onNotifyInteraction(
+ @NonNull String requestId, @NonNull Bundle interaction) {
+ // TODO(b/127532182): remove after next prebuilt drop.
+ notifyInteraction(requestId, interaction);
+ }
private ContentSuggestionsManager.SelectionsCallback wrapSelectionsCallback(
ISelectionsCallback callback) {
@@ -163,4 +181,42 @@
}
});
}
+
+
+ /**
+ * For temporary compat reason, remove with b/127532182
+ * @deprecated use {@link #onProcessContextImage(int, Bitmap, Bundle)} instead.
+ */
+ @Deprecated
+ public void processContextImage(
+ int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras) {
+ }
+
+ /**
+ * For temporary compat reason, remove with b/127532182
+ * @deprecated use {@link #onSuggestContentSelections(SelectionsRequest,
+ * ContentSuggestionsManager.SelectionsCallback)} instead.
+ */
+ @Deprecated
+ public void suggestContentSelections(@NonNull SelectionsRequest request,
+ @NonNull ContentSuggestionsManager.SelectionsCallback callback) {
+ }
+
+ /**
+ * For temporary compat reason, remove with b/127532182
+ * @deprecated use {@link #onClassifyContentSelections(ClassificationsRequest,
+ * ContentSuggestionsManager.ClassificationsCallback)} instead.
+ */
+ @Deprecated
+ public void classifyContentSelections(@NonNull ClassificationsRequest request,
+ @NonNull ContentSuggestionsManager.ClassificationsCallback callback) {
+ }
+
+ /**
+ * For temporary compat reason, remove with b/127532182
+ * @deprecated use {@link #onNotifyInteraction(String, Bundle)} instead.
+ */
+ @Deprecated
+ public void notifyInteraction(@NonNull String requestId, @NonNull Bundle interaction) {
+ }
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 87bdfe0..780b576 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -373,7 +373,10 @@
args.recycle();
Adjustment adjustment = onNotificationEnqueued(sbn, channel);
if (adjustment != null) {
- if (!isBound()) return;
+ if (!isBound()) {
+ Log.w(TAG, "MSG_ON_NOTIFICATION_ENQUEUED: service not bound, skip.");
+ return;
+ }
try {
getNotificationInterface().applyEnqueuedAdjustmentFromAssistant(
mWrapper, adjustment);
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 0836327..cc74e1a 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -16,6 +16,7 @@
package android.service.notification;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.app.Notification;
import android.app.NotificationManager;
@@ -62,9 +63,6 @@
private Context mContext; // used for inflation & icon expansion
- // Contains the basic logging data of the notification.
- private LogMaker mLogMaker;
-
/** @hide */
public StatusBarNotification(String pkg, String opPkg, int id,
String tag, int uid, int initialPid, Notification notification, UserHandle user,
@@ -299,7 +297,7 @@
* Might be different from {@link #getPackageName()} if the app owning the notification has
* a {@link NotificationManager#setNotificationDelegate(String) notification delegate}.
*/
- public String getOpPkg() {
+ public @NonNull String getOpPkg() {
return opPkg;
}
@@ -403,24 +401,15 @@
* @hide
*/
public LogMaker getLogMaker() {
- if (mLogMaker == null) {
- // Initialize fields that only change on update (so a new record).
- mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
- .setPackageName(getPackageName())
+ return new LogMaker(MetricsEvent.VIEW_UNKNOWN).setPackageName(getPackageName())
.addTaggedData(MetricsEvent.NOTIFICATION_ID, getId())
.addTaggedData(MetricsEvent.NOTIFICATION_TAG, getTag())
- .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag());
- }
- // Reset fields that can change between updates, or are used by multiple logs.
- return mLogMaker
- .clearCategory()
- .clearType()
- .clearSubtype()
- .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag())
- .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY,
- getNotification().isGroupSummary() ? 1 : 0)
- .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CATEGORY,
- getNotification().category);
+ .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag())
+ .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag())
+ .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY,
+ getNotification().isGroupSummary() ? 1 : 0)
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CATEGORY,
+ getNotification().category);
}
private String getGroupLogTag() {
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 24d746e..defe2ce 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -643,7 +643,7 @@
.setBreakStrategy(b.mBreakStrategy)
.setHyphenationFrequency(b.mHyphenationFrequency)
// TODO: Support more justification mode, e.g. letter spacing, stretching.
- .setJustified(b.mJustificationMode)
+ .setJustificationMode(b.mJustificationMode)
.setIndents(indents)
.build();
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b99336b..7747a55 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -48,7 +48,7 @@
DEFAULT_FLAGS = new HashMap<>();
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
- DEFAULT_FLAGS.put("settings_network_and_internet_v2", "false");
+ DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
DEFAULT_FLAGS.put("settings_slice_injection", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put("settings_wifi_mac_randomization", "true");
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 1382fbc..2d7e179 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -142,6 +142,10 @@
&& legacyContentInsets != null && legacyStableInsets != null) {
WindowInsets.assignCompatInsets(typeInsetsMap, legacyContentInsets);
WindowInsets.assignCompatInsets(typeMaxInsetsMap, legacyStableInsets);
+
+ // TODO: set system gesture insets based on actual system gesture area.
+ typeInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyContentInsets);
+ typeMaxInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyContentInsets);
}
for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
InsetsSource source = mSources.get(type);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 6ff699e..cb64ab1 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
@@ -193,7 +194,7 @@
*
* @param from The SurfaceControl to assosciate this Surface with
*/
- public Surface(SurfaceControl from) {
+ public Surface(@NonNull SurfaceControl from) {
copyFrom(from);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5e2aaae..998ad2a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -459,6 +459,7 @@
* Construct a new {@link SurfaceControl} with the set parameters. The builder
* remains valid.
*/
+ @NonNull
public SurfaceControl build() {
if (mWidth < 0 || mHeight < 0) {
throw new IllegalArgumentException(
@@ -477,7 +478,8 @@
*
* @param name A name to identify the Surface in debugging.
*/
- public Builder setName(String name) {
+ @NonNull
+ public Builder setName(@NonNull String name) {
mName = name;
return this;
}
@@ -488,6 +490,7 @@
* @param width The buffer width in pixels.
* @param height The buffer height in pixels.
*/
+ @NonNull
public Builder setBufferSize(@IntRange(from = 0) int width,
@IntRange(from = 0) int height) {
if (width < 0 || height < 0) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fdbbe31..7fcce6d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5974,20 +5974,28 @@
* this {@link View}.
*/
@NonNull
- public List<Integer> getAttributeResolutionStack(@AttrRes int attribute) {
- ArrayList<Integer> stack = new ArrayList<>();
- if (!sDebugViewAttributes || mAttributeResolutionStacks == null) {
- return stack;
- }
- if (mSourceLayoutId != ID_NULL) {
- stack.add(mSourceLayoutId);
+ public int[] getAttributeResolutionStack(@AttrRes int attribute) {
+ if (!sDebugViewAttributes
+ || mAttributeResolutionStacks == null
+ || mAttributeResolutionStacks.get(attribute) == null) {
+ return new int[0];
}
int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
- if (attributeResolutionStack == null) {
- return stack;
+ int stackSize = attributeResolutionStack.length;
+ if (mSourceLayoutId != ID_NULL) {
+ stackSize++;
+ }
+
+ int currentIndex = 0;
+ int[] stack = new int[stackSize];
+
+ if (mSourceLayoutId != ID_NULL) {
+ stack[currentIndex] = mSourceLayoutId;
+ currentIndex++;
}
for (int i = 0; i < attributeResolutionStack.length; i++) {
- stack.add(attributeResolutionStack[i]);
+ stack[currentIndex] = attributeResolutionStack[i];
+ currentIndex++;
}
return stack;
}
@@ -6138,7 +6146,9 @@
/**
* Stores debugging information about attributes. This should be called in a constructor by
- * every custom {@link View} that uses a custom styleable.
+ * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
+ * then the custom attributes used by this view will not be visible in layout inspection tools.
+ *
* @param context Context under which this view is created.
* @param styleable A reference to styleable array R.styleable.Foo
* @param attrs AttributeSet used to construct this view.
@@ -24106,7 +24116,7 @@
*
* @param matrix input matrix to modify
*/
- public void transformMatrixToGlobal(Matrix matrix) {
+ public void transformMatrixToGlobal(@NonNull Matrix matrix) {
final ViewParent parent = mParent;
if (parent instanceof View) {
final View vp = (View) parent;
@@ -24131,7 +24141,7 @@
*
* @param matrix input matrix to modify
*/
- public void transformMatrixToLocal(Matrix matrix) {
+ public void transformMatrixToLocal(@NonNull Matrix matrix) {
final ViewParent parent = mParent;
if (parent instanceof View) {
final View vp = (View) parent;
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index f3bbca3..f1a992c 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -27,6 +27,7 @@
import static android.view.WindowInsets.Type.all;
import static android.view.WindowInsets.Type.compatSystemInsets;
import static android.view.WindowInsets.Type.indexOf;
+import static android.view.WindowInsets.Type.systemGestures;
import android.annotation.IntDef;
import android.annotation.IntRange;
@@ -220,6 +221,8 @@
}
Insets[] typeInsetMap = new Insets[SIZE];
assignCompatInsets(typeInsetMap, insets);
+ // TODO: set system gesture insets based on actual system gesture area.
+ typeInsetMap[indexOf(systemGestures())] = Insets.of(insets);
return typeInsetMap;
}
@@ -229,7 +232,6 @@
static void assignCompatInsets(Insets[] typeInsetMap, Rect insets) {
typeInsetMap[indexOf(TOP_BAR)] = Insets.of(0, insets.top, 0, 0);
typeInsetMap[indexOf(SIDE_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom);
- typeInsetMap[indexOf(SYSTEM_GESTURES)] = Insets.of(insets);
}
private static boolean[] createCompatVisibilityMap(@Nullable Insets[] typeInsetMap) {
@@ -675,6 +677,7 @@
public String toString() {
return "WindowInsets{systemWindowInsets=" + getSystemWindowInsets()
+ " stableInsets=" + getStableInsets()
+ + " sysGestureInsets=" + getSystemGestureInsets()
+ (mDisplayCutout != null ? " cutout=" + mDisplayCutout : "")
+ (isRound() ? " round" : "")
+ "}";
diff --git a/core/java/android/view/contentcapture/ContentCaptureHelper.java b/core/java/android/view/contentcapture/ContentCaptureHelper.java
index 6e84ff0..6bc3829 100644
--- a/core/java/android/view/contentcapture/ContentCaptureHelper.java
+++ b/core/java/android/view/contentcapture/ContentCaptureHelper.java
@@ -20,7 +20,6 @@
import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_OFF;
import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_VERBOSE;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Build;
import android.provider.DeviceConfig;
@@ -48,21 +47,6 @@
}
/**
- * Gets the value of a device config property from the Content Capture namespace.
- */
- public static int getIntDeviceConfigProperty(@NonNull String key, int defaultValue) {
- final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE, key);
- if (value == null) return defaultValue;
-
- try {
- return Integer.parseInt(value);
- } catch (Exception e) {
- Log.w(TAG, "error parsing value (" + value + ") of property " + key + ": " + e);
- return defaultValue;
- }
- }
-
- /**
* Gets the default logging level for the device.
*/
@LoggingLevel
@@ -75,8 +59,8 @@
*/
public static void setLoggingLevel() {
final int defaultLevel = getDefaultLoggingLevel();
- final int level = getIntDeviceConfigProperty(DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
- defaultLevel);
+ final int level = DeviceConfig.getInt(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL, defaultLevel);
setLoggingLevel(level);
}
diff --git a/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java b/core/java/android/view/inspector/StaticInspectionCompanionProvider.java
similarity index 76%
rename from core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java
rename to core/java/android/view/inspector/StaticInspectionCompanionProvider.java
index d4b7e85..42a892d 100644
--- a/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java
+++ b/core/java/android/view/inspector/StaticInspectionCompanionProvider.java
@@ -20,15 +20,15 @@
import android.annotation.Nullable;
/**
- * An inspection companion provider that loads pre-generated inspection companions
+ * An inspection companion provider that finds companions as inner classes or generated code.
*
* @see android.processor.view.inspector.PlatformInspectableProcessor
*/
-public class GeneratedInspectionCompanionProvider implements InspectionCompanionProvider {
+public class StaticInspectionCompanionProvider implements InspectionCompanionProvider {
/**
- * The suffix used for the generated class
+ * The suffix used for the generated classes and inner classes
*/
- private static final String COMPANION_SUFFIX = "$$InspectionCompanion";
+ private static final String COMPANION_SUFFIX = "$InspectionCompanion";
@Override
@Nullable
@@ -39,7 +39,12 @@
try {
final Class<InspectionCompanion<T>> companionClass =
(Class<InspectionCompanion<T>>) cls.getClassLoader().loadClass(companionName);
- return companionClass.newInstance();
+
+ if (InspectionCompanion.class.isAssignableFrom(companionClass)) {
+ return companionClass.newInstance();
+ } else {
+ return null;
+ }
} catch (ClassNotFoundException e) {
return null;
} catch (IllegalAccessException e) {
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
index 78ed9bf..dc75212 100644
--- a/core/java/android/view/textclassifier/ConversationActions.java
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -318,19 +318,15 @@
private final List<String> mHints;
@Nullable
private String mCallingPackageName;
- @Nullable
- private final String mConversationId;
private Request(
@NonNull List<Message> conversation,
@NonNull TextClassifier.EntityConfig typeConfig,
int maxSuggestions,
- String conversationId,
@Nullable @Hint List<String> hints) {
mConversation = Preconditions.checkNotNull(conversation);
mTypeConfig = Preconditions.checkNotNull(typeConfig);
mMaxSuggestions = maxSuggestions;
- mConversationId = conversationId;
mHints = hints;
}
@@ -339,7 +335,6 @@
in.readParcelableList(conversation, null);
TextClassifier.EntityConfig typeConfig = in.readParcelable(null);
int maxSuggestions = in.readInt();
- String conversationId = in.readString();
List<String> hints = new ArrayList<>();
in.readStringList(hints);
String callingPackageName = in.readString();
@@ -348,7 +343,6 @@
conversation,
typeConfig,
maxSuggestions,
- conversationId,
hints);
request.setCallingPackageName(callingPackageName);
return request;
@@ -359,7 +353,6 @@
parcel.writeParcelableList(mConversation, flags);
parcel.writeParcelable(mTypeConfig, flags);
parcel.writeInt(mMaxSuggestions);
- parcel.writeString(mConversationId);
parcel.writeStringList(mHints);
parcel.writeString(mCallingPackageName);
}
@@ -403,16 +396,6 @@
return mMaxSuggestions;
}
- /**
- * Return an unique identifier of the conversation that is generating actions for. This
- * identifier is unique within the calling package only, so use it with
- * {@link #getCallingPackageName()}.
- */
- @Nullable
- public String getConversationId() {
- return mConversationId;
- }
-
/** Returns an immutable list of hints */
@Nullable
@Hint
@@ -448,8 +431,6 @@
private TextClassifier.EntityConfig mTypeConfig;
private int mMaxSuggestions = -1;
@Nullable
- private String mConversationId;
- @Nullable
@Hint
private List<String> mHints;
@@ -490,15 +471,6 @@
return this;
}
- /**
- * Sets an unique identifier of the conversation that is generating actions for.
- */
- @NonNull
- public Builder setConversationId(@Nullable String conversationId) {
- mConversationId = conversationId;
- return this;
- }
-
/** Builds the {@link Request} object. */
@NonNull
public Request build() {
@@ -508,7 +480,6 @@
? new TextClassifier.EntityConfig.Builder().build()
: mTypeConfig,
mMaxSuggestions,
- mConversationId,
mHints == null
? Collections.emptyList()
: Collections.unmodifiableList(mHints));
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 8b98469..494eb03 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -231,34 +231,34 @@
FORCE_DARK_ON
})
@Retention(RetentionPolicy.SOURCE)
- public @interface ForceDarkMode {}
+ public @interface ForceDark {}
/**
- * Used with {@link #setForceDarkMode}
+ * Used with {@link #setForceDark}
*
* Disable force dark, irrespective of the force dark mode of the WebView parent. In this mode,
* WebView content will always be rendered as-is, regardless of whether native views are being
* automatically darkened.
*/
- public static final int FORCE_DARK_OFF = -1;
+ public static final int FORCE_DARK_OFF = 0;
/**
- * Used with {@link #setForceDarkMode}
+ * Used with {@link #setForceDark}
*
* Enable force dark, dependent on the state of the WebView parent. If the WebView parent view
* is being automatically rendered in dark mode, then WebView content will be rendered so as to
* emulate a dark theme. WebViews that are not attached to the view hierarchy will not be
* inverted.
*/
- public static final int FORCE_DARK_AUTO = 0;
+ public static final int FORCE_DARK_AUTO = 1;
/**
- * Used with {@link #setForceDarkMode}
+ * Used with {@link #setForceDark}
*
* Unconditionally enable force dark. In this mode WebView content will always be rendered so
* as to emulate a dark theme.
*/
- public static final int FORCE_DARK_ON = +1;
+ public static final int FORCE_DARK_ON = 2;
/**
* Enables dumping the pages navigation cache to a text file. The default
@@ -1467,7 +1467,7 @@
/**
* Set the force dark mode for this WebView.
*/
- public void setForceDarkMode(@ForceDarkMode int forceDarkMode) {
+ public void setForceDark(@ForceDark int forceDark) {
// Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
}
@@ -1476,7 +1476,7 @@
*
* @return the currently set force dark mode.
*/
- public @ForceDarkMode int getForceDarkMode() {
+ public @ForceDark int getForceDark() {
// Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
return FORCE_DARK_AUTO;
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3555822..034cabd 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1704,7 +1704,7 @@
/**
- * Gets the WebView renderer associated with this WebView.
+ * Gets a handle to the WebView renderer process associated with this WebView.
*
* <p>In {@link android.os.Build.VERSION_CODES#O} and above, WebView may
* run in "multiprocess" mode. In multiprocess mode, rendering of web
@@ -1717,67 +1717,70 @@
* handle to the renderer process associated with the WebView, which can
* be used to control the renderer process.
*
- * @return the {@link WebViewRenderer} renderer handle associated
+ * @return the {@link WebViewRenderProcess} renderer handle associated
* with this {@link WebView}, or {@code null} if
* WebView is not runing in multiprocess mode.
*/
@Nullable
- public WebViewRenderer getWebViewRenderer() {
+ public WebViewRenderProcess getWebViewRenderProcess() {
checkThread();
- return mProvider.getWebViewRenderer();
+ return mProvider.getWebViewRenderProcess();
}
/**
* Sets the renderer client object associated with this WebView.
*
* <p>The renderer client encapsulates callbacks relevant to WebView renderer
- * state. See {@link WebViewRendererClient} for details.
+ * state. See {@link WebViewRenderProcessClient} for details.
*
* <p>Although many WebView instances may share a single underlying
* renderer, and renderers may live either in the application
* process, or in a sandboxed process that is isolated from the
- * application process, instances of {@link WebViewRendererClient}
+ * application process, instances of {@link WebViewRenderProcessClient}
* are set per-WebView. Callbacks represent renderer events from
* the perspective of this WebView, and may or may not be correlated
* with renderer events affecting other WebViews.
*
- * @param executor the Executor on which {@link WebViewRendererClient} callbacks will execute.
- * @param webViewRendererClient the {@link WebViewRendererClient} object.
+ * @param executor the Executor on which {@link WebViewRenderProcessClient}
+ * callbacks will execute.
+ * @param webViewRenderProcessClient the {@link WebViewRenderProcessClient}
+ * object.
*/
- public void setWebViewRendererClient(
+ public void setWebViewRenderProcessClient(
@NonNull @CallbackExecutor Executor executor,
- @NonNull WebViewRendererClient webViewRendererClient) {
+ @NonNull WebViewRenderProcessClient webViewRenderProcessClient) {
checkThread();
- mProvider.setWebViewRendererClient(executor, webViewRendererClient);
+ mProvider.setWebViewRenderProcessClient(
+ executor, webViewRenderProcessClient);
}
/**
* Sets the renderer client object associated with this WebView.
*
- * See {@link #setWebViewRendererClient(Executor,WebViewRendererClient)} for details.
+ * See {@link #setWebViewRenderProcessClient(Executor,WebViewRenderProcessClient)} for details.
*
- * <p> {@link WebViewRendererClient} callbacks will run on the thread that this WebView was
+ * <p> {@link WebViewRenderProcessClient} callbacks will run on the thread that this WebView was
* initialized on.
*
- * @param webViewRendererClient the {@link WebViewRendererClient} object.
+ * @param webViewRenderProcessClient the {@link WebViewRenderProcessClient} object.
*/
- public void setWebViewRendererClient(
- @Nullable WebViewRendererClient webViewRendererClient) {
+ public void setWebViewRenderProcessClient(
+ @Nullable WebViewRenderProcessClient webViewRenderProcessClient) {
checkThread();
- mProvider.setWebViewRendererClient(null, webViewRendererClient);
+ mProvider.setWebViewRenderProcessClient(null, webViewRenderProcessClient);
}
/**
* Gets the renderer client object associated with this WebView.
*
- * @return the {@link WebViewRendererClient} object associated with this WebView, if one has
- * been set via {@link #setWebViewRendererClient(WebViewRendererClient)} or {@code null}
- * otherwise.
+ * @return the {@link WebViewRenderProcessClient} object associated with this WebView, if one
+ * has been set via {@link #setWebViewRenderProcessClient(WebViewRenderProcessClient)}
+ * or {@code null} otherwise.
*/
@Nullable
- public WebViewRendererClient getWebViewRendererClient() {
+ public WebViewRenderProcessClient getWebViewRenderProcessClient() {
checkThread();
- return mProvider.getWebViewRendererClient();
+ return mProvider.getWebViewRenderProcessClient();
}
/**
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 090640e..150fa88 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -102,9 +102,11 @@
/**
* Notify the host application that a page has finished loading. This method
- * is called only for main frame. When onPageFinished() is called, the
- * rendering picture may not be updated yet. To get the notification for the
- * new Picture, use {@link WebView.PictureListener#onNewPicture}.
+ * is called only for main frame. Receiving an {@code onPageFinished()} callback does not
+ * guarantee that the next frame drawn by WebView will reflect the state of the DOM at this
+ * point. In order to be notified that the current DOM state is ready to be rendered, request a
+ * visual state callback with {@link WebView#postVisualStateCallback} and wait for the supplied
+ * callback to be triggered.
*
* @param view The WebView that is initiating the callback.
* @param url The url of the page.
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 4c8f72a..010c0b7 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -238,13 +238,15 @@
public WebViewClient getWebViewClient();
- public WebViewRenderer getWebViewRenderer();
+ @Nullable
+ public WebViewRenderProcess getWebViewRenderProcess();
- public void setWebViewRendererClient(
+ public void setWebViewRenderProcessClient(
@Nullable Executor executor,
- @Nullable WebViewRendererClient client);
+ @Nullable WebViewRenderProcessClient client);
- public WebViewRendererClient getWebViewRendererClient();
+ @Nullable
+ public WebViewRenderProcessClient getWebViewRenderProcessClient();
public void setDownloadListener(DownloadListener listener);
diff --git a/core/java/android/webkit/WebViewRenderer.java b/core/java/android/webkit/WebViewRenderProcess.java
similarity index 82%
rename from core/java/android/webkit/WebViewRenderer.java
rename to core/java/android/webkit/WebViewRenderProcess.java
index fc38cd9..1be2210 100644
--- a/core/java/android/webkit/WebViewRenderer.java
+++ b/core/java/android/webkit/WebViewRenderProcess.java
@@ -16,12 +16,10 @@
package android.webkit;
-import android.annotation.SystemApi;
-
/**
- * WebViewRenderer provides an opaque handle to a {@link WebView} renderer.
+ * WebViewRenderProcess provides an opaque handle to a {@link WebView} renderer.
*/
-public abstract class WebViewRenderer {
+public abstract class WebViewRenderProcess {
/**
* Cause this renderer to terminate.
*
@@ -38,11 +36,6 @@
*/
public abstract boolean terminate();
- /**
- * This class cannot be created by applications.
- * @hide
- */
- @SystemApi
- public WebViewRenderer() {
+ public WebViewRenderProcess() {
}
}
diff --git a/core/java/android/webkit/WebViewRendererClient.java b/core/java/android/webkit/WebViewRenderProcessClient.java
similarity index 66%
rename from core/java/android/webkit/WebViewRendererClient.java
rename to core/java/android/webkit/WebViewRenderProcessClient.java
index 2fadf54..24b8fb5 100644
--- a/core/java/android/webkit/WebViewRendererClient.java
+++ b/core/java/android/webkit/WebViewRenderProcessClient.java
@@ -22,14 +22,14 @@
/**
* Used to receive callbacks on {@link WebView} renderer events.
*
- * WebViewRendererClient instances may be set or retrieved via {@link
- * WebView#setWebViewRendererClient(WebViewRendererClient)} and {@link
- * WebView#getWebViewRendererClient()}.
+ * WebViewRenderProcessClient instances may be set or retrieved via {@link
+ * WebView#setWebViewRenderProcessClient(WebViewRenderProcessClient)} and {@link
+ * WebView#getWebViewRenderProcessClient()}.
*
* Instances may be attached to multiple WebViews, and thus a single renderer event may cause
* a callback to be called multiple times with different WebView parameters.
*/
-public abstract class WebViewRendererClient {
+public abstract class WebViewRenderProcessClient {
/**
* Called when the renderer currently associated with {@code view} becomes unresponsive as a
* result of a long running blocking task such as the execution of JavaScript.
@@ -40,8 +40,11 @@
*
* <p>This callback will continue to be called at regular intervals as long as the renderer
* remains unresponsive. If the renderer becomes responsive again, {@link
- * WebViewRendererClient#onRendererResponsive} will be called once, and this method will not
- * subsequently be called unless another period of unresponsiveness is detected.
+ * WebViewRenderProcessClient#onRenderProcessResponsive} will be called once, and this method
+ * will not subsequently be called unless another period of unresponsiveness is detected.
+ *
+ * <p>The minimum interval between successive calls to {@code onRenderProcessUnresponsive} is 5
+ * seconds.
*
* <p>No action is taken by WebView as a result of this method call. Applications may
* choose to terminate the associated renderer via the object that is passed to this callback,
@@ -50,28 +53,28 @@
* with the same renderer. Failure to do so will result in application termination.
*
* @param view The {@link WebView} for which unresponsiveness was detected.
- * @param renderer The {@link WebViewRenderer} that has become unresponsive,
+ * @param renderer The {@link WebViewRenderProcess} that has become unresponsive,
* or {@code null} if WebView is running in single process mode.
*/
- public abstract void onRendererUnresponsive(
- @NonNull WebView view, @Nullable WebViewRenderer renderer);
+ public abstract void onRenderProcessUnresponsive(
+ @NonNull WebView view, @Nullable WebViewRenderProcess renderer);
/**
* Called once when an unresponsive renderer currently associated with {@code view} becomes
* responsive.
*
* <p>After a WebView renderer becomes unresponsive, which is notified to the application by
- * {@link WebViewRendererClient#onRendererUnresponsive}, it is possible for the blocking
- * renderer task to complete, returning the renderer to a responsive state. In that case,
- * this method is called once to indicate responsiveness.
+ * {@link WebViewRenderProcessClient#onRenderProcessUnresponsive}, it is possible for the
+ * blocking renderer task to complete, returning the renderer to a responsive state. In that
+ * case, this method is called once to indicate responsiveness.
*
* <p>No action is taken by WebView as a result of this method call.
*
* @param view The {@link WebView} for which responsiveness was detected.
*
- * @param renderer The {@link WebViewRenderer} that has become responsive, or {@code null} if
- * WebView is running in single process mode.
+ * @param renderer The {@link WebViewRenderProcess} that has become responsive, or {@code null}
+ * if WebView is running in single process mode.
*/
- public abstract void onRendererResponsive(
- @NonNull WebView view, @Nullable WebViewRenderer renderer);
+ public abstract void onRenderProcessResponsive(
+ @NonNull WebView view, @Nullable WebViewRenderProcess renderer);
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6eceb003..24f1fb5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -7794,6 +7794,11 @@
mLastSeenPos = firstPos;
final int childCount = getChildCount();
+
+ if (childCount <= 0) {
+ return;
+ }
+
final int position = mTargetPos;
final int lastPos = firstPos + childCount - 1;
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index dad2669..685e8de 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1587,6 +1587,7 @@
* others.
* @return The height of the divider
*/
+ @Px
public int getSelectionDividerHeight() {
return mSelectionDividerHeight;
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index fd978f5..91928b5 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -420,6 +420,10 @@
if (isFinishing() || isDestroyed()) {
return;
}
+ // May be null if there are no apps to perform share/open action.
+ if (mChooserListAdapter == null) {
+ return;
+ }
final List<DisplayResolveInfo> driList =
getDisplayResolveInfos(mChooserListAdapter);
final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
diff --git a/core/java/com/android/internal/colorextraction/types/Tonal.java b/core/java/com/android/internal/colorextraction/types/Tonal.java
index d6a8934..9d85a03 100644
--- a/core/java/com/android/internal/colorextraction/types/Tonal.java
+++ b/core/java/com/android/internal/colorextraction/types/Tonal.java
@@ -56,7 +56,6 @@
private final TonalPalette mGreyPalette;
private final ArrayList<TonalPalette> mTonalPalettes;
- private final ArrayList<ColorRange> mBlacklistedColors;
// Temporary variable to avoid allocations
private float[] mTmpHSL = new float[3];
@@ -65,7 +64,6 @@
ConfigParser parser = new ConfigParser(context);
mTonalPalettes = parser.getTonalPalettes();
- mBlacklistedColors = parser.getBlacklistedColors();
mGreyPalette = mTonalPalettes.get(0);
mTonalPalettes.remove(0);
@@ -131,7 +129,7 @@
Color.blue(colorValue), hsl);
// Stop when we find a color that meets our criteria
- if (!generatedFromBitmap || !isBlacklisted(hsl)) {
+ if (!generatedFromBitmap) {
bestColor = color;
break;
}
@@ -300,22 +298,6 @@
return getColorPalette(palette.h, palette.s, palette.l);
}
-
- /**
- * Checks if a given color exists in the blacklist
- * @param hsl float array with 3 components (H 0..360, S 0..1 and L 0..1)
- * @return true if color should be avoided
- */
- private boolean isBlacklisted(float[] hsl) {
- for (int i = mBlacklistedColors.size() - 1; i >= 0; i--) {
- ColorRange badRange = mBlacklistedColors.get(i);
- if (badRange.containsColor(hsl[0], hsl[1], hsl[2])) {
- return true;
- }
- }
- return false;
- }
-
/**
* Offsets all colors by a delta, clamping values that go beyond what's
* supported on the color space.
@@ -364,11 +346,6 @@
return minErrorIndex;
}
- @VisibleForTesting
- public List<ColorRange> getBlacklistedColors() {
- return mBlacklistedColors;
- }
-
@Nullable
private TonalPalette findTonalPalette(float h, float s) {
// Fallback to a grey palette if the color is too desaturated.
@@ -502,11 +479,9 @@
@VisibleForTesting
public static class ConfigParser {
private final ArrayList<TonalPalette> mTonalPalettes;
- private final ArrayList<ColorRange> mBlacklistedColors;
public ConfigParser(Context context) {
mTonalPalettes = new ArrayList<>();
- mBlacklistedColors = new ArrayList<>();
// Load all palettes and the blacklist from an XML.
try {
@@ -520,8 +495,6 @@
String tagName = parser.getName();
if (tagName.equals("palettes")) {
parsePalettes(parser);
- } else if (tagName.equals("blacklist")) {
- parseBlacklist(parser);
}
} else {
throw new XmlPullParserException("Invalid XML event " + eventType + " - "
@@ -538,28 +511,6 @@
return mTonalPalettes;
}
- public ArrayList<ColorRange> getBlacklistedColors() {
- return mBlacklistedColors;
- }
-
- private void parseBlacklist(XmlPullParser parser)
- throws XmlPullParserException, IOException {
- parser.require(XmlPullParser.START_TAG, null, "blacklist");
- while (parser.next() != XmlPullParser.END_TAG) {
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- continue;
- }
- String name = parser.getName();
- // Starts by looking for the entry tag
- if (name.equals("range")) {
- mBlacklistedColors.add(readRange(parser));
- parser.next();
- } else {
- throw new XmlPullParserException("Invalid tag: " + name, parser, null);
- }
- }
- }
-
private ColorRange readRange(XmlPullParser parser)
throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, null, "range");
diff --git a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
index 293ffd3..37f61bf 100644
--- a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
+import android.os.Handler;
import android.os.IInterface;
import android.util.Slog;
@@ -43,10 +44,10 @@
public AbstractMultiplePendingRequestsRemoteService(@NonNull Context context,
@NonNull String serviceInterface, @NonNull ComponentName componentName, int userId,
- @NonNull VultureCallback<S> callback, boolean bindInstantServiceAllowed,
- boolean verbose, int initialCapacity) {
- super(context, serviceInterface, componentName, userId, callback, bindInstantServiceAllowed,
- verbose);
+ @NonNull VultureCallback<S> callback, @NonNull Handler handler,
+ boolean bindInstantServiceAllowed, boolean verbose, int initialCapacity) {
+ super(context, serviceInterface, componentName, userId, callback, handler,
+ bindInstantServiceAllowed, verbose);
mInitialCapacity = initialCapacity;
}
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 7270302..2e709de 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -28,7 +28,6 @@
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.IInterface;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -114,14 +113,14 @@
// NOTE: must be package-protected so this class is not extended outside
AbstractRemoteService(@NonNull Context context, @NonNull String serviceInterface,
@NonNull ComponentName componentName, int userId, @NonNull VultureCallback<S> callback,
- boolean bindInstantServiceAllowed, boolean verbose) {
+ @NonNull Handler handler, boolean bindInstantServiceAllowed, boolean verbose) {
mContext = context;
mVultureCallback = callback;
mVerbose = verbose;
mComponentName = componentName;
mIntent = new Intent(serviceInterface).setComponent(mComponentName);
mUserId = userId;
- mHandler = new Handler(Looper.getMainLooper());
+ mHandler = new Handler(handler.getLooper());
mBindInstantServiceAllowed = bindInstantServiceAllowed;
}
diff --git a/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java b/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
index 3e92a0b..a70fc3e 100644
--- a/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
+import android.os.Handler;
import android.os.IInterface;
import android.util.Slog;
@@ -42,10 +43,10 @@
public AbstractSinglePendingRequestRemoteService(@NonNull Context context,
@NonNull String serviceInterface, @NonNull ComponentName componentName, int userId,
- @NonNull VultureCallback<S> callback, boolean bindInstantServiceAllowed,
- boolean verbose) {
- super(context, serviceInterface, componentName, userId, callback, bindInstantServiceAllowed,
- verbose);
+ @NonNull VultureCallback<S> callback, @NonNull Handler handler,
+ boolean bindInstantServiceAllowed, boolean verbose) {
+ super(context, serviceInterface, componentName, userId, callback, handler,
+ bindInstantServiceAllowed, verbose);
}
@Override // from AbstractRemoteService
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index ec02432..940cc36 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -18,6 +18,8 @@
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
+import android.net.ProxyInfo;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -46,6 +48,10 @@
public static final int TYPE_IPSEC_HYBRID_RSA = 5;
public static final int TYPE_MAX = 5;
+ // Match these constants with R.array.vpn_proxy_settings.
+ public static final int PROXY_NONE = 0;
+ public static final int PROXY_MANUAL = 1;
+
// Entity fields.
@UnsupportedAppUsage
public final String key; // -1
@@ -68,6 +74,7 @@
public String ipsecUserCert = ""; // 12
public String ipsecCaCert = ""; // 13
public String ipsecServerCert = "";// 14
+ public ProxyInfo proxy = null; // 15~18
// Helper fields.
@UnsupportedAppUsage
@@ -96,6 +103,7 @@
ipsecCaCert = in.readString();
ipsecServerCert = in.readString();
saveLogin = in.readInt() != 0;
+ proxy = in.readParcelable(null);
}
@Override
@@ -117,6 +125,7 @@
out.writeString(ipsecCaCert);
out.writeString(ipsecServerCert);
out.writeInt(saveLogin ? 1 : 0);
+ out.writeParcelable(proxy, flags);
}
@UnsupportedAppUsage
@@ -127,8 +136,8 @@
}
String[] values = new String(value, StandardCharsets.UTF_8).split("\0", -1);
- // There can be 14 or 15 values in ICS MR1.
- if (values.length < 14 || values.length > 15) {
+ // There can be 14 - 19 Bytes in values.length.
+ if (values.length < 14 || values.length > 19) {
return null;
}
@@ -151,7 +160,18 @@
profile.ipsecUserCert = values[12];
profile.ipsecCaCert = values[13];
profile.ipsecServerCert = (values.length > 14) ? values[14] : "";
-
+ if (values.length > 15) {
+ String host = (values.length > 15) ? values[15] : "";
+ String port = (values.length > 16) ? values[16] : "";
+ String exclList = (values.length > 17) ? values[17] : "";
+ String pacFileUrl = (values.length > 18) ? values[18] : "";
+ if (pacFileUrl.isEmpty()) {
+ profile.proxy = new ProxyInfo(host, port.isEmpty() ?
+ 0 : Integer.parseInt(port), exclList);
+ } else {
+ profile.proxy = new ProxyInfo(pacFileUrl);
+ }
+ } // else profle.proxy = null
profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
return profile;
} catch (Exception e) {
@@ -176,6 +196,13 @@
builder.append('\0').append(ipsecUserCert);
builder.append('\0').append(ipsecCaCert);
builder.append('\0').append(ipsecServerCert);
+ if (proxy != null) {
+ builder.append('\0').append(proxy.getHost() != null ? proxy.getHost() : "");
+ builder.append('\0').append(proxy.getPort());
+ builder.append('\0').append(proxy.getExclusionListAsString() != null ?
+ proxy.getExclusionListAsString() : "");
+ builder.append('\0').append(proxy.getPacFileUrl().toString());
+ }
return builder.toString().getBytes(StandardCharsets.UTF_8);
}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 5688870..0fb2728 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -344,6 +344,7 @@
resultCallStats.add(createDebugEntry("end_time_millis", SystemClock.elapsedRealtime()));
resultCallStats.add(
createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis()));
+ resultCallStats.add(createDebugEntry("sampling_interval", mPeriodicSamplingInterval));
}
return resultCallStats;
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index c059721..932ff57 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -165,6 +165,7 @@
exportedEntries.add(createDebugEntry("end_time_millis", SystemClock.elapsedRealtime()));
exportedEntries.add(
createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis()));
+ exportedEntries.add(createDebugEntry("sampling_interval", mSamplingInterval));
}
return exportedEntries;
}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 2bba3c9..70d8b45 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -369,17 +369,8 @@
* @param appInfo ApplicationInfo of the application
*/
protected static void allowAppFilesAcrossFork(ApplicationInfo appInfo) {
- Zygote.nativeAllowFileAcrossFork(appInfo.sourceDir);
- if (appInfo.splitSourceDirs != null) {
- for (String path : appInfo.splitSourceDirs) {
- Zygote.nativeAllowFileAcrossFork(path);
- }
- }
- // As well as its shared libs
- if (appInfo.sharedLibraryFiles != null) {
- for (String path : appInfo.sharedLibraryFiles) {
- Zygote.nativeAllowFileAcrossFork(path);
- }
+ for (String path : appInfo.getAllApkPaths()) {
+ Zygote.nativeAllowFileAcrossFork(path);
}
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 17ed2a0..c095376 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1687,8 +1687,21 @@
*
* @return a unique 64-bit token handle which is needed to refer to this token later.
*/
- public long addEscrowToken(byte[] token, int userId) {
- return getLockSettingsInternal().addEscrowToken(token, userId);
+ public long addEscrowToken(byte[] token, int userId,
+ @Nullable EscrowTokenStateChangeCallback callback) {
+ return getLockSettingsInternal().addEscrowToken(token, userId, callback);
+ }
+
+ /**
+ * Callback interface to notify when an added escrow token has been activated.
+ */
+ public interface EscrowTokenStateChangeCallback {
+ /**
+ * The method to be called when the token is activated.
+ * @param handle 64 bit handle corresponding to the escrow token
+ * @param userid user for whom the escrow token has been added
+ */
+ void onEscrowTokenActivated(long handle, int userid);
}
/**
diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java
index 90397df..d459bfb 100644
--- a/core/java/com/android/internal/widget/LockSettingsInternal.java
+++ b/core/java/com/android/internal/widget/LockSettingsInternal.java
@@ -29,15 +29,18 @@
* or change user password.
*
* After adding, if the user currently has lockscreen password, he will need to perform a
- * confirm credential operation in order to activate the token for future use. If the user
+ * confirm credential operation in order to activate the token for future use.
+ * Once the token is activated, the callback that is passed here is called. If the user
* has no secure lockscreen, then the token is activated immediately.
*
* @return a unique 64-bit token handle which is needed to refer to this token later.
*/
- public abstract long addEscrowToken(byte[] token, int userId);
+ public abstract long addEscrowToken(byte[] token, int userId,
+ LockPatternUtils.EscrowTokenStateChangeCallback callback);
/**
* Remove an escrow token.
+ *
* @return true if the given handle refers to a valid token previously returned from
* {@link #addEscrowToken}, whether it's active or not. return false otherwise.
*/
@@ -51,6 +54,7 @@
/**
* Set the lock credential.
+ *
* @return true if password is set.
*/
public abstract boolean setLockCredentialWithToken(byte[] credential, int type,
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index de86d92..e7d240a 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -126,6 +126,9 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mImagePushIn > 0) {
+ if (this.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ mImagePushIn *= -1;
+ }
mRightIcon.layout(mRightIcon.getLeft() + mImagePushIn, mRightIcon.getTop(),
mRightIcon.getRight() + mImagePushIn, mRightIcon.getBottom());
}
diff --git a/core/java/com/android/server/net/OWNERS b/core/java/com/android/server/net/OWNERS
index 7311eee..d3836d4 100644
--- a/core/java/com/android/server/net/OWNERS
+++ b/core/java/com/android/server/net/OWNERS
@@ -1,8 +1,8 @@
set noparent
codewiz@google.com
-ek@google.com
jchalard@google.com
+junyulai@google.com
lorenzo@google.com
reminv@google.com
satk@google.com
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index dc536b2..be82879 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -187,20 +187,20 @@
off64_t offset;
if (!zipFile->getEntryInfo(zipEntry, &method, &uncompLen, NULL, &offset, &when, &crc)) {
- ALOGD("Couldn't read zip entry info\n");
+ ALOGE("Couldn't read zip entry info\n");
return INSTALL_FAILED_INVALID_APK;
}
if (!extractNativeLibs) {
// check if library is uncompressed and page-aligned
if (method != ZipFileRO::kCompressStored) {
- ALOGD("Library '%s' is compressed - will not be able to open it directly from apk.\n",
+ ALOGE("Library '%s' is compressed - will not be able to open it directly from apk.\n",
fileName);
return INSTALL_FAILED_INVALID_APK;
}
if (offset % PAGE_SIZE != 0) {
- ALOGD("Library '%s' is not page-aligned - will not be able to open it directly from"
+ ALOGE("Library '%s' is not page-aligned - will not be able to open it directly from"
" apk.\n", fileName);
return INSTALL_FAILED_INVALID_APK;
}
@@ -213,7 +213,7 @@
char localFileName[nativeLibPath.size() + fileNameLen + 2];
if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) != nativeLibPath.size()) {
- ALOGD("Couldn't allocate local file name for library");
+ ALOGE("Couldn't allocate local file name for library");
return INSTALL_FAILED_INTERNAL_ERROR;
}
@@ -221,7 +221,7 @@
if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName, sizeof(localFileName)
- nativeLibPath.size() - 1) != fileNameLen) {
- ALOGD("Couldn't allocate local file name for library");
+ ALOGE("Couldn't allocate local file name for library");
return INSTALL_FAILED_INTERNAL_ERROR;
}
@@ -237,24 +237,24 @@
char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 1];
if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName))
!= nativeLibPath.size()) {
- ALOGD("Couldn't allocate local file name for library");
+ ALOGE("Couldn't allocate local file name for library");
return INSTALL_FAILED_INTERNAL_ERROR;
}
if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN,
TMP_FILE_PATTERN_LEN + 1) != TMP_FILE_PATTERN_LEN) {
- ALOGI("Couldn't allocate temporary file name for library");
+ ALOGE("Couldn't allocate temporary file name for library");
return INSTALL_FAILED_INTERNAL_ERROR;
}
int fd = mkstemp(localTmpFileName);
if (fd < 0) {
- ALOGI("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno));
+ ALOGE("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno));
return INSTALL_FAILED_CONTAINER_ERROR;
}
if (!zipFile->uncompressEntry(zipEntry, fd)) {
- ALOGI("Failed uncompressing %s to %s\n", fileName, localTmpFileName);
+ ALOGE("Failed uncompressing %s to %s\n", fileName, localTmpFileName);
close(fd);
unlink(localTmpFileName);
return INSTALL_FAILED_CONTAINER_ERROR;
@@ -268,7 +268,7 @@
times[1].tv_sec = modTime;
times[0].tv_usec = times[1].tv_usec = 0;
if (utimes(localTmpFileName, times) < 0) {
- ALOGI("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno));
+ ALOGE("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno));
unlink(localTmpFileName);
return INSTALL_FAILED_CONTAINER_ERROR;
}
@@ -276,14 +276,14 @@
// Set the mode to 755
static const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
if (chmod(localTmpFileName, mode) < 0) {
- ALOGI("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno));
+ ALOGE("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno));
unlink(localTmpFileName);
return INSTALL_FAILED_CONTAINER_ERROR;
}
// Finally, rename it to the final name.
if (rename(localTmpFileName, localFileName) < 0) {
- ALOGI("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno));
+ ALOGE("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno));
unlink(localTmpFileName);
return INSTALL_FAILED_CONTAINER_ERROR;
}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 445075d..927c85f2 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2299,4 +2299,7 @@
// Open: Settings will show the conditional when Grayscale mode is on
SETTINGS_CONDITION_GRAYSCALE_MODE = 1683;
+
+ // Panel for Wifi
+ PANEL_WIFI = 1687;
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 08286a1..27a18ee 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -191,6 +191,21 @@
optional SettingProto emergency_assistance_application = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto enhanced_voice_privacy_enabled = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Gesture {
+ optional SettingProto aware_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ optional SettingProto silence_alarms_count = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto silence_calls_count = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto silence_enabled = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto silence_notification_count = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto silence_timer_count = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ optional SettingProto skip_count = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto skip_enabled = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Gesture gesture = 74;
+
optional SettingProto immersive_mode_confirmations = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
message Incall {
@@ -443,6 +458,7 @@
// parent profile.
optional SettingProto sync_parent_sounds = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto system_navigation_keys_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto theme_customization_overlay_packages = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto trust_agents_initialized = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
message Tts {
@@ -534,13 +550,7 @@
}
optional Zen zen = 71;
- optional SettingProto skip_gesture_enabled = 74 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto silence_gesture_enabled = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto theme_customization_overlay_packages = 76 [ (android.privacy).dest = DEST_AUTOMATIC ];
-
- optional SettingProto aware_enabled = 77 [ (android.privacy).dest = DEST_AUTOMATIC ];
-
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 78;
+ // Next tag = 76;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5d24ebc..d176260 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3049,12 +3049,6 @@
<permission android:name="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
android:protectionLevel="signature" />
- <!-- Must be required by the RoleControllerService to ensure that only the system can bind to
- it.
- @hide -->
- <permission android:name="android.permission.BIND_ROLE_CONTROLLER_SERVICE"
- android:protectionLevel="signature" />
-
<!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
that only the system can bind to it.
@hide -->
diff --git a/core/res/res/anim/lock_in.xml b/core/res/res/anim/lock_in.xml
index 992bc92..cd4effd 100755
--- a/core/res/res/anim/lock_in.xml
+++ b/core/res/res/anim/lock_in.xml
@@ -14,111 +14,76 @@
limitations under the License.
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
+ xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
- <vector
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
+ <vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
+ android:viewportWidth="32">
<group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_3_T_0_M">
- <group
- android:name="_R_G_L_2_G_N_3_T_0"
- android:pivotX="2.25"
- android:pivotY="2.25"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="9.75"
- android:translateY="12.75">
- <group
- android:name="_R_G_L_2_G_T_1"
- android:scaleX="0.12346"
- android:scaleY="0.12346"
- android:translateX="2.25"
- android:translateY="2.373">
- <group
- android:name="_R_G_L_2_G"
- android:translateY="32">
- <path
- android:name="_R_G_L_2_G_D_0_P_0"
- android:fillAlpha="0"
- android:fillColor="#ff0000"
- android:fillType="nonZero"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:trimPathStart="0.14"
- android:trimPathEnd="0.89"
- android:trimPathOffset="0" />
- <path
- android:name="_R_G_L_2_G_D_1_P_0"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:strokeWidth="16"
- android:strokeAlpha="1"
- android:strokeColor="?attr/textColor"
- android:trimPathStart="0.14"
- android:trimPathEnd="0.89"
- android:trimPathOffset="0" />
+ <group android:name="_R_G_L_2_G_N_2_N_1_T_0" android:translateX="16"
+ android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_2_G_N_2_T_0" android:translateX="-2.25"
+ android:translateY="0.75" android:pivotX="2.25" android:pivotY="2.25"
+ android:scaleX="0" android:scaleY="0">
+ <group android:name="_R_G_L_2_G_T_1" android:translateX="2.25"
+ android:translateY="2.373" android:scaleX="0.12346"
+ android:scaleY="0.12346">
+ <group android:name="_R_G_L_2_G" android:translateY="32">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#ff0000"
+ android:fillAlpha="0" android:fillType="nonZero"
+ android:trimPathStart="0.14" android:trimPathEnd="0.89"
+ android:trimPathOffset="0"
+ android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
+ <path android:name="_R_G_L_2_G_D_1_P_0"
+ android:strokeColor="?attr/textColor" android:strokeLineCap="round"
+ android:strokeLineJoin="round" android:strokeWidth="16"
+ android:strokeAlpha="1" android:trimPathStart="0.14"
+ android:trimPathEnd="0.89" android:trimPathOffset="0"
+ android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
</group>
</group>
</group>
</group>
- <group
- android:name="_R_G_L_1_G"
- android:pivotX="8.25"
- android:pivotY="7.25"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="3.75"
- android:translateY="7.75">
- <path
- android:name="_R_G_L_1_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="?attr/textColor"
- android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c " />
+ <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="16"
+ android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_1_G" android:translateX="-8.25"
+ android:translateY="-4.25" android:pivotX="8.25" android:pivotY="7.25"
+ android:scaleX="0" android:scaleY="0">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
+ </group>
</group>
- <group
- android:name="_R_G_L_0_G"
- android:pivotX="2.25"
- android:pivotY="2.25"
- android:scaleX="0"
- android:scaleY="0"
- android:translateX="9.75"
- android:translateY="12.75">
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="?attr/textColor"
- android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
+ <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="16"
+ android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_0_G" android:translateX="-2.25"
+ android:translateY="0.75" android:pivotX="2.25" android:pivotY="2.25"
+ android:scaleX="0" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="?attr/textColor"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
+ </group>
</group>
</group>
- <group android:name="time_group" />
+ <group android:name="time_group"/>
</vector>
</aapt:attr>
<target android:name="_R_G_L_2_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="trimPathStart"
- android:startOffset="0"
- android:valueFrom="0.14"
- android:valueTo="0.14"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="trimPathStart" android:duration="50"
+ android:startOffset="0" android:valueFrom="0.14"
+ android:valueTo="0.14" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="trimPathStart"
- android:startOffset="50"
- android:valueFrom="0.14"
- android:valueTo="0"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="trimPathStart" android:duration="67"
+ android:startOffset="50" android:valueFrom="0.14"
+ android:valueTo="0" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -127,26 +92,20 @@
<target android:name="_R_G_L_2_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="trimPathEnd"
- android:startOffset="0"
- android:valueFrom="0.89"
- android:valueTo="0.89"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="trimPathEnd" android:duration="50"
+ android:startOffset="0" android:valueFrom="0.89"
+ android:valueTo="0.89" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="trimPathEnd"
- android:startOffset="50"
- android:valueFrom="0.89"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="trimPathEnd" android:duration="67"
+ android:startOffset="50" android:valueFrom="0.89"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -155,26 +114,20 @@
<target android:name="_R_G_L_2_G_D_1_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="trimPathStart"
- android:startOffset="0"
- android:valueFrom="0.14"
- android:valueTo="0.14"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="trimPathStart" android:duration="50"
+ android:startOffset="0" android:valueFrom="0.14"
+ android:valueTo="0.14" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="trimPathStart"
- android:startOffset="50"
- android:valueFrom="0.14"
- android:valueTo="0"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="trimPathStart" android:duration="67"
+ android:startOffset="50" android:valueFrom="0.14"
+ android:valueTo="0" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -183,26 +136,20 @@
<target android:name="_R_G_L_2_G_D_1_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="50"
- android:propertyName="trimPathEnd"
- android:startOffset="0"
- android:valueFrom="0.89"
- android:valueTo="0.89"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="trimPathEnd" android:duration="50"
+ android:startOffset="0" android:valueFrom="0.89"
+ android:valueTo="0.89" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="67"
- android:propertyName="trimPathEnd"
- android:startOffset="50"
- android:valueFrom="0.89"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="trimPathEnd" android:duration="67"
+ android:startOffset="50" android:valueFrom="0.89"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -211,128 +158,91 @@
<target android:name="_R_G_L_2_G_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="150"
- android:pathData="M 2.25,2.373C 2.25,1.2001604776382402 2.25,-3.49116047763824 2.25,-4.664"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="0">
+ <objectAnimator android:propertyName="translateXY" android:duration="150"
+ android:startOffset="0" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 2.25,2.373C 2.25,1.2001604776382402 2.25,-3.49116047763824 2.25,-4.664">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_2_G_N_3_T_0">
+ <target android:name="_R_G_L_2_G_N_2_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.0125"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleX" android:duration="233"
+ android:startOffset="0" android:valueFrom="0"
+ android:valueTo="1.0125" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.0125"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleY" android:duration="233"
+ android:startOffset="0" android:valueFrom="0"
+ android:valueTo="1.0125" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.0125"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleX" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.0125"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.0125"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleY" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.0125"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_2_G_N_3_T_0_M">
+ <target android:name="_R_G_L_2_G_N_2_N_1_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="0"
- android:propertyName="scaleX"
- android:startOffset="50"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
+ <objectAnimator android:propertyName="scaleX" android:duration="0"
+ android:startOffset="50" android:valueFrom="0" android:valueTo="1.3"
+ android:valueType="floatType"/>
</set>
</aapt:attr>
</target>
<target android:name="_R_G_L_1_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleX" android:duration="233"
+ android:startOffset="0" android:valueFrom="0"
+ android:valueTo="1.025" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.025"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleY" android:duration="233"
+ android:startOffset="0" android:valueFrom="0"
+ android:valueTo="1.025" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleX" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.025"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.025"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleY" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.025"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -341,48 +251,34 @@
<target android:name="_R_G_L_0_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.0125"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleX" android:duration="233"
+ android:startOffset="0" android:valueFrom="0"
+ android:valueTo="1.0125" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="233"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1.0125"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleY" android:duration="233"
+ android:startOffset="0" android:valueFrom="0"
+ android:valueTo="1.0125" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.043,0.556 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleX"
- android:startOffset="233"
- android:valueFrom="1.0125"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleX" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.0125"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="117"
- android:propertyName="scaleY"
- android:startOffset="233"
- android:valueFrom="1.0125"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleY" android:duration="117"
+ android:startOffset="233" android:valueFrom="1.0125"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -391,13 +287,9 @@
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="717"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
+ <objectAnimator android:propertyName="translateX" android:duration="717"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
</set>
</aapt:attr>
</target>
diff --git a/core/res/res/anim/lock_lock.xml b/core/res/res/anim/lock_lock.xml
index 8b7887c..ce9c8e8 100755
--- a/core/res/res/anim/lock_lock.xml
+++ b/core/res/res/anim/lock_lock.xml
@@ -13,4 +13,277 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"><group android:name="_R_G"><group android:name="_R_G_L_2_G_T_1" android:translateX="12" android:translateY="15"><group android:name="_R_G_L_2_G" android:translateX="-8.25" android:translateY="-7.25"><path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/></group></group><group android:name="_R_G_L_1_G_N_5_T_1" android:translateX="12" android:translateY="15"><group android:name="_R_G_L_1_G_N_5_T_0" android:translateX="-8.25" android:translateY="-7.25"><group android:name="_R_G_L_1_G" android:translateX="6" android:translateY="5" android:pivotX="2.25" android:pivotY="2.25" android:scaleX="1" android:scaleY="1"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/></group></group></group><group android:name="_R_G_L_0_G_N_5_T_1" android:translateX="12" android:translateY="15"><group android:name="_R_G_L_0_G_N_5_T_0" android:translateX="-8.25" android:translateY="-7.25"><group android:name="_R_G_L_0_G" android:translateX="-16.219" android:translateY="32.25" android:pivotX="27.965" android:pivotY="-32" android:scaleX="0.125" android:scaleY="0.125"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ff0000" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "/><path android:name="_R_G_L_0_G_D_1_P_0" android:strokeColor="?attr/textColor" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="16" android:strokeAlpha="1" android:pathData=" M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "/></group></group></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_2_G_T_1"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateXY" android:duration="400" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15C 12,15.09895833581686 12,15 12,15"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="67" android:startOffset="400" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15C 12,15.09895833581686 12,15.594 12,15.594"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="83" android:startOffset="467" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15.594C 12,15.594 12,15.09895833581686 12,15"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="450" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="450" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="450" android:valueFrom="1" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="450" android:valueFrom="1" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="183" android:startOffset="517" android:valueFrom="1.1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="183" android:startOffset="517" android:valueFrom="1.1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_N_5_T_1"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateXY" android:duration="400" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15C 12,15.09895833581686 12,15 12,15"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="67" android:startOffset="400" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15C 12,15.09895833581686 12,15.594 12,15.594"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="83" android:startOffset="467" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15.594C 12,15.594 12,15.09895833581686 12,15"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="317" android:startOffset="0" android:valueFrom="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 " android:valueTo="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.974,0 0.458,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="133" android:startOffset="317" android:valueFrom="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 " android:valueTo="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="250" android:startOffset="450" android:valueFrom="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 " android:valueTo="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.414,0 0.647,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="317" android:startOffset="0" android:valueFrom="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 " android:valueTo="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.974,0 0.458,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="133" android:startOffset="317" android:valueFrom="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 " android:valueTo="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="250" android:startOffset="450" android:valueFrom="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 " android:valueTo="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.414,0 0.647,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_N_5_T_1"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateXY" android:duration="400" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15C 12,15.09895833581686 12,15 12,15"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="67" android:startOffset="400" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15C 12,15.09895833581686 12,15.594 12,15.594"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="translateXY" android:duration="83" android:startOffset="467" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 12,15.594C 12,15.594 12,15.09895833581686 12,15"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="717" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
+ android:viewportWidth="32">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="16"
+ android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_2_G_T_1" android:translateX="0"
+ android:translateY="3">
+ <group android:name="_R_G_L_2_G" android:translateX="-8.25"
+ android:translateY="-7.25">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G_N_4_N_1_T_0" android:translateX="16"
+ android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_1_G_N_4_T_1" android:translateX="0"
+ android:translateY="3">
+ <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="-8.25"
+ android:translateY="-7.25">
+ <group android:name="_R_G_L_1_G" android:translateX="6"
+ android:translateY="5" android:pivotX="2.25"
+ android:pivotY="2.25" android:scaleX="1" android:scaleY="1">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G_N_4_N_1_T_0" android:translateX="16"
+ android:translateY="16" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_0_G_N_4_T_1" android:translateX="0"
+ android:translateY="3">
+ <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="-8.25"
+ android:translateY="-7.25">
+ <group android:name="_R_G_L_0_G" android:translateX="-16.219"
+ android:translateY="32.25" android:pivotX="27.965"
+ android:pivotY="-32" android:scaleX="0.125"
+ android:scaleY="0.125">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ff0000"
+ android:fillAlpha="0" android:fillType="nonZero"
+ android:pathData=" M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "/>
+ <path android:name="_R_G_L_0_G_D_1_P_0"
+ android:strokeColor="?attr/textColor" android:strokeLineCap="round"
+ android:strokeLineJoin="round" android:strokeWidth="16"
+ android:strokeAlpha="1"
+ android:pathData=" M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_2_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="400"
+ android:startOffset="0" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3C 0,3.09895833581686 0,3 0,3">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="67"
+ android:startOffset="400" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3C 0,3.09895833581686 0,3.594 0,3.594">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="83"
+ android:startOffset="467" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3.594C 0,3.594 0,3.09895833581686 0,3">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="450"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="450"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="67"
+ android:startOffset="450" android:valueFrom="1"
+ android:valueTo="1.1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="67"
+ android:startOffset="450" android:valueFrom="1"
+ android:valueTo="1.1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="183"
+ android:startOffset="517" android:valueFrom="1.1"
+ android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="183"
+ android:startOffset="517" android:valueFrom="1.1"
+ android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_4_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="400"
+ android:startOffset="0" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3C 0,3.09895833581686 0,3 0,3">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="67"
+ android:startOffset="400" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3C 0,3.09895833581686 0,3.594 0,3.594">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="83"
+ android:startOffset="467" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3.594C 0,3.594 0,3.09895833581686 0,3">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="317"
+ android:startOffset="0"
+ android:valueFrom="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
+ android:valueTo="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.974,0 0.458,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="133"
+ android:startOffset="317"
+ android:valueFrom="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 "
+ android:valueTo="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="250"
+ android:startOffset="450"
+ android:valueFrom="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 "
+ android:valueTo="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.414,0 0.647,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_1_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="317"
+ android:startOffset="0"
+ android:valueFrom="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
+ android:valueTo="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.974,0 0.458,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="133"
+ android:startOffset="317"
+ android:valueFrom="M-27.97 -55.05 C-27.97,-55.05 -28,-60.25 -27.97,-61.98 C-27.92,-64.13 -23.5,-86.37 -0.75,-86.32 C22.77,-86.26 27.75,-65.87 27.72,-64.77 C27.55,-59.38 27.97,-31.67 27.97,-31.67 "
+ android:valueTo="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="250"
+ android:startOffset="450"
+ android:valueFrom="M-28.21 -28.42 C-28.21,-28.42 -27.85,-44.88 -27.97,-51.98 C-28,-54.13 -23.5,-76.37 -0.75,-76.32 C22.77,-76.26 27.75,-55.87 27.72,-54.77 C27.55,-49.38 27.97,-28.17 27.97,-28.17 "
+ android:valueTo="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.414,0 0.647,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_4_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="400"
+ android:startOffset="0" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3C 0,3.09895833581686 0,3 0,3">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="67"
+ android:startOffset="400" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3C 0,3.09895833581686 0,3.594 0,3.594">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="83"
+ android:startOffset="467" android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:pathData="M 0,3.594C 0,3.594 0,3.09895833581686 0,3">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="717"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_scanning.xml b/core/res/res/anim/lock_scanning.xml
index 36d8f88..998c965 100644
--- a/core/res/res/anim/lock_scanning.xml
+++ b/core/res/res/anim/lock_scanning.xml
@@ -16,43 +16,35 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
- <vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
+ <vector android:height="42dp" android:width="32dp" android:viewportHeight="42"
android:viewportWidth="32">
<group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_1_T_0" android:pivotX="16" android:pivotY="16"
- android:scaleX="1.5" android:scaleY="1.5">
- <group android:name="_R_G_L_2_G" android:translateX="7.75"
+ <group android:name="_R_G_L_2_G_N_5_N_1_T_0" android:translateY="5"
+ android:pivotX="16" android:pivotY="16" android:scaleX="2"
+ android:scaleY="2">
+ <group android:name="_R_G_L_2_G_N_5_T_0" android:translateX="7.75"
android:translateY="10.670000000000002" android:pivotX="8.25"
android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
- </group>
- </group>
- <group android:name="_R_G_L_1_G_N_4_N_1_T_0" android:pivotX="16" android:pivotY="16"
- android:scaleX="1.5" android:scaleY="1.5">
- <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="7.75"
- android:translateY="10.670000000000002" android:pivotX="8.25"
- android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
- <group android:name="_R_G_L_1_G" android:translateX="6"
+ <group android:name="_R_G_L_2_G" android:translateX="6"
android:translateY="5" android:pivotX="2.25" android:pivotY="2.25"
android:scaleX="1" android:scaleY="1">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
android:fillAlpha="1" android:fillType="nonZero"
android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
</group>
</group>
</group>
- <group android:name="_R_G_L_0_G_N_4_N_1_T_0" android:pivotX="16" android:pivotY="16"
- android:scaleX="1.5" android:scaleY="1.5">
- <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="7.75"
+ <group android:name="_R_G_L_1_G_N_5_N_1_T_0" android:translateY="5"
+ android:pivotX="16" android:pivotY="16" android:scaleX="2"
+ android:scaleY="2">
+ <group android:name="_R_G_L_1_G_N_5_T_0" android:translateX="7.75"
android:translateY="10.670000000000002" android:pivotX="8.25"
android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
- <group android:name="_R_G_L_0_G_T_1" android:translateX="8.25"
+ <group android:name="_R_G_L_1_G_T_1" android:translateX="8.25"
android:translateY="1.121" android:scaleX="0.125"
android:scaleY="0.125">
- <group android:name="_R_G_L_0_G" android:translateY="25.029">
- <path android:name="_R_G_L_0_G_D_0_P_0"
+ <group android:name="_R_G_L_1_G" android:translateY="25.029">
+ <path android:name="_R_G_L_1_G_D_0_P_0"
android:strokeColor="?attr/textColor" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="16"
android:strokeAlpha="1"
@@ -61,6 +53,21 @@
</group>
</group>
</group>
+ <group android:name="_R_G_L_0_G_N_5_N_1_T_0" android:translateY="5"
+ android:pivotX="16" android:pivotY="16" android:scaleX="2"
+ android:scaleY="2">
+ <group android:name="_R_G_L_0_G_N_5_T_0" android:translateX="7.75"
+ android:translateY="10.670000000000002" android:pivotX="8.25"
+ android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
+ <group android:name="_R_G_L_0_G" android:translateY="0.04699999999999971"
+ android:pivotX="8.25" android:pivotY="7.25" android:scaleX="1.01562"
+ android:scaleY="1.01563">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="?attr/textColor"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
+ </group>
+ </group>
+ </group>
</group>
<group android:name="time_group"/>
</vector>
@@ -68,68 +75,6 @@
<target android:name="_R_G_L_2_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator android:propertyName="scaleX" android:duration="83"
- android:startOffset="0" android:valueFrom="0.64"
- android:valueTo="0.64" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="83"
- android:startOffset="0" android:valueFrom="0.64"
- android:valueTo="0.64" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="83"
- android:startOffset="83" android:valueFrom="0.64"
- android:valueTo="0.62" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="83"
- android:startOffset="83" android:valueFrom="0.64"
- android:valueTo="0.62" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="183"
- android:startOffset="167" android:valueFrom="0.62"
- android:valueTo="0.8" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="183"
- android:startOffset="167" android:valueFrom="0.62"
- android:valueTo="0.8" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleX" android:duration="250"
- android:startOffset="350" android:valueFrom="0.8"
- android:valueTo="0.64" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- <objectAnimator android:propertyName="scaleY" android:duration="250"
- android:startOffset="350" android:valueFrom="0.8"
- android:valueTo="0.64" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_1_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
<objectAnimator android:propertyName="scaleX" android:duration="150"
android:startOffset="0" android:valueFrom="1" android:valueTo="1"
android:valueType="floatType">
@@ -175,7 +120,7 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_1_G_N_4_T_0">
+ <target android:name="_R_G_L_2_G_N_5_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="scaleX" android:duration="83"
@@ -237,7 +182,7 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_0_G_D_0_P_0">
+ <target android:name="_R_G_L_1_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="pathData" android:duration="83"
@@ -270,7 +215,7 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_0_G_T_1">
+ <target android:name="_R_G_L_1_G_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="translateY" android:duration="83"
@@ -297,7 +242,69 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_0_G_N_4_T_0">
+ <target android:name="_R_G_L_1_G_N_5_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="83"
+ android:startOffset="0" android:valueFrom="0.64"
+ android:valueTo="0.64" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="83"
+ android:startOffset="0" android:valueFrom="0.64"
+ android:valueTo="0.64" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="83"
+ android:startOffset="83" android:valueFrom="0.64"
+ android:valueTo="0.62" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="83"
+ android:startOffset="83" android:valueFrom="0.64"
+ android:valueTo="0.62" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="183"
+ android:startOffset="167" android:valueFrom="0.62"
+ android:valueTo="0.8" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="183"
+ android:startOffset="167" android:valueFrom="0.62"
+ android:valueTo="0.8" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="250"
+ android:startOffset="350" android:valueFrom="0.8"
+ android:valueTo="0.64" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="250"
+ android:startOffset="350" android:valueFrom="0.8"
+ android:valueTo="0.64" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_5_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="scaleX" android:duration="83"
diff --git a/core/res/res/anim/lock_to_error.xml b/core/res/res/anim/lock_to_error.xml
index 4aad742..ddef96b 100755
--- a/core/res/res/anim/lock_to_error.xml
+++ b/core/res/res/anim/lock_to_error.xml
@@ -19,52 +19,44 @@
<vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
android:viewportWidth="32">
<group android:name="_R_G">
- <group android:name="_R_G_L_2_G_N_1_T_0" android:pivotX="16" android:pivotY="16"
- android:scaleX="1.5" android:scaleY="1.5">
- <group android:name="_R_G_L_2_G" android:translateX="7.75"
- android:translateY="10.670000000000002" android:pivotX="8.25"
- android:pivotY="7.25" android:rotation="0" android:scaleX="0.64"
- android:scaleY="0.64">
+ <group android:name="_R_G_L_2_G_N_2_T_0" android:translateX="7.75"
+ android:translateY="12.649999999999999" android:pivotX="8.25"
+ android:pivotY="7.25" android:rotation="0" android:scaleX="1.3"
+ android:scaleY="1.3">
+ <group android:name="_R_G_L_2_G" android:translateX="6"
+ android:translateY="4.954" android:pivotX="2.25" android:pivotY="2.25"
+ android:scaleX="0.98462" android:scaleY="0.98462">
<path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
</group>
</group>
- <group android:name="_R_G_L_1_G_N_4_N_1_T_0" android:pivotX="16" android:pivotY="16"
- android:scaleX="1.5" android:scaleY="1.5">
- <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="7.75"
- android:translateY="10.670000000000002" android:pivotX="8.25"
- android:pivotY="7.25" android:rotation="0" android:scaleX="0.64"
- android:scaleY="0.64">
- <group android:name="_R_G_L_1_G" android:translateX="6"
- android:translateY="5">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
- android:fillAlpha="1" android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
- </group>
+ <group android:name="_R_G_L_1_G_N_2_T_0" android:translateX="7.75"
+ android:translateY="12.649999999999999" android:pivotX="8.25"
+ android:pivotY="7.25" android:rotation="0" android:scaleX="1.3"
+ android:scaleY="1.3">
+ <group android:name="_R_G_L_1_G" android:translateX="-16.273"
+ android:translateY="32.312" android:pivotX="27.965" android:pivotY="-32"
+ android:scaleX="0.12308" android:scaleY="0.12308">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="?attr/textColor"
+ android:strokeLineCap="round" android:strokeLineJoin="round"
+ android:strokeWidth="16" android:strokeAlpha="1"
+ android:pathData=" M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "/>
</group>
</group>
- <group android:name="_R_G_L_0_G_N_4_N_1_T_0" android:pivotX="16" android:pivotY="16"
- android:scaleX="1.5" android:scaleY="1.5">
- <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="7.75"
- android:translateY="10.670000000000002" android:pivotX="8.25"
- android:pivotY="7.25" android:rotation="0" android:scaleX="0.64"
- android:scaleY="0.64">
- <group android:name="_R_G_L_0_G" android:translateX="-16.219"
- android:translateY="32.25" android:pivotX="27.965"
- android:pivotY="-32" android:scaleX="0.125" android:scaleY="0.125">
- <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="?attr/textColor"
- android:strokeLineCap="round" android:strokeLineJoin="round"
- android:strokeWidth="16" android:strokeAlpha="1"
- android:pathData=" M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "/>
- </group>
- </group>
+ <group android:name="_R_G_L_0_G" android:translateX="7.75"
+ android:translateY="12.649999999999999" android:pivotX="8.25"
+ android:pivotY="7.25" android:rotation="0" android:scaleX="1.3"
+ android:scaleY="1.3">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="?attr/textColor"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
</group>
</group>
<group android:name="time_group"/>
</vector>
</aapt:attr>
- <target android:name="_R_G_L_2_G">
+ <target android:name="_R_G_L_2_G_N_2_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="rotation" android:duration="133"
@@ -105,7 +97,7 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_1_G_N_4_T_0">
+ <target android:name="_R_G_L_1_G_N_2_T_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="rotation" android:duration="133"
@@ -146,7 +138,7 @@
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_0_G_N_4_T_0">
+ <target android:name="_R_G_L_0_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="rotation" android:duration="133"
diff --git a/core/res/res/anim/lock_unlock.xml b/core/res/res/anim/lock_unlock.xml
index 9cc31a0..0e85c9d 100755
--- a/core/res/res/anim/lock_unlock.xml
+++ b/core/res/res/anim/lock_unlock.xml
@@ -14,124 +14,85 @@
limitations under the License.
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
+ xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
- <vector
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
+ <vector android:height="40dp" android:width="32dp" android:viewportHeight="40"
+ android:viewportWidth="32">
<group android:name="_R_G">
- <group
- android:name="_R_G_L_2_G_T_1"
- android:translateX="12"
- android:translateY="15">
- <group
- android:name="_R_G_L_2_G"
- android:translateX="-8.25"
- android:translateY="-7.25">
- <path
- android:name="_R_G_L_2_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="?attr/textColor"
- android:fillType="nonZero"
- android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c " />
- </group>
- </group>
- <group
- android:name="_R_G_L_1_G_N_5_T_1"
- android:translateX="12"
- android:translateY="15">
- <group
- android:name="_R_G_L_1_G_N_5_T_0"
- android:translateX="-8.25"
- android:translateY="-7.25">
- <group
- android:name="_R_G_L_1_G"
- android:pivotX="2.25"
- android:pivotY="2.25"
- android:scaleX="1"
- android:scaleY="1"
- android:translateX="6"
- android:translateY="5">
- <path
- android:name="_R_G_L_1_G_D_0_P_0"
- android:fillAlpha="1"
- android:fillColor="?attr/textColor"
- android:fillType="nonZero"
- android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
+ <group android:name="_R_G_L_2_G_N_1_T_0" android:translateX="16"
+ android:translateY="20" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_2_G_T_1" android:translateY="3">
+ <group android:name="_R_G_L_2_G" android:translateX="-8.25"
+ android:translateY="-7.25">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
</group>
</group>
</group>
- <group
- android:name="_R_G_L_0_G_N_5_T_1"
- android:translateX="12"
- android:translateY="15">
- <group
- android:name="_R_G_L_0_G_N_5_T_0"
- android:translateX="-8.25"
- android:translateY="-7.25">
- <group
- android:name="_R_G_L_0_G"
- android:pivotX="27.965"
- android:pivotY="-32"
- android:scaleX="0.125"
- android:scaleY="0.125"
- android:translateX="-16.219"
- android:translateY="32.25">
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:fillAlpha="0"
- android:fillColor="#ff0000"
- android:fillType="nonZero"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 " />
- <path
- android:name="_R_G_L_0_G_D_1_P_0"
- android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:strokeWidth="16"
- android:strokeAlpha="1"
- android:strokeColor="?attr/textColor"/>
+ <group android:name="_R_G_L_1_G_N_4_N_1_T_0" android:translateX="16"
+ android:translateY="20" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_1_G_N_4_T_1" android:translateY="3">
+ <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="-8.25"
+ android:translateY="-7.25">
+ <group android:name="_R_G_L_1_G" android:translateX="6"
+ android:translateY="5" android:pivotX="2.25"
+ android:pivotY="2.25" android:scaleX="1" android:scaleY="1">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+ android:fillAlpha="1" android:fillType="nonZero"
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G_N_4_N_1_T_0" android:translateX="16"
+ android:translateY="20" android:scaleX="1.3" android:scaleY="1.3">
+ <group android:name="_R_G_L_0_G_N_4_T_1" android:translateY="3">
+ <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="-8.25"
+ android:translateY="-7.25">
+ <group android:name="_R_G_L_0_G" android:translateX="-16.219"
+ android:translateY="32.25" android:pivotX="27.965"
+ android:pivotY="-32" android:scaleX="0.125"
+ android:scaleY="0.125">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ff0000"
+ android:fillAlpha="0" android:fillType="nonZero"
+ android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
+ <path android:name="_R_G_L_0_G_D_1_P_0"
+ android:strokeColor="?attr/textColor" android:strokeLineCap="round"
+ android:strokeLineJoin="round" android:strokeWidth="16"
+ android:strokeAlpha="1"
+ android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
+ </group>
</group>
</group>
</group>
</group>
- <group android:name="time_group" />
+ <group android:name="time_group"/>
</vector>
</aapt:attr>
<target android:name="_R_G_L_2_G_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="133"
- android:pathData="M 12,15C 12,14.85416667163372 12,14.125 12,14.125"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="0">
+ <objectAnimator android:propertyName="translateY" android:duration="133"
+ android:startOffset="0" android:valueFrom="3"
+ android:valueTo="1.625" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.075,0.167 0.622,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="133"
- android:pathData="M 12,14.125C 12,14.125 12,15.05870145463943 12,15.324"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="133">
+ <objectAnimator android:propertyName="translateY" android:duration="133"
+ android:startOffset="133" android:valueFrom="1.625"
+ android:valueTo="3.699" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.352,0 0.717,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="100"
- android:pathData="M 12,15.324C 12,15.40252217555046 12,14.96669441461563 12,15"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="267">
+ <objectAnimator android:propertyName="translateY" android:duration="100"
+ android:startOffset="267" android:valueFrom="3.699"
+ android:valueTo="3" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.356,0 0.527,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -140,87 +101,60 @@
<target android:name="_R_G_L_1_G">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="100"
- android:propertyName="scaleX"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.85"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleX" android:duration="100"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="0.85"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="100"
- android:propertyName="scaleY"
- android:startOffset="0"
- android:valueFrom="1"
- android:valueTo="0.85"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleY" android:duration="100"
+ android:startOffset="0" android:valueFrom="1" android:valueTo="0.85"
+ android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="283"
- android:propertyName="scaleX"
- android:startOffset="100"
- android:valueFrom="0.85"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleX" android:duration="283"
+ android:startOffset="100" android:valueFrom="0.85"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="283"
- android:propertyName="scaleY"
- android:startOffset="100"
- android:valueFrom="0.85"
- android:valueTo="1"
- android:valueType="floatType">
+ <objectAnimator android:propertyName="scaleY" android:duration="283"
+ android:startOffset="100" android:valueFrom="0.85"
+ android:valueTo="1" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_1_G_N_5_T_1">
+ <target android:name="_R_G_L_1_G_N_4_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="133"
- android:pathData="M 12,15C 12,14.85416667163372 12,14.125 12,14.125"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="0">
+ <objectAnimator android:propertyName="translateY" android:duration="133"
+ android:startOffset="0" android:valueFrom="3"
+ android:valueTo="1.625" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.075,0.167 0.622,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="133"
- android:pathData="M 12,14.125C 12,14.125 12,15.05870145463943 12,15.324"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="133">
+ <objectAnimator android:propertyName="translateY" android:duration="133"
+ android:startOffset="133" android:valueFrom="1.625"
+ android:valueTo="3.699" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.352,0 0.717,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="100"
- android:pathData="M 12,15.324C 12,15.40252217555046 12,14.96669441461563 12,15"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="267">
+ <objectAnimator android:propertyName="translateY" android:duration="100"
+ android:startOffset="267" android:valueFrom="3.699"
+ android:valueTo="3" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.356,0 0.527,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -229,26 +163,22 @@
<target android:name="_R_G_L_0_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="67"
- android:propertyName="pathData"
- android:startOffset="0"
- android:valueFrom="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueTo="M-27.97 -48.55 C-27.97,-48.55 -28,-53.75 -27.97,-55.48 C-27.92,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueType="pathType">
+ <objectAnimator android:propertyName="pathData" android:duration="67"
+ android:startOffset="0"
+ android:valueFrom="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
+ android:valueTo="M-27.97 -59.3 C-27.97,-59.3 -28,-64.5 -27.97,-66.23 C-27.92,-68.37 -23.5,-90.63 -0.75,-90.57 C22.77,-90.51 27.75,-70.12 27.72,-69.02 C27.55,-63.63 27.97,-25.67 27.97,-25.67 "
+ android:valueType="pathType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.353,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.353,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="333"
- android:propertyName="pathData"
- android:startOffset="67"
- android:valueFrom="M-27.97 -48.55 C-27.97,-48.55 -28,-53.75 -27.97,-55.48 C-27.92,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueTo="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
- android:valueType="pathType">
+ <objectAnimator android:propertyName="pathData" android:duration="333"
+ android:startOffset="67"
+ android:valueFrom="M-27.97 -59.3 C-27.97,-59.3 -28,-64.5 -27.97,-66.23 C-27.92,-68.37 -23.5,-90.63 -0.75,-90.57 C22.77,-90.51 27.75,-70.12 27.72,-69.02 C27.55,-63.63 27.97,-25.67 27.97,-25.67 "
+ android:valueTo="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
+ android:valueType="pathType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.542,0 0.026,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.542,0 0.026,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -257,65 +187,50 @@
<target android:name="_R_G_L_0_G_D_1_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="67"
- android:propertyName="pathData"
- android:startOffset="0"
- android:valueFrom="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueTo="M-27.97 -48.55 C-27.97,-48.55 -28,-53.75 -27.97,-55.48 C-27.92,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueType="pathType">
+ <objectAnimator android:propertyName="pathData" android:duration="67"
+ android:startOffset="0"
+ android:valueFrom="M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
+ android:valueTo="M-27.97 -59.3 C-27.97,-59.3 -28,-64.5 -27.97,-66.23 C-27.92,-68.37 -23.5,-90.63 -0.75,-90.57 C22.77,-90.51 27.75,-70.12 27.72,-69.02 C27.55,-63.63 27.97,-25.67 27.97,-25.67 "
+ android:valueType="pathType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.353,0 0.2,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.353,0 0.2,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="333"
- android:propertyName="pathData"
- android:startOffset="67"
- android:valueFrom="M-27.97 -48.55 C-27.97,-48.55 -28,-53.75 -27.97,-55.48 C-27.92,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
- android:valueTo="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
- android:valueType="pathType">
+ <objectAnimator android:propertyName="pathData" android:duration="333"
+ android:startOffset="67"
+ android:valueFrom="M-27.97 -59.3 C-27.97,-59.3 -28,-64.5 -27.97,-66.23 C-27.92,-68.37 -23.5,-90.63 -0.75,-90.57 C22.77,-90.51 27.75,-70.12 27.72,-69.02 C27.55,-63.63 27.97,-25.67 27.97,-25.67 "
+ android:valueTo="M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "
+ android:valueType="pathType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.542,0 0.026,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.542,0 0.026,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
- <target android:name="_R_G_L_0_G_N_5_T_1">
+ <target android:name="_R_G_L_0_G_N_4_T_1">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="133"
- android:pathData="M 12,15C 12,14.85416667163372 12,14.125 12,14.125"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="0">
+ <objectAnimator android:propertyName="translateY" android:duration="133"
+ android:startOffset="0" android:valueFrom="3"
+ android:valueTo="1.625" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator
+ android:pathData="M 0.0,0.0 c0.075,0.167 0.622,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="133"
- android:pathData="M 12,14.125C 12,14.125 12,15.05870145463943 12,15.324"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="133">
+ <objectAnimator android:propertyName="translateY" android:duration="133"
+ android:startOffset="133" android:valueFrom="1.625"
+ android:valueTo="3.699" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.352,0 0.717,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
- <objectAnimator
- android:duration="100"
- android:pathData="M 12,15.324C 12,15.40252217555046 12,14.96669441461563 12,15"
- android:propertyName="translateXY"
- android:propertyXName="translateX"
- android:propertyYName="translateY"
- android:startOffset="267">
+ <objectAnimator android:propertyName="translateY" android:duration="100"
+ android:startOffset="267" android:valueFrom="3.699"
+ android:valueTo="3" android:valueType="floatType">
<aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.356,0 0.527,1 1.0,1.0"/>
</aapt:attr>
</objectAnimator>
</set>
@@ -324,13 +239,9 @@
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
- <objectAnimator
- android:duration="717"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
+ <objectAnimator android:propertyName="translateX" android:duration="717"
+ android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+ android:valueType="floatType"/>
</set>
</aapt:attr>
</target>
diff --git a/core/res/res/drawable/ic_lock.xml b/core/res/res/drawable/ic_lock.xml
new file mode 100644
index 0000000..8d7143b
--- /dev/null
+++ b/core/res/res/drawable/ic_lock.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="32"
+ android:viewportHeight="32">
+ <path
+ android:fillColor="?attr/textColor"
+ android:pathData="M16,20m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
+ <path
+ android:fillColor="?attr/textColor"
+ android:pathData="M24,10.7h-2V7.3c0,-3.3 -2.7,-6 -6,-6s-6,2.7 -6,6v3.3H8c-1.5,0 -2.7,1.2 -2.7,2.7v13.3c0,1.5 1.2,2.7 2.7,2.7h16c1.5,0 2.7,-1.2 2.7,-2.7V13.3C26.7,11.9 25.5,10.7 24,10.7zM12.7,7.3C12.7,5.5 14.2,4 16,4s3.3,1.5 3.3,3.3v3.3h-6.7V7.3zM24,26.7H8V13.3h2h12h2V26.7z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_lock_24dp.xml b/core/res/res/drawable/ic_lock_24dp.xml
deleted file mode 100644
index d848426..0000000
--- a/core/res/res/drawable/ic_lock_24dp.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="?attr/textColor"
- android:pathData="M12.0,15.0m-2.0,0.0a2.0,2.0 0.0,1.0 1.0,4.0 0.0a2.0,2.0 0.0,1.0 1.0,-4.0 0.0"/>
- <path
- android:pathData="M0,0h24v24H0V0z"
- android:fillColor="#00000000"/>
- <path
- android:fillColor="?attr/textColor"
- android:pathData="M18.0,8.0l-1.5,0.0L16.5,5.5C16.5,3.01 14.49,1.0 12.0,1.0S7.5,3.01 7.5,5.5L7.5,8.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.1 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0C20.0,8.9 19.1,8.0 18.0,8.0zM9.5,5.5C9.5,4.12 10.62,3.0 12.0,3.0c1.38,0.0 2.5,1.12 2.5,2.5L14.5,8.0l-5.0,0.0L9.5,5.5zM18.0,20.0L6.0,20.0L6.0,10.0l1.5,0.0l9.0,0.0L18.0,10.0L18.0,20.0z"/>
-</vector>
diff --git a/core/res/res/drawable/ic_lock_open.xml b/core/res/res/drawable/ic_lock_open.xml
new file mode 100644
index 0000000..3a6bf93
--- /dev/null
+++ b/core/res/res/drawable/ic_lock_open.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="32"
+ android:viewportHeight="32">
+ <path
+ android:fillColor="?attr/textColor"
+ android:pathData="M16,20m-2.67,0a2.67,2.67 0,1 1,5.34 0a2.67,2.67 0,1 1,-5.34 0"/>
+ <path
+ android:fillColor="?attr/textColor"
+ android:pathData="M24.67,1.33a6,6 0,0 0,-6 6v3.34L8,10.67a2.67,2.67 0,0 0,-2.67 2.66L5.33,26.67A2.67,2.67 0,0 0,8 29.33L24,29.33a2.67,2.67 0,0 0,2.67 -2.66L26.67,13.33A2.67,2.67 0,0 0,24 10.67L21.33,10.67L21.33,7.33a3.34,3.34 0,0 1,6.67 0L28,8h2.67L30.67,7.33A6,6 0,0 0,24.67 1.33ZM24,13.33L24,26.67L8,26.67L8,13.33Z"/>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_lock_open_24dp.xml b/core/res/res/drawable/ic_lock_open_24dp.xml
deleted file mode 100644
index 94eecad..0000000
--- a/core/res/res/drawable/ic_lock_open_24dp.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="?attr/textColor"
- android:pathData="M12.0,15.0m-2.0,0.0a2.0,2.0 0.0,1.0 1.0,4.0 0.0a2.0,2.0 0.0,1.0 1.0,-4.0 0.0"/>
- <path
- android:fillColor="?attr/textColor"
- android:pathData="M18.5,1.0C16.01,1.0 14.0,3.01 14.0,5.5L14.0,8.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.1 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0l-2.0,0.0L16.0,5.5C16.0,4.12 17.12,3.0 18.5,3.0C19.88,3.0 21.0,4.12 21.0,5.5L21.0,6.0l2.0,0.0L23.0,5.5C23.0,3.01 20.99,1.0 18.5,1.0zM18.0,10.0l0.0,10.0L6.0,20.0L6.0,10.0L18.0,10.0z"/>
- <path
- android:pathData="M0,0h24v24H0V0z"
- android:fillColor="#00000000"/>
-</vector>
diff --git a/core/res/res/layout/notification_material_media_seekbar.xml b/core/res/res/layout/notification_material_media_seekbar.xml
index c23ca83..4aa8acc 100644
--- a/core/res/res/layout/notification_material_media_seekbar.xml
+++ b/core/res/res/layout/notification_material_media_seekbar.xml
@@ -50,7 +50,7 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginStart="@dimen/notification_content_margin_start"
- android:gravity="left"
+ android:gravity="start"
/>
<TextView android:id="@+id/notification_media_total_time"
@@ -59,7 +59,7 @@
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginEnd="@dimen/notification_content_margin_end"
- android:gravity="right"
+ android:gravity="end"
/>
</FrameLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/values-night/values.xml b/core/res/res/values-night/values.xml
index a2ad3b9..4e6b712 100644
--- a/core/res/res/values-night/values.xml
+++ b/core/res/res/values-night/values.xml
@@ -24,6 +24,7 @@
<item name="colorError">@color/error_color_device_default_dark</item>
<item name="colorControlNormal">?attr/textColorPrimary</item>
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
+ <item name="forceDarkAllowed">false</item>
<!-- QS panel background -->
<item name="colorBackgroundFloating">@color/black</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b7f594e..bfb6d24 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1950,7 +1950,7 @@
<!-- The name of the package that will hold the browser role by default. -->
<string name="config_defaultBrowser" translatable="false">@string/default_browser</string>
<!-- The name of the package that will hold the dialer role by default. -->
- <string name="config_defaultDialer" translatable="false">com.android.phone</string>
+ <string name="config_defaultDialer" translatable="false">com.android.dialer</string>
<!-- The name of the package that will hold the SMS role by default. -->
<string name="config_defaultSms" translatable="false">@string/default_sms_application</string>
<!-- Whether the default emergency settings should be shown. -->
@@ -3943,4 +3943,8 @@
<!-- The default peak refresh rate for a given device. Change this value if you want to allow
for higher refresh rates to be automatically used out of the box -->
<integer name="config_defaultPeakRefreshRate">60</integer>
+
+ <!-- The type of the light sensor to be used by the display framework for things like
+ auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
+ <string name="config_displayLightSensorType" translatable="false" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5b658b7..05cf419 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -280,9 +280,9 @@
<!-- WFC, summary for Disabled -->
<string name="wifi_calling_off_summary">Off</string>
<!-- WFC, summary for Wi-Fi Preferred -->
- <string name="wfc_mode_wifi_preferred_summary">Wi-Fi preferred</string>
+ <string name="wfc_mode_wifi_preferred_summary">Call over Wi-Fi</string>
<!-- WFC, summary for Mobile data Preferred -->
- <string name="wfc_mode_cellular_preferred_summary">Mobile preferred</string>
+ <string name="wfc_mode_cellular_preferred_summary">Call over mobile network</string>
<!-- WFC, summary for Wi-Fi Only -->
<string name="wfc_mode_wifi_only_summary">Wi-Fi only</string>
@@ -707,12 +707,12 @@
<string name="permgrouprequest_location">Allow
<b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to access this device\'s location?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the location only while app is in foreground [CHAR LIMIT=150]-->
- <string name="permgrouprequestdetail_location">The app will only have access to the location while you\u2019re using the app.</string>
+ <string name="permgrouprequestdetail_location">The app will only have access to the location while you\u2019re using the app</string>
<!-- Message shown to the user when the apps requests permission to use the location while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
- <string name="permgroupbackgroundrequest_location">Always allow
- <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to access this device\u2019s location?</string>
+ <string name="permgroupbackgroundrequest_location">Allow
+ <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to access this device\u2019s location <b>all the time</b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the location while app is in foreground and background [CHAR LIMIT=150] -->
- <string name="permgroupbackgroundrequestdetail_location">The app will always have access to the location, even when you\u2019re not using the app.</string>
+ <string name="permgroupbackgroundrequestdetail_location">App currently can access location only while you\u2019re using the app</string>
<!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permgrouplab_calendar">Calendar</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 13551e7..c7e19c5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1378,8 +1378,8 @@
<java-symbol type="drawable" name="ic_text_dot" />
<java-symbol type="drawable" name="ic_print" />
<java-symbol type="drawable" name="ic_print_error" />
- <java-symbol type="drawable" name="ic_lock_24dp" />
- <java-symbol type="drawable" name="ic_lock_open_24dp" />
+ <java-symbol type="drawable" name="ic_lock" />
+ <java-symbol type="drawable" name="ic_lock_open" />
<java-symbol type="drawable" name="jog_dial_arrow_long_left_green" />
<java-symbol type="drawable" name="jog_dial_arrow_long_right_red" />
<java-symbol type="drawable" name="jog_dial_arrow_short_left_and_right" />
@@ -3693,5 +3693,9 @@
<java-symbol type="string" name="mime_type_presentation" />
<java-symbol type="string" name="mime_type_presentation_ext" />
+ <!-- For high refresh rate displays -->
<java-symbol type="integer" name="config_defaultPeakRefreshRate" />
+
+ <!-- For Auto-Brightness -->
+ <java-symbol type="string" name="config_displayLightSensorType" />
</resources>
diff --git a/core/res/res/xml/color_extraction.xml b/core/res/res/xml/color_extraction.xml
index 93ab0ff..c3ebe4e 100644
--- a/core/res/res/xml/color_extraction.xml
+++ b/core/res/res/xml/color_extraction.xml
@@ -246,109 +246,4 @@
0.6549019607843137,0.7549019607843137,0.8509803921568627,
0.9411764705882353"/>
</palettes>
- <blacklist>
- <!-- Red -->
- <range h="0, 20"
- s="0.7, 1"
- l="0.21, 0.79"/>
- <range h="0, 20"
- s="0.3, 0.7"
- l="0.355, 0.653"/>
- <!-- Red Orange -->
- <range h="20, 40"
- s="0.7, 1"
- l="0.2, 0.643"/>
- <range h="20, 40"
- s="0.3, 0.7"
- l="0.414, 0.561"/>
- <range h="20, 40"
- s="0, 0.3"
- l="0.343, 0.584"/>
- <!-- Orange -->
- <range h="40, 60"
- s="0.7, 1"
- l="0.173, 0.38"/>
- <range h="40, 60"
- s="0.3, 0.7"
- l="0.233, 0.427"/>
- <range h="40, 60"
- s="0, 0.3"
- l="0.231, 0.48"/>
- <!-- Yellow 60 -->
- <range h="60, 80"
- s="0.7, 1"
- l="0.15, 0.40"/>
- <range h="60, 80"
- s="0.3, 0.7"
- l="0.15, 0.42"/>
- <range h="60, 80"
- s="0, 0.3"
- l="0.35, 0.57"/>
- <!-- Yellow Green 80 -->
- <range h="80, 100"
- s="0.7, 1"
- l="0.36, 0.65"/>
- <range h="80, 100"
- s="0.3, 0.7"
- l="0.48, 0.57"/>
- <!-- Yellow green 100 -->
- <range h="100, 120"
- s="0.7, 1"
- l="0.388, 0.67"/>
- <range h="100, 120"
- s="0.3, 0.7"
- l="0.424, 0.58"/>
- <!-- Green -->
- <range h="120, 140"
- s="0.7, 1"
- l="0.37, 0.65"/>
- <range h="120, 140"
- s="0.3, 0.7"
- l="0.435, 0.58"/>
- <!-- Green Blue 140 -->
- <range h="140, 160"
- s="0.7, 1"
- l="0.43, 0.641"/>
- <!-- Seaoam -->
- <range h="160, 180"
- s="0.7, 1"
- l="0.496, 0.567"/>
- <!-- Cyan -->
- <range h="180, 200"
- s="0.7, 1"
- l="0.52, 0.729"/>
- <!-- Blue -->
- <range h="220, 240"
- s="0.7, 1"
- l="0.396, 0.571"/>
- <range h="220, 240"
- s="0.3, 0.7"
- l="0.425, 0.551"/>
- <!-- Blue Purple 240 -->
- <range h="240, 260"
- s="0.7, 1"
- l="0.418, 0.639"/>
- <range h="220, 240"
- s="0.3, 0.7"
- l="0.441, 0.576"/>
- <!-- Blue Purple 260 -->
- <range h="260, 280"
- s="0.3, 1"
- l="0.461, 0.553"/>
- <!-- Fuchsia -->
- <range h="300, 320"
- s="0.7, 1"
- l="0.484, 0.588"/>
- <range h="300, 320"
- s="0.3, 0.7"
- l="0.48, 0.592"/>
- <!-- Pink -->
- <range h="320, 340"
- s="0.7, 1"
- l="0.466, 0.629"/>
- <!-- Soft red -->
- <range h="340, 360"
- s="0.7, 1"
- l="0.437, 0.596"/>
- </blacklist>
-</colorextraction>
\ No newline at end of file
+</colorextraction>
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index d100f40..04fa524 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -16,6 +16,7 @@
package android.provider;
+import static android.provider.DeviceConfig.OnPropertiesChangedListener;
import static android.provider.DeviceConfig.OnPropertyChangedListener;
import static com.google.common.truth.Truth.assertThat;
@@ -224,29 +225,31 @@
}
@Test
- public void testListener_propertiesCallback() throws InterruptedException {
+ public void testOnPropertiesChangedListener() throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(1);
- OnPropertyChangedListener changeListener = new OnPropertyChangedListener() {
- public void onPropertyChanged(String namespace, String name, String value) {
- // ignore legacy callback
- }
-
- @Override
- public void onPropertiesChanged(DeviceConfig.Properties properties) {
- assertThat(properties.getNamespace()).isEqualTo(sNamespace);
- assertThat(properties.getKeyset().size()).isEqualTo(1);
- assertThat(properties.getKeyset()).contains(sKey);
- assertThat(properties.getString(sKey, "default_value")).isEqualTo(sValue);
- countDownLatch.countDown();
- }
+ OnPropertiesChangedListener changeListener = (properties) -> {
+ assertThat(properties.getNamespace()).isEqualTo(sNamespace);
+ assertThat(properties.getKeyset()).contains(sKey);
+ assertThat(properties.getString(sKey, "default_value")).isEqualTo(sValue);
+ countDownLatch.countDown();
};
- testListener(countDownLatch, changeListener);
+ try {
+ DeviceConfig.addOnPropertiesChangedListener(sNamespace,
+ ActivityThread.currentApplication().getMainExecutor(), changeListener);
+ DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
+ assertThat(countDownLatch.await(
+ WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
+ } catch (InterruptedException e) {
+ Assert.fail(e.getMessage());
+ } finally {
+ DeviceConfig.removeOnPropertiesChangedListener(changeListener);
+ }
}
@Test
- public void testListener_legacyCallback() throws InterruptedException {
+ public void testOnPropertyChangedListener() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
OnPropertyChangedListener changeListener = (namespace, name, value) -> {
@@ -256,12 +259,6 @@
countDownLatch.countDown();
};
- testListener(countDownLatch, changeListener);
-
- }
-
- private void testListener(CountDownLatch countDownLatch,
- OnPropertyChangedListener changeListener) {
try {
DeviceConfig.addOnPropertyChangedListener(sNamespace,
ActivityThread.currentApplication().getMainExecutor(), changeListener);
@@ -273,6 +270,7 @@
} finally {
DeviceConfig.removeOnPropertyChangedListener(changeListener);
}
+
}
private static boolean deleteViaContentProvider(String namespace, String key) {
diff --git a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
index c99777b..0f32a82 100644
--- a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
+++ b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
@@ -89,6 +89,17 @@
assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CATEGORY));
}
+ /** Verify that modifying the returned logMaker won't leave stale data behind for
+ * the next caller.*/
+ @Test
+ public void testLogMakerNoStaleData() {
+ StatusBarNotification sbn = getNotification(PKG, GROUP_ID_1, CHANNEL_ID);
+ final LogMaker logMaker = sbn.getLogMaker();
+ int extraTag = MetricsEvent.FIELD_NOTIFICATION_CHANNEL_GROUP_ID; // An arbitrary new tag
+ logMaker.addTaggedData(extraTag, 1);
+ assertNull(sbn.getLogMaker().getTaggedData(extraTag));
+ }
+
@Test
public void testLogMakerWithCategory() {
Notification.Builder builder = getNotificationBuilder(GROUP_ID_1, CHANNEL_ID)
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index c4632f7..eb9c7b6 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -642,8 +642,9 @@
long startTime = SystemClock.elapsedRealtime();
TestBinderCallsStats bcs = new TestBinderCallsStats();
bcs.setAddDebugEntries(true);
+ bcs.setSamplingInterval(10);
ArrayList<BinderCallsStats.ExportedCallStat> callStats = bcs.getExportedCallStats();
- assertEquals(3, callStats.size());
+ assertEquals(4, callStats.size());
BinderCallsStats.ExportedCallStat debugEntry1 = callStats.get(0);
assertEquals("", debugEntry1.className);
assertEquals("__DEBUG_start_time_millis", debugEntry1.methodName);
@@ -656,6 +657,9 @@
assertEquals("", debugEntry3.className);
assertEquals("__DEBUG_battery_time_millis", debugEntry3.methodName);
assertTrue(debugEntry3.latencyMicros >= 0);
+ BinderCallsStats.ExportedCallStat debugEntry4 = callStats.get(3);
+ assertEquals("__DEBUG_sampling_interval", debugEntry4.methodName);
+ assertEquals(10, debugEntry4.latencyMicros);
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index 3edf5f8..7917a06 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -452,6 +452,7 @@
public void testAddsDebugEntries() {
TestableLooperStats looperStats = new TestableLooperStats(1, 100);
looperStats.setAddDebugEntries(true);
+ looperStats.setSamplingInterval(10);
Message message = mHandlerFirst.obtainMessage(1000);
message.when = looperStats.getSystemUptimeMillis();
@@ -459,7 +460,7 @@
looperStats.messageDispatched(token, message);
List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
- assertThat(entries).hasSize(4);
+ assertThat(entries).hasSize(5);
LooperStats.ExportedEntry debugEntry1 = entries.get(1);
assertThat(debugEntry1.handlerClassName).isEqualTo("");
assertThat(debugEntry1.messageName).isEqualTo("__DEBUG_start_time_millis");
@@ -474,6 +475,9 @@
assertThat(debugEntry3.handlerClassName).isEqualTo("");
assertThat(debugEntry3.messageName).isEqualTo("__DEBUG_battery_time_millis");
assertThat(debugEntry3.totalLatencyMicros).isAtLeast(0L);
+ LooperStats.ExportedEntry debugEntry4 = entries.get(4);
+ assertThat(debugEntry4.messageName).isEqualTo("__DEBUG_sampling_interval");
+ assertThat(debugEntry4.totalLatencyMicros).isEqualTo(10L);
}
@Test
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index c6dc239..1e03c53 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -30,7 +30,7 @@
*
*/
public final class Insets implements Parcelable {
- public static final Insets NONE = new Insets(0, 0, 0, 0);
+ public static final @NonNull Insets NONE = new Insets(0, 0, 0, 0);
public final int left;
public final int top;
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index e617c42..9eeb43b 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1733,7 +1733,7 @@
* @return the paint's extra word-spacing for drawing text in pixels.
* @see #setWordSpacing(float)
*/
- public float getWordSpacing() {
+ public @Px float getWordSpacing() {
return nGetWordSpacing(mNativePaint);
}
@@ -1746,7 +1746,7 @@
* @param wordSpacing set the paint's extra word-spacing for drawing text in pixels.
* @see #getWordSpacing()
*/
- public void setWordSpacing(float wordSpacing) {
+ public void setWordSpacing(@Px float wordSpacing) {
nSetWordSpacing(mNativePaint, wordSpacing);
}
@@ -2706,6 +2706,8 @@
}
/**
+ * Retrieve the text boundary box and store to bounds.
+ *
* Return in bounds (allocated by the caller) the smallest rectangle that
* encloses all of the characters, with an implied origin at (0,0).
*
@@ -2725,6 +2727,8 @@
}
/**
+ * Retrieve the text boundary box and store to bounds.
+ *
* Return in bounds (allocated by the caller) the smallest rectangle that
* encloses all of the characters, with an implied origin at (0,0).
*
@@ -2736,7 +2740,8 @@
* @param end 1 past the last char in the text to measure
* @param bounds returns the unioned bounds of all the text. Must be allocated by the caller
*/
- public void getTextBounds(CharSequence text, int start, int end, Rect bounds) {
+ public void getTextBounds(@NonNull CharSequence text, int start, int end,
+ @NonNull Rect bounds) {
if ((start | end | (end - start) | (text.length() - end)) < 0) {
throw new IndexOutOfBoundsException();
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index e93e757..9518714 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -34,6 +34,7 @@
import android.graphics.fonts.SystemFonts;
import android.os.Build;
import android.os.Build.VERSION_CODES;
+import android.os.ParcelFileDescriptor;
import android.provider.FontRequest;
import android.provider.FontsContract;
import android.text.FontConfig;
@@ -368,7 +369,7 @@
private final AssetManager mAssetManager;
private final String mPath;
- private final Font.Builder mFontBuilder;
+ private final @Nullable Font.Builder mFontBuilder;
private String mFallbackFamilyName;
@@ -395,7 +396,16 @@
* @param fd The file descriptor. The passed fd must be mmap-able.
*/
public Builder(@NonNull FileDescriptor fd) {
- mFontBuilder = new Font.Builder(fd);
+ Font.Builder builder;
+ try {
+ builder = new Font.Builder(ParcelFileDescriptor.dup(fd));
+ } catch (IOException e) {
+ // We cannot tell the error to developer at this moment since we cannot change the
+ // public API signature. Instead, silently fallbacks to system fallback in the build
+ // method as the same as other error cases.
+ builder = null;
+ }
+ mFontBuilder = builder;
mAssetManager = null;
mPath = null;
}
@@ -585,6 +595,9 @@
* @return Newly created Typeface. May return null if some parameters are invalid.
*/
public Typeface build() {
+ if (mFontBuilder == null) {
+ return resolveFallbackTypeface();
+ }
try {
final Font font = mFontBuilder.build();
final String key = mAssetManager == null ? null : createAssetUid(
@@ -687,7 +700,7 @@
* </pre>
* </p>
*/
- public static class CustomFallbackBuilder {
+ public static final class CustomFallbackBuilder {
private static final int MAX_CUSTOM_FALLBACK = 64;
private final ArrayList<FontFamily> mFamilies = new ArrayList<>();
private String mFallbackName = null;
@@ -728,7 +741,7 @@
* @param familyName a family name to be used for fallback if the provided fonts can not be
* used
*/
- public CustomFallbackBuilder setSystemFallback(@NonNull String familyName) {
+ public @NonNull CustomFallbackBuilder setSystemFallback(@NonNull String familyName) {
Preconditions.checkNotNull(familyName);
mFallbackName = familyName;
return this;
@@ -743,7 +756,7 @@
*
* @param style a font style
*/
- public CustomFallbackBuilder setStyle(@NonNull FontStyle style) {
+ public @NonNull CustomFallbackBuilder setStyle(@NonNull FontStyle style) {
mStyle = style;
return this;
}
@@ -758,7 +771,7 @@
* @param family a fallback family
* @throws IllegalArgumentException if you give more than 64 custom fallback families
*/
- public CustomFallbackBuilder addCustomFallback(@NonNull FontFamily family) {
+ public @NonNull CustomFallbackBuilder addCustomFallback(@NonNull FontFamily family) {
Preconditions.checkNotNull(family);
Preconditions.checkArgument(mFamilies.size() < getMaxCustomFallbackCount(),
"Custom fallback limit exceeded(" + getMaxCustomFallbackCount() + ")");
@@ -771,7 +784,7 @@
*
* @return the Typeface object
*/
- public Typeface build() {
+ public @NonNull Typeface build() {
final int userFallbackSize = mFamilies.size();
final FontFamily[] fallback = SystemFonts.getSystemFallback(mFallbackName);
final long[] ptrArray = new long[fallback.length + userFallbackSize];
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 7f165bf..f715f43 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -22,6 +22,7 @@
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.LocaleList;
+import android.os.ParcelFileDescriptor;
import android.util.TypedValue;
import com.android.internal.util.Preconditions;
@@ -31,7 +32,6 @@
import libcore.util.NativeAllocationRegistry;
import java.io.File;
-import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -53,7 +53,7 @@
/**
* A builder class for creating new Font.
*/
- public static class Builder {
+ public static final class Builder {
private static final NativeAllocationRegistry sAssetByteBufferRegistroy =
new NativeAllocationRegistry(ByteBuffer.class.getClassLoader(),
nGetReleaseNativeAssetFunc(), 64);
@@ -122,7 +122,7 @@
*
* @param fd a file descriptor
*/
- public Builder(@NonNull FileDescriptor fd) {
+ public Builder(@NonNull ParcelFileDescriptor fd) {
this(fd, 0, -1);
}
@@ -133,9 +133,9 @@
* @param offset an offset to of the font data in the file
* @param size a size of the font data. If -1 is passed, use until end of the file.
*/
- public Builder(@NonNull FileDescriptor fd, @IntRange(from = 0) long offset,
+ public Builder(@NonNull ParcelFileDescriptor fd, @IntRange(from = 0) long offset,
@IntRange(from = -1) long size) {
- try (FileInputStream fis = new FileInputStream(fd)) {
+ try (FileInputStream fis = new FileInputStream(fd.getFileDescriptor())) {
final FileChannel fc = fis.getChannel();
size = (size == -1) ? fc.size() - offset : size;
mBuffer = fc.map(FileChannel.MapMode.READ_ONLY, offset, size);
@@ -467,7 +467,7 @@
* @see Builder#setSlant(int)
* @return a font style
*/
- public FontStyle getStyle() {
+ public @NonNull FontStyle getStyle() {
return mFontStyle;
}
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index c0f1b16..4772c1c 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -61,7 +61,7 @@
/**
* A builder class for creating new FontFamily.
*/
- public static class Builder {
+ public static final class Builder {
private static final NativeAllocationRegistry sFamilyRegistory =
new NativeAllocationRegistry(FontFamily.class.getClassLoader(),
nGetReleaseNativeFamily(), 64);
@@ -152,7 +152,7 @@
* @param index an index of the font
* @return a registered font
*/
- public Font getFont(@IntRange(from = 0) int index) {
+ public @NonNull Font getFont(@IntRange(from = 0) int index) {
return mFonts.get(index);
}
@@ -161,7 +161,7 @@
*
* @return the number of fonts registered in this family.
*/
- public int getSize() {
+ public @IntRange(from = 1) int getSize() {
return mFonts.size();
}
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 1647909..046bbcf 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -177,10 +177,10 @@
/**
* Helper class for creating a {@link LineBreaker}.
*/
- public static class Builder {
+ public static final class Builder {
private @BreakStrategy int mBreakStrategy = BREAK_STRATEGY_SIMPLE;
private @HyphenationFrequency int mHyphenationFrequency = HYPHENATION_FREQUENCY_NONE;
- private @JustificationMode int mJustified = JUSTIFICATION_MODE_NONE;
+ private @JustificationMode int mJustificationMode = JUSTIFICATION_MODE_NONE;
private @Nullable int[] mIndents = null;
/**
@@ -189,7 +189,7 @@
* You can change the line breaking behavior by setting break strategy. The default value is
* {@link #BREAK_STRATEGY_SIMPLE}.
*/
- public Builder setBreakStrategy(@BreakStrategy int breakStrategy) {
+ public @NonNull Builder setBreakStrategy(@BreakStrategy int breakStrategy) {
mBreakStrategy = breakStrategy;
return this;
}
@@ -200,7 +200,8 @@
* You can change the amount of automatic hyphenation used. The default value is
* {@link #HYPHENATION_FREQUENCY_NONE}.
*/
- public Builder setHyphenationFrequency(@HyphenationFrequency int hyphenationFrequency) {
+ public @NonNull Builder setHyphenationFrequency(
+ @HyphenationFrequency int hyphenationFrequency) {
mHyphenationFrequency = hyphenationFrequency;
return this;
}
@@ -212,8 +213,8 @@
* internal parameters for justification.
* The default value is {@link #JUSTIFICATION_MODE_NONE}
*/
- public Builder setJustified(@JustificationMode int justified) {
- mJustified = justified;
+ public @NonNull Builder setJustificationMode(@JustificationMode int justificationMode) {
+ mJustificationMode = justificationMode;
return this;
}
@@ -224,7 +225,7 @@
* amount is the sum of both left and right indentations. For lines past the last element in
* the array, the indentation amount of the last element is used.
*/
- public Builder setIndents(@Nullable int[] indents) {
+ public @NonNull Builder setIndents(@Nullable int[] indents) {
mIndents = indents;
return this;
}
@@ -234,8 +235,9 @@
*
* You can reuse the Builder instance even after calling this method.
*/
- public LineBreaker build() {
- return new LineBreaker(mBreakStrategy, mHyphenationFrequency, mJustified, mIndents);
+ public @NonNull LineBreaker build() {
+ return new LineBreaker(mBreakStrategy, mHyphenationFrequency, mJustificationMode,
+ mIndents);
}
}
@@ -412,7 +414,7 @@
}
/**
- * Returns a packed packed hyphen edit for the line.
+ * Returns a packed hyphen edit for the line.
*
* @param lineIndex an index of the line.
* @return a packed hyphen edit for the line.
@@ -451,7 +453,7 @@
* @param constraints for a single paragraph
* @param lineNumber a line number of this paragraph
*/
- public Result computeLineBreaks(
+ public @NonNull Result computeLineBreaks(
@NonNull MeasuredText measuredPara,
@NonNull ParagraphConstraints constraints,
@IntRange(from = 0) int lineNumber) {
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
index 2536619..480aff2 100644
--- a/graphics/java/android/graphics/text/MeasuredText.java
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -168,7 +168,7 @@
*
* Note: The appendStyle and appendReplacementRun should be called to cover the text length.
*/
- public static class Builder {
+ public static final class Builder {
private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
MeasuredText.class.getClassLoader(), nGetReleaseFunc(), 1024);
@@ -227,7 +227,7 @@
* text
* @param isRtl true if the text is in RTL context, otherwise false.
*/
- public Builder appendStyleRun(@NonNull Paint paint, @IntRange(from = 0) int length,
+ public @NonNull Builder appendStyleRun(@NonNull Paint paint, @IntRange(from = 0) int length,
boolean isRtl) {
Preconditions.checkNotNull(paint);
Preconditions.checkArgument(length > 0, "length can not be negative");
@@ -253,8 +253,8 @@
* text
* @param width a replacement width of the range
*/
- public Builder appendReplacementRun(@NonNull Paint paint,
- @IntRange(from = 0) int length, @FloatRange(from = 0) float width) {
+ public @NonNull Builder appendReplacementRun(@NonNull Paint paint,
+ @IntRange(from = 0) int length, @Px @FloatRange(from = 0) float width) {
Preconditions.checkArgument(length > 0, "length can not be negative");
final int end = mCurrentOffset + length;
Preconditions.checkArgument(end <= mText.length, "Replacement exceeds the text length");
@@ -275,7 +275,7 @@
*
* @param computeHyphenation true if you want to use automatic hyphenations.
*/
- public Builder setComputeHyphenation(boolean computeHyphenation) {
+ public @NonNull Builder setComputeHyphenation(boolean computeHyphenation) {
mComputeHyphenation = computeHyphenation;
return this;
}
@@ -292,7 +292,7 @@
*
* @param computeLayout true if you want to retrieve full layout info, e.g. bbox.
*/
- public Builder setComputeLayout(boolean computeLayout) {
+ public @NonNull Builder setComputeLayout(boolean computeLayout) {
mComputeLayout = computeLayout;
return this;
}
@@ -305,7 +305,7 @@
* @throws IllegalStateException if the whole text is not covered by one or more runs (style
* or replacement)
*/
- public MeasuredText build() {
+ public @NonNull MeasuredText build() {
ensureNativePtrNoReuse();
if (mCurrentOffset != mText.length) {
throw new IllegalStateException("Style info has not been provided for all text.");
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index cc177af..e62fb61 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -388,7 +388,7 @@
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
- out_values[SYTLE_SOURCE_RESOURCE_ID] = value_source_resid;
+ out_values[STYLE_SOURCE_RESOURCE_ID] = value_source_resid;
if (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY) {
indices_idx++;
diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
index 0cc1d3c..d71aad2 100644
--- a/libs/androidfw/include/androidfw/AttributeResolution.h
+++ b/libs/androidfw/include/androidfw/AttributeResolution.h
@@ -33,7 +33,7 @@
STYLE_RESOURCE_ID = 3,
STYLE_CHANGING_CONFIGURATIONS = 4,
STYLE_DENSITY = 5,
- SYTLE_SOURCE_RESOURCE_ID = 6
+ STYLE_SOURCE_RESOURCE_ID = 6
};
// These are all variations of the same method. They each perform the exact same operation,
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 793dd8d..4f1b2a4 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -69,6 +69,7 @@
"libminikin",
"libandroidfw",
"libcrypto",
+ "libsync",
],
static_libs: [
"libEGL_blobCache",
@@ -180,6 +181,7 @@
"renderthread/EglManager.cpp",
"renderthread/ReliableSurface.cpp",
"renderthread/VulkanManager.cpp",
+ "renderthread/VulkanSurface.cpp",
"renderthread/RenderProxy.cpp",
"renderthread/RenderTask.cpp",
"renderthread/RenderThread.cpp",
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index a15ff22..c174c24 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -19,8 +19,6 @@
#include "renderstate/RenderState.h"
#include "utils/Color.h"
-#include <SkToSRGBColorFilter.h>
-
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 2ffda83..fe633e9 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -20,7 +20,6 @@
#include "renderthread/EglManager.h"
#include "renderthread/VulkanManager.h"
-#include <SkToSRGBColorFilter.h>
#include <gui/Surface.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 1ff7ffe..e0ed3e4 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -134,6 +134,7 @@
void RenderNode::damageSelf(TreeInfo& info) {
if (isRenderable()) {
+ mDamageGenerationId = info.damageGenerationId;
if (properties().getClipDamageToBounds()) {
info.damageAccumulator->dirty(0, 0, properties().getWidth(), properties().getHeight());
} else {
@@ -199,6 +200,12 @@
* stencil buffer may be needed. Views that use a functor to draw will be forced onto a layer.
*/
void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer) {
+ if (mDamageGenerationId == info.damageGenerationId) {
+ // We hit the same node a second time in the same tree. We don't know the minimal
+ // damage rect anymore, so just push the biggest we can onto our parent's transform
+ // We push directly onto parent in case we are clipped to bounds but have moved position.
+ info.damageAccumulator->dirty(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX);
+ }
info.damageAccumulator->pushTransform(this);
if (info.mode == TreeInfo::MODE_FULL) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 6060123..23e7a0e 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -255,6 +255,8 @@
DisplayList* mDisplayList;
DisplayList* mStagingDisplayList;
+ int64_t mDamageGenerationId;
+
friend class AnimatorManager;
AnimatorManager mAnimatorManager;
diff --git a/libs/hwui/TreeInfo.cpp b/libs/hwui/TreeInfo.cpp
index 808a12a..cdad20e 100644
--- a/libs/hwui/TreeInfo.cpp
+++ b/libs/hwui/TreeInfo.cpp
@@ -24,6 +24,7 @@
: mode(mode)
, prepareTextures(mode == MODE_FULL)
, canvasContext(canvasContext)
+ , damageGenerationId(canvasContext.getFrameNumber())
, disableForceDark(canvasContext.useForceDark() ? 0 : 1) {}
} // namespace android::uirenderer
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index a0d9605..04eabac 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -87,6 +87,7 @@
// Must not be null during actual usage
DamageAccumulator* damageAccumulator = nullptr;
+ int64_t damageGenerationId = 0;
LayerUpdateQueue* layerUpdateQueue = nullptr;
ErrorHandler* errorHandler = nullptr;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 87cffb5..edde6d3 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -55,20 +55,8 @@
}
Frame SkiaVulkanPipeline::getFrame() {
- LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
- "drawRenderNode called on a context with no surface!");
-
- SkSurface* backBuffer = mVkManager.getBackbufferSurface(&mVkSurface);
- LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
- "drawRenderNode called on a context with an invalid surface");
- if (backBuffer == nullptr) {
- SkDebugf("failed to get backbuffer");
- return Frame(-1, -1, 0);
- }
-
- Frame frame(mVkSurface->windowWidth(), mVkSurface->windowHeight(),
- mVkManager.getAge(mVkSurface));
- return frame;
+ LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!");
+ return mVkManager.dequeueNextBuffer(mVkSurface);
}
bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
@@ -77,13 +65,13 @@
bool opaque, const LightInfo& lightInfo,
const std::vector<sp<RenderNode>>& renderNodes,
FrameInfoVisualizer* profiler) {
- sk_sp<SkSurface> backBuffer = mVkSurface->getBackBufferSurface();
+ sk_sp<SkSurface> backBuffer = mVkSurface->getCurrentSkSurface();
if (backBuffer.get() == nullptr) {
return false;
}
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
- backBuffer, mVkSurface->preTransform());
+ backBuffer, mVkSurface->getCurrentPreTransform());
ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
layerUpdateQueue->clear();
@@ -113,7 +101,7 @@
currentFrameInfo->markSwapBuffers();
if (*requireSwap) {
- mVkManager.swapBuffers(mVkSurface);
+ mVkManager.swapBuffers(mVkSurface, screenDirty);
}
return *requireSwap;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 2c24edd..77a7ab1 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -18,6 +18,7 @@
#include "SkiaPipeline.h"
#include "renderthread/VulkanManager.h"
+#include "renderthread/VulkanSurface.h"
#include "renderstate/RenderState.h"
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 5af660c..6dacc7a 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -16,6 +16,7 @@
#include "VulkanManager.h"
+#include <android/sync.h>
#include <gui/Surface.h>
#include "Properties.h"
@@ -23,6 +24,7 @@
#include "renderstate/RenderState.h"
#include "utils/FatVector.h"
+#include <GrBackendSemaphore.h>
#include <GrBackendSurface.h>
#include <GrContext.h>
#include <GrTypes.h>
@@ -79,7 +81,9 @@
mDevice = VK_NULL_HANDLE;
mPhysicalDevice = VK_NULL_HANDLE;
mInstance = VK_NULL_HANDLE;
+ mInstanceExtensionsOwner.clear();
mInstanceExtensions.clear();
+ mDeviceExtensionsOwner.clear();
mDeviceExtensions.clear();
free_features_extensions_structs(mPhysicalDeviceFeatures2);
mPhysicalDeviceFeatures2 = {};
@@ -104,18 +108,18 @@
uint32_t extensionCount = 0;
err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
- std::unique_ptr<VkExtensionProperties[]> extensions(
- new VkExtensionProperties[extensionCount]);
- err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.get());
+ mInstanceExtensionsOwner.resize(extensionCount);
+ err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
+ mInstanceExtensionsOwner.data());
LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
bool hasKHRSurfaceExtension = false;
bool hasKHRAndroidSurfaceExtension = false;
- for (uint32_t i = 0; i < extensionCount; ++i) {
- mInstanceExtensions.push_back(extensions[i].extensionName);
- if (!strcmp(extensions[i].extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
+ for (const VkExtensionProperties& extension : mInstanceExtensionsOwner) {
+ mInstanceExtensions.push_back(extension.extensionName);
+ if (!strcmp(extension.extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
hasKHRSurfaceExtension = true;
}
- if (!strcmp(extensions[i].extensionName,VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
+ if (!strcmp(extension.extensionName, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
hasKHRAndroidSurfaceExtension = true;
}
}
@@ -142,6 +146,7 @@
GET_INST_PROC(GetPhysicalDeviceProperties);
GET_INST_PROC(GetPhysicalDeviceQueueFamilyProperties);
GET_INST_PROC(GetPhysicalDeviceFeatures2);
+ GET_INST_PROC(GetPhysicalDeviceImageFormatProperties2);
GET_INST_PROC(CreateDevice);
GET_INST_PROC(EnumerateDeviceExtensionProperties);
GET_INST_PROC(CreateAndroidSurfaceKHR);
@@ -193,15 +198,14 @@
err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
nullptr);
LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
- std::unique_ptr<VkExtensionProperties[]> extensions(
- new VkExtensionProperties[extensionCount]);
+ mDeviceExtensionsOwner.resize(extensionCount);
err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
- extensions.get());
+ mDeviceExtensionsOwner.data());
LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
bool hasKHRSwapchainExtension = false;
- for (uint32_t i = 0; i < extensionCount; ++i) {
- mDeviceExtensions.push_back(extensions[i].extensionName);
- if (!strcmp(extensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
+ for (const VkExtensionProperties& extension : mDeviceExtensionsOwner) {
+ mDeviceExtensions.push_back(extension.extensionName);
+ if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
hasKHRSwapchainExtension = true;
}
}
@@ -214,6 +218,7 @@
}
return vkGetInstanceProcAddr(instance, proc_name);
};
+
grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
mInstanceExtensions.data(), mDeviceExtensions.size(), mDeviceExtensions.data());
@@ -318,11 +323,6 @@
GET_DEV_PROC(GetDeviceQueue);
GET_DEV_PROC(DeviceWaitIdle);
GET_DEV_PROC(DestroyDevice);
- GET_DEV_PROC(CreateSwapchainKHR);
- GET_DEV_PROC(DestroySwapchainKHR);
- GET_DEV_PROC(GetSwapchainImagesKHR);
- GET_DEV_PROC(AcquireNextImageKHR);
- GET_DEV_PROC(QueuePresentKHR);
GET_DEV_PROC(CreateCommandPool);
GET_DEV_PROC(DestroyCommandPool);
GET_DEV_PROC(AllocateCommandBuffers);
@@ -426,201 +426,102 @@
};
}
-// Returns the next BackbufferInfo to use for the next draw. The function will make sure all
-// previous uses have finished before returning.
-VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurface* surface) {
- SkASSERT(surface->mBackbuffers);
+Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
- ++surface->mCurrentBackbufferIndex;
- if (surface->mCurrentBackbufferIndex > surface->mImageCount) {
- surface->mCurrentBackbufferIndex = 0;
+ VulkanSurface::NativeBufferInfo* bufferInfo = surface->dequeueNativeBuffer();
+
+ if (bufferInfo == nullptr) {
+ ALOGE("VulkanSurface::dequeueNativeBuffer called with an invalid surface!");
+ return Frame(-1, -1, 0);
}
- VulkanSurface::BackbufferInfo* backbuffer =
- surface->mBackbuffers + surface->mCurrentBackbufferIndex;
+ LOG_ALWAYS_FATAL_IF(!bufferInfo->dequeued);
- // Before we reuse a backbuffer, make sure its fences have all signaled so that we can safely
- // reuse its commands buffers.
- VkResult res = mWaitForFences(mDevice, 2, backbuffer->mUsageFences, true, UINT64_MAX);
- if (res != VK_SUCCESS) {
- return nullptr;
+ if (bufferInfo->dequeue_fence != -1) {
+ int fence_clone = dup(bufferInfo->dequeue_fence);
+ if (fence_clone == -1) {
+ ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno), errno);
+ sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
+ } else {
+ VkSemaphoreCreateInfo semaphoreInfo;
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreInfo.pNext = nullptr;
+ semaphoreInfo.flags = 0;
+ VkSemaphore semaphore;
+ VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
+ LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to create import semaphore, err: %d",
+ err);
+
+ VkImportSemaphoreFdInfoKHR importInfo;
+ importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
+ importInfo.pNext = nullptr;
+ importInfo.semaphore = semaphore;
+ importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
+ importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+ importInfo.fd = fence_clone;
+
+ err = mImportSemaphoreFdKHR(mDevice, &importInfo);
+ LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to import semaphore, err: %d", err);
+
+ GrBackendSemaphore backendSemaphore;
+ backendSemaphore.initVulkan(semaphore);
+ bufferInfo->skSurface->wait(1, &backendSemaphore);
+ }
}
- return backbuffer;
+ int bufferAge = (mSwapBehavior == SwapBehavior::Discard) ? 0 : surface->getCurrentBuffersAge();
+ return Frame(surface->logicalWidth(), surface->logicalHeight(), bufferAge);
}
-static SkMatrix getPreTransformMatrix(int width, int height,
- VkSurfaceTransformFlagBitsKHR transform) {
- switch (transform) {
- case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
- return SkMatrix::I();
- case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
- return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
- return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
- return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
- return SkMatrix::MakeAll(-1, 0, width, 0, 1, 0, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
- return SkMatrix::MakeAll(0, -1, height, -1, 0, width, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
- return SkMatrix::MakeAll(1, 0, 0, 0, -1, height, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
- return SkMatrix::MakeAll(0, 1, 0, 1, 0, 0, 0, 0, 1);
- default:
- LOG_ALWAYS_FATAL("Unsupported pre transform of swapchain.");
- }
- return SkMatrix::I();
-}
-
-
-SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
- // Recreate VulkanSurface, if ANativeWindow has been resized.
- VulkanSurface* surface = *surfaceOut;
- int windowWidth = 0, windowHeight = 0;
- ANativeWindow* window = surface->mNativeWindow;
- window->query(window, NATIVE_WINDOW_WIDTH, &windowWidth);
- window->query(window, NATIVE_WINDOW_HEIGHT, &windowHeight);
- if (windowWidth != surface->mWindowWidth || windowHeight != surface->mWindowHeight) {
- ColorMode colorMode = surface->mColorMode;
- sk_sp<SkColorSpace> colorSpace = surface->mColorSpace;
- SkColorType colorType = surface->mColorType;
- GrContext* grContext = surface->mGrContext;
- destroySurface(surface);
- *surfaceOut = createSurface(window, colorMode, colorSpace, colorType, grContext);
- surface = *surfaceOut;
- if (!surface) {
- return nullptr;
- }
+void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
+ if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
+ ATRACE_NAME("Finishing GPU work");
+ mDeviceWaitIdle(mDevice);
}
- VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface);
- SkASSERT(backbuffer);
+ VkExportSemaphoreCreateInfo exportInfo;
+ exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
+ exportInfo.pNext = nullptr;
+ exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- VkResult res;
+ VkSemaphoreCreateInfo semaphoreInfo;
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreInfo.pNext = &exportInfo;
+ semaphoreInfo.flags = 0;
+ VkSemaphore semaphore;
+ VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
+ ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to create semaphore");
- res = mResetFences(mDevice, 2, backbuffer->mUsageFences);
- SkASSERT(VK_SUCCESS == res);
+ GrBackendSemaphore backendSemaphore;
+ backendSemaphore.initVulkan(semaphore);
- // The acquire will signal the attached mAcquireSemaphore. We use this to know the image has
- // finished presenting and that it is safe to begin sending new commands to the returned image.
- res = mAcquireNextImageKHR(mDevice, surface->mSwapchain, UINT64_MAX,
- backbuffer->mAcquireSemaphore, VK_NULL_HANDLE,
- &backbuffer->mImageIndex);
+ VulkanSurface::NativeBufferInfo* bufferInfo = surface->getCurrentBufferInfo();
- if (VK_ERROR_SURFACE_LOST_KHR == res) {
- // need to figure out how to create a new vkSurface without the platformData*
- // maybe use attach somehow? but need a Window
- return nullptr;
- }
- if (VK_ERROR_OUT_OF_DATE_KHR == res || VK_SUBOPTIMAL_KHR == res) {
- // tear swapchain down and try again
- if (!createSwapchain(surface)) {
- return nullptr;
- }
- backbuffer = getAvailableBackbuffer(surface);
- res = mResetFences(mDevice, 2, backbuffer->mUsageFences);
- SkASSERT(VK_SUCCESS == res);
+ int fenceFd = -1;
+ GrSemaphoresSubmitted submitted =
+ bufferInfo->skSurface->flush(SkSurface::BackendSurfaceAccess::kPresent,
+ SkSurface::kNone_FlushFlags, 1, &backendSemaphore);
+ if (submitted == GrSemaphoresSubmitted::kYes) {
+ VkSemaphoreGetFdInfoKHR getFdInfo;
+ getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
+ getFdInfo.pNext = nullptr;
+ getFdInfo.semaphore = semaphore;
+ getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- // acquire the image
- res = mAcquireNextImageKHR(mDevice, surface->mSwapchain, UINT64_MAX,
- backbuffer->mAcquireSemaphore, VK_NULL_HANDLE,
- &backbuffer->mImageIndex);
-
- if (VK_SUCCESS != res) {
- return nullptr;
- }
+ err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
+ ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
+ } else {
+ ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");
+ mQueueWaitIdle(mGraphicsQueue);
}
- // set up layout transfer from initial to color attachment
- VkImageLayout layout = surface->mImageInfos[backbuffer->mImageIndex].mImageLayout;
- SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout || VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout);
- VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkAccessFlags srcAccessMask = 0;
- VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ surface->presentCurrentBuffer(dirtyRect, fenceFd);
- VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
- mPresentQueueIndex, // srcQueueFamilyIndex
- mGraphicsQueueIndex, // dstQueueFamilyIndex
- surface->mImages[backbuffer->mImageIndex], // image
- {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
- };
- mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[0], 0);
-
- VkCommandBufferBeginInfo info;
- memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = 0;
- mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[0], &info);
-
- mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[0], srcStageMask, dstStageMask, 0, 0,
- nullptr, 0, nullptr, 1, &imageMemoryBarrier);
-
- mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[0]);
-
- VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- // insert the layout transfer into the queue and wait on the acquire
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 1;
- // Wait to make sure aquire semaphore set above has signaled.
- submitInfo.pWaitSemaphores = &backbuffer->mAcquireSemaphore;
- submitInfo.pWaitDstStageMask = &waitDstStageFlags;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &backbuffer->mTransitionCmdBuffers[0];
- submitInfo.signalSemaphoreCount = 0;
-
- // Attach first fence to submission here so we can track when the command buffer finishes.
- mQueueSubmit(mGraphicsQueue, 1, &submitInfo, backbuffer->mUsageFences[0]);
-
- // We need to notify Skia that we changed the layout of the wrapped VkImage
- sk_sp<SkSurface> skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface;
- GrBackendRenderTarget backendRT = skSurface->getBackendRenderTarget(
- SkSurface::kFlushRead_BackendHandleAccess);
- if (!backendRT.isValid()) {
- SkASSERT(backendRT.isValid());
- return nullptr;
- }
- backendRT.setVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-
- surface->mPreTransform = getPreTransformMatrix(surface->windowWidth(),
- surface->windowHeight(),
- surface->mTransform);
-
- surface->mBackbuffer = std::move(skSurface);
- return surface->mBackbuffer.get();
-}
-
-void VulkanManager::destroyBuffers(VulkanSurface* surface) {
- if (surface->mBackbuffers) {
- for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
- mWaitForFences(mDevice, 2, surface->mBackbuffers[i].mUsageFences, true, UINT64_MAX);
- surface->mBackbuffers[i].mImageIndex = -1;
- mDestroySemaphore(mDevice, surface->mBackbuffers[i].mAcquireSemaphore, nullptr);
- mDestroySemaphore(mDevice, surface->mBackbuffers[i].mRenderSemaphore, nullptr);
- mFreeCommandBuffers(mDevice, mCommandPool, 2,
- surface->mBackbuffers[i].mTransitionCmdBuffers);
- mDestroyFence(mDevice, surface->mBackbuffers[i].mUsageFences[0], 0);
- mDestroyFence(mDevice, surface->mBackbuffers[i].mUsageFences[1], 0);
- }
- }
-
- delete[] surface->mBackbuffers;
- surface->mBackbuffers = nullptr;
- delete[] surface->mImageInfos;
- surface->mImageInfos = nullptr;
- delete[] surface->mImages;
- surface->mImages = nullptr;
+ // Exporting a semaphore with copy transference via vkGetSemaphoreFdKHR, has the same effect of
+ // destroying the semaphore and creating a new one with the same handle, and the payloads
+ // ownership is move to the Fd we created. Thus the semaphore is in a state that we can delete
+ // it and we don't need to wait on the command buffer we submitted to finish.
+ mDestroySemaphore(mDevice, semaphore, nullptr);
}
void VulkanManager::destroySurface(VulkanSurface* surface) {
@@ -630,271 +531,9 @@
}
mDeviceWaitIdle(mDevice);
- destroyBuffers(surface);
-
- if (VK_NULL_HANDLE != surface->mSwapchain) {
- mDestroySwapchainKHR(mDevice, surface->mSwapchain, nullptr);
- surface->mSwapchain = VK_NULL_HANDLE;
- }
-
- if (VK_NULL_HANDLE != surface->mVkSurface) {
- mDestroySurfaceKHR(mInstance, surface->mVkSurface, nullptr);
- surface->mVkSurface = VK_NULL_HANDLE;
- }
delete surface;
}
-void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExtent2D extent) {
- mGetSwapchainImagesKHR(mDevice, surface->mSwapchain, &surface->mImageCount, nullptr);
- SkASSERT(surface->mImageCount);
- surface->mImages = new VkImage[surface->mImageCount];
- mGetSwapchainImagesKHR(mDevice, surface->mSwapchain, &surface->mImageCount, surface->mImages);
-
- SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
-
- // set up initial image layouts and create surfaces
- surface->mImageInfos = new VulkanSurface::ImageInfo[surface->mImageCount];
- for (uint32_t i = 0; i < surface->mImageCount; ++i) {
- GrVkImageInfo info;
- info.fImage = surface->mImages[i];
- info.fAlloc = GrVkAlloc();
- info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
- info.fFormat = format;
- info.fLevelCount = 1;
-
- GrBackendRenderTarget backendRT(extent.width, extent.height, 0, 0, info);
-
- VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
- imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(
- surface->mGrContext, backendRT, kTopLeft_GrSurfaceOrigin,
- surface->mColorType, surface->mColorSpace, &props);
- }
-
- SkASSERT(mCommandPool != VK_NULL_HANDLE);
-
- // set up the backbuffers
- VkSemaphoreCreateInfo semaphoreInfo;
- memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
- semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreInfo.pNext = nullptr;
- semaphoreInfo.flags = 0;
- VkCommandBufferAllocateInfo commandBuffersInfo;
- memset(&commandBuffersInfo, 0, sizeof(VkCommandBufferAllocateInfo));
- commandBuffersInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- commandBuffersInfo.pNext = nullptr;
- commandBuffersInfo.commandPool = mCommandPool;
- commandBuffersInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- commandBuffersInfo.commandBufferCount = 2;
- VkFenceCreateInfo fenceInfo;
- memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
- fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceInfo.pNext = nullptr;
- fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-
- // we create one additional backbuffer structure here, because we want to
- // give the command buffers they contain a chance to finish before we cycle back
- surface->mBackbuffers = new VulkanSurface::BackbufferInfo[surface->mImageCount + 1];
- for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
- SkDEBUGCODE(VkResult res);
- surface->mBackbuffers[i].mImageIndex = -1;
- SkDEBUGCODE(res =) mCreateSemaphore(mDevice, &semaphoreInfo, nullptr,
- &surface->mBackbuffers[i].mAcquireSemaphore);
- SkDEBUGCODE(res =) mCreateSemaphore(mDevice, &semaphoreInfo, nullptr,
- &surface->mBackbuffers[i].mRenderSemaphore);
- SkDEBUGCODE(res =) mAllocateCommandBuffers(mDevice, &commandBuffersInfo,
- surface->mBackbuffers[i].mTransitionCmdBuffers);
- SkDEBUGCODE(res =) mCreateFence(mDevice, &fenceInfo, nullptr,
- &surface->mBackbuffers[i].mUsageFences[0]);
- SkDEBUGCODE(res =) mCreateFence(mDevice, &fenceInfo, nullptr,
- &surface->mBackbuffers[i].mUsageFences[1]);
- SkASSERT(VK_SUCCESS == res);
- }
- surface->mCurrentBackbufferIndex = surface->mImageCount;
-}
-
-bool VulkanManager::createSwapchain(VulkanSurface* surface) {
- // check for capabilities
- VkSurfaceCapabilitiesKHR caps;
- VkResult res = mGetPhysicalDeviceSurfaceCapabilitiesKHR(mPhysicalDevice,
- surface->mVkSurface, &caps);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- uint32_t surfaceFormatCount;
- res = mGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDevice, surface->mVkSurface,
- &surfaceFormatCount, nullptr);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- FatVector<VkSurfaceFormatKHR, 4> surfaceFormats(surfaceFormatCount);
- res = mGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDevice, surface->mVkSurface,
- &surfaceFormatCount, surfaceFormats.data());
- if (VK_SUCCESS != res) {
- return false;
- }
-
- uint32_t presentModeCount;
- res = mGetPhysicalDeviceSurfacePresentModesKHR(mPhysicalDevice,
- surface->mVkSurface, &presentModeCount, nullptr);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- FatVector<VkPresentModeKHR, VK_PRESENT_MODE_RANGE_SIZE_KHR> presentModes(presentModeCount);
- res = mGetPhysicalDeviceSurfacePresentModesKHR(mPhysicalDevice,
- surface->mVkSurface, &presentModeCount,
- presentModes.data());
- if (VK_SUCCESS != res) {
- return false;
- }
-
- if (!SkToBool(caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)) {
- return false;
- }
- VkSurfaceTransformFlagBitsKHR transform;
- if (SkToBool(caps.supportedTransforms & caps.currentTransform) &&
- !SkToBool(caps.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR)) {
- transform = caps.currentTransform;
- } else {
- transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- }
-
- VkExtent2D extent = caps.currentExtent;
- // clamp width; to handle currentExtent of -1 and protect us from broken hints
- if (extent.width < caps.minImageExtent.width) {
- extent.width = caps.minImageExtent.width;
- }
- SkASSERT(extent.width <= caps.maxImageExtent.width);
- // clamp height
- if (extent.height < caps.minImageExtent.height) {
- extent.height = caps.minImageExtent.height;
- }
- SkASSERT(extent.height <= caps.maxImageExtent.height);
-
- VkExtent2D swapExtent = extent;
- if (transform == VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||
- transform == VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR ||
- transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR ||
- transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
- swapExtent.width = extent.height;
- swapExtent.height = extent.width;
- }
-
- surface->mWindowWidth = extent.width;
- surface->mWindowHeight = extent.height;
-
- uint32_t imageCount = std::max<uint32_t>(3, caps.minImageCount);
- if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
- // Application must settle for fewer images than desired:
- imageCount = caps.maxImageCount;
- }
-
- // Currently Skia requires the images to be color attchments and support all transfer
- // operations.
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
-
- SkASSERT(caps.supportedCompositeAlpha &
- (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
- VkCompositeAlphaFlagBitsKHR composite_alpha =
- (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
- ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
- : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
-
- VkFormat surfaceFormat = VK_FORMAT_R8G8B8A8_UNORM;
- VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
- if (surface->mColorType == SkColorType::kRGBA_F16_SkColorType) {
- surfaceFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
- }
-
- if (surface->mColorMode == ColorMode::WideColorGamut) {
- skcms_Matrix3x3 surfaceGamut;
- LOG_ALWAYS_FATAL_IF(!surface->mColorSpace->toXYZD50(&surfaceGamut),
- "Could not get gamut matrix from color space");
- if (memcmp(&surfaceGamut, &SkNamedGamut::kSRGB, sizeof(surfaceGamut)) == 0) {
- colorSpace = VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT;
- } else if (memcmp(&surfaceGamut, &SkNamedGamut::kDCIP3, sizeof(surfaceGamut)) == 0) {
- colorSpace = VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT;
- } else {
- LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
- }
- }
-
- bool foundSurfaceFormat = false;
- for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
- if (surfaceFormat == surfaceFormats[i].format
- && colorSpace == surfaceFormats[i].colorSpace) {
- foundSurfaceFormat = true;
- break;
- }
- }
-
- if (!foundSurfaceFormat) {
- return false;
- }
-
- // FIFO is always available and will match what we do on GL so just pick that here.
- VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
-
- VkSwapchainCreateInfoKHR swapchainCreateInfo;
- memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
- swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- swapchainCreateInfo.surface = surface->mVkSurface;
- swapchainCreateInfo.minImageCount = imageCount;
- swapchainCreateInfo.imageFormat = surfaceFormat;
- swapchainCreateInfo.imageColorSpace = colorSpace;
- swapchainCreateInfo.imageExtent = swapExtent;
- swapchainCreateInfo.imageArrayLayers = 1;
- swapchainCreateInfo.imageUsage = usageFlags;
-
- uint32_t queueFamilies[] = {mGraphicsQueueIndex, mPresentQueueIndex};
- if (mGraphicsQueueIndex != mPresentQueueIndex) {
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
- swapchainCreateInfo.queueFamilyIndexCount = 2;
- swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
- } else {
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchainCreateInfo.queueFamilyIndexCount = 0;
- swapchainCreateInfo.pQueueFamilyIndices = nullptr;
- }
-
- swapchainCreateInfo.preTransform = transform;
- swapchainCreateInfo.compositeAlpha = composite_alpha;
- swapchainCreateInfo.presentMode = mode;
- swapchainCreateInfo.clipped = true;
- swapchainCreateInfo.oldSwapchain = surface->mSwapchain;
-
- res = mCreateSwapchainKHR(mDevice, &swapchainCreateInfo, nullptr, &surface->mSwapchain);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- surface->mTransform = transform;
-
- // destroy the old swapchain
- if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
- mDeviceWaitIdle(mDevice);
-
- destroyBuffers(surface);
-
- mDestroySwapchainKHR(mDevice, swapchainCreateInfo.oldSwapchain, nullptr);
- }
-
- createBuffers(surface, surfaceFormat, swapExtent);
-
- // The window content is not updated (frozen) until a buffer of the window size is received.
- // This prevents temporary stretching of the window after it is resized, but before the first
- // buffer with new size is enqueued.
- native_window_set_scaling_mode(surface->mNativeWindow, NATIVE_WINDOW_SCALING_MODE_FREEZE);
-
- return true;
-}
-
VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
SkColorType surfaceColorType,
@@ -904,185 +543,8 @@
return nullptr;
}
- VulkanSurface* surface = new VulkanSurface(colorMode, window, surfaceColorSpace,
- surfaceColorType, grContext);
-
- VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
- memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
- surfaceCreateInfo.pNext = nullptr;
- surfaceCreateInfo.flags = 0;
- surfaceCreateInfo.window = window;
-
- VkResult res = mCreateAndroidSurfaceKHR(mInstance, &surfaceCreateInfo, nullptr,
- &surface->mVkSurface);
- if (VK_SUCCESS != res) {
- delete surface;
- return nullptr;
- }
-
- SkDEBUGCODE(VkBool32 supported; res = mGetPhysicalDeviceSurfaceSupportKHR(
- mPhysicalDevice, mPresentQueueIndex, surface->mVkSurface, &supported);
- // All physical devices and queue families on Android must be capable of
- // presentation with any native window.
- SkASSERT(VK_SUCCESS == res && supported););
-
- if (!createSwapchain(surface)) {
- destroySurface(surface);
- return nullptr;
- }
-
- return surface;
-}
-
-// Helper to know which src stage flags we need to set when transitioning to the present layout
-static VkPipelineStageFlags layoutToPipelineSrcStageFlags(const VkImageLayout layout) {
- if (VK_IMAGE_LAYOUT_GENERAL == layout) {
- return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
- } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout ||
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
- return VK_PIPELINE_STAGE_TRANSFER_BIT;
- } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
- return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout ||
- VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == layout) {
- return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
- return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
- return VK_PIPELINE_STAGE_HOST_BIT;
- }
-
- SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout);
- return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
-}
-
-// Helper to know which src access mask we need to set when transitioning to the present layout
-static VkAccessFlags layoutToSrcAccessMask(const VkImageLayout layout) {
- VkAccessFlags flags = 0;
- if (VK_IMAGE_LAYOUT_GENERAL == layout) {
- flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT |
- VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_HOST_WRITE_BIT |
- VK_ACCESS_HOST_READ_BIT;
- } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
- flags = VK_ACCESS_HOST_WRITE_BIT;
- } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
- flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout) {
- flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
- flags = VK_ACCESS_TRANSFER_WRITE_BIT;
- } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) {
- flags = VK_ACCESS_TRANSFER_READ_BIT;
- } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
- flags = VK_ACCESS_SHADER_READ_BIT;
- }
- return flags;
-}
-
-void VulkanManager::swapBuffers(VulkanSurface* surface) {
- if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
- ATRACE_NAME("Finishing GPU work");
- mDeviceWaitIdle(mDevice);
- }
-
- SkASSERT(surface->mBackbuffers);
- VulkanSurface::BackbufferInfo* backbuffer =
- surface->mBackbuffers + surface->mCurrentBackbufferIndex;
-
- SkSurface* skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface.get();
- GrBackendRenderTarget backendRT = skSurface->getBackendRenderTarget(
- SkSurface::kFlushRead_BackendHandleAccess);
- SkASSERT(backendRT.isValid());
-
- GrVkImageInfo imageInfo;
- SkAssertResult(backendRT.getVkImageInfo(&imageInfo));
-
- // Check to make sure we never change the actually wrapped image
- SkASSERT(imageInfo.fImage == surface->mImages[backbuffer->mImageIndex]);
-
- // We need to transition the image to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR and make sure that all
- // previous work is complete for before presenting. So we first add the necessary barrier here.
- VkImageLayout layout = imageInfo.fImageLayout;
- VkPipelineStageFlags srcStageMask = layoutToPipelineSrcStageFlags(layout);
- VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- VkAccessFlags srcAccessMask = layoutToSrcAccessMask(layout);
- VkAccessFlags dstAccessMask = 0;
-
- VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
- mGraphicsQueueIndex, // srcQueueFamilyIndex
- mPresentQueueIndex, // dstQueueFamilyIndex
- surface->mImages[backbuffer->mImageIndex], // image
- {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
- };
-
- mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[1], 0);
- VkCommandBufferBeginInfo info;
- memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = 0;
- mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[1], &info);
- mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[1], srcStageMask, dstStageMask, 0, 0,
- nullptr, 0, nullptr, 1, &imageMemoryBarrier);
- mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[1]);
-
- surface->mImageInfos[backbuffer->mImageIndex].mImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-
- // insert the layout transfer into the queue and wait on the acquire
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 0;
- submitInfo.pWaitDstStageMask = 0;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &backbuffer->mTransitionCmdBuffers[1];
- submitInfo.signalSemaphoreCount = 1;
- // When this command buffer finishes we will signal this semaphore so that we know it is now
- // safe to present the image to the screen.
- submitInfo.pSignalSemaphores = &backbuffer->mRenderSemaphore;
-
- // Attach second fence to submission here so we can track when the command buffer finishes.
- mQueueSubmit(mGraphicsQueue, 1, &submitInfo, backbuffer->mUsageFences[1]);
-
- // Submit present operation to present queue. We use a semaphore here to make sure all rendering
- // to the image is complete and that the layout has been change to present on the graphics
- // queue.
- const VkPresentInfoKHR presentInfo = {
- VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
- NULL, // pNext
- 1, // waitSemaphoreCount
- &backbuffer->mRenderSemaphore, // pWaitSemaphores
- 1, // swapchainCount
- &surface->mSwapchain, // pSwapchains
- &backbuffer->mImageIndex, // pImageIndices
- NULL // pResults
- };
-
- mQueuePresentKHR(mPresentQueue, &presentInfo);
-
- surface->mBackbuffer.reset();
- surface->mImageInfos[backbuffer->mImageIndex].mLastUsed = surface->mCurrentTime;
- surface->mImageInfos[backbuffer->mImageIndex].mInvalid = false;
- surface->mCurrentTime++;
-}
-
-int VulkanManager::getAge(VulkanSurface* surface) {
- SkASSERT(surface->mBackbuffers);
- VulkanSurface::BackbufferInfo* backbuffer =
- surface->mBackbuffers + surface->mCurrentBackbufferIndex;
- if (mSwapBehavior == SwapBehavior::Discard ||
- surface->mImageInfos[backbuffer->mImageIndex].mInvalid) {
- return 0;
- }
- uint16_t lastUsed = surface->mImageInfos[backbuffer->mImageIndex].mLastUsed;
- return surface->mCurrentTime - lastUsed;
+ return VulkanSurface::Create(window, colorMode, surfaceColorType, surfaceColorSpace, grContext,
+ *this);
}
bool VulkanManager::setupDummyCommandBuffer() {
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 95c9630..c2d1802 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -28,7 +28,9 @@
#include <ui/Fence.h>
#include <utils/StrongPointer.h>
#include <vk/GrVkBackendContext.h>
+#include "Frame.h"
#include "IRenderPipeline.h"
+#include "VulkanSurface.h"
class GrVkExtensions;
@@ -38,66 +40,6 @@
class RenderThread;
-class VulkanSurface {
-public:
- VulkanSurface(ColorMode colorMode, ANativeWindow* window, sk_sp<SkColorSpace> colorSpace,
- SkColorType colorType, GrContext* grContext)
- : mColorMode(colorMode), mNativeWindow(window), mColorSpace(colorSpace),
- mColorType(colorType), mGrContext(grContext) {}
-
- sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
-
- // The width and height are are the logical width and height for when submitting draws to the
- // surface. In reality if the window is rotated the underlying VkImage may have the width and
- // height swapped.
- int windowWidth() const { return mWindowWidth; }
- int windowHeight() const { return mWindowHeight; }
-
- SkMatrix& preTransform() { return mPreTransform; }
-
-private:
- friend class VulkanManager;
- struct BackbufferInfo {
- uint32_t mImageIndex; // image this is associated with
- VkSemaphore mAcquireSemaphore; // we signal on this for acquisition of image
- VkSemaphore mRenderSemaphore; // we wait on this for rendering to be done
- VkCommandBuffer
- mTransitionCmdBuffers[2]; // to transition layout between present and render
- // We use these fences to make sure the above Command buffers have finished their work
- // before attempting to reuse them or destroy them.
- VkFence mUsageFences[2];
- };
-
- struct ImageInfo {
- VkImageLayout mImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- sk_sp<SkSurface> mSurface;
- uint16_t mLastUsed = 0;
- bool mInvalid = true;
- };
-
- sk_sp<SkSurface> mBackbuffer;
-
- VkSurfaceKHR mVkSurface = VK_NULL_HANDLE;
- VkSwapchainKHR mSwapchain = VK_NULL_HANDLE;
-
- BackbufferInfo* mBackbuffers = nullptr;
- uint32_t mCurrentBackbufferIndex;
-
- uint32_t mImageCount;
- VkImage* mImages = nullptr;
- ImageInfo* mImageInfos;
- uint16_t mCurrentTime = 0;
- ColorMode mColorMode;
- ANativeWindow* mNativeWindow;
- int mWindowWidth = 0;
- int mWindowHeight = 0;
- sk_sp<SkColorSpace> mColorSpace;
- SkColorType mColorType;
- VkSurfaceTransformFlagBitsKHR mTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- SkMatrix mPreTransform;
- GrContext* mGrContext;
-};
-
// This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
// which are re-used by CanvasContext. This class is created once and should be used by all vulkan
// windowing contexts. The VulkanManager must be initialized before use.
@@ -114,33 +56,19 @@
// Quick check to see if the VulkanManager has been initialized.
bool hasVkContext() { return mDevice != VK_NULL_HANDLE; }
- // Given a window this creates a new VkSurfaceKHR and VkSwapchain and stores them inside a new
- // VulkanSurface object which is returned.
+ // Create and destroy functions for wrapping an ANativeWindow in a VulkanSurface
VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
SkColorType surfaceColorType,
GrContext* grContext);
-
- // Destroy the VulkanSurface and all associated vulkan objects.
void destroySurface(VulkanSurface* surface);
+ Frame dequeueNextBuffer(VulkanSurface* surface);
+ void swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect);
+
// Cleans up all the global state in the VulkanManger.
void destroy();
- // No work is needed to make a VulkanSurface current, and all functions require that a
- // VulkanSurface is passed into them so we just return true here.
- bool isCurrent(VulkanSurface* surface) { return true; }
-
- int getAge(VulkanSurface* surface);
-
- // Returns an SkSurface which wraps the next image returned from vkAcquireNextImageKHR. It also
- // will transition the VkImage from a present layout to color attachment so that it can be used
- // by the client for drawing.
- SkSurface* getBackbufferSurface(VulkanSurface** surface);
-
- // Presents the current VkImage.
- void swapBuffers(VulkanSurface* surface);
-
// Inserts a wait on fence command into the Vulkan command buffer.
status_t fenceWait(sp<Fence>& fence);
@@ -148,22 +76,17 @@
status_t createReleaseFence(sp<Fence>& nativeFence);
// Returned pointers are owned by VulkanManager.
+ // An instance of VkFunctorInitParams returned from getVkFunctorInitParams refers to
+ // the internal state of VulkanManager: VulkanManager must be alive to use the returned value.
VkFunctorInitParams getVkFunctorInitParams() const;
sk_sp<GrContext> createContext(const GrContextOptions& options);
private:
+ friend class VulkanSurface;
// Sets up the VkInstance and VkDevice objects. Also fills out the passed in
// VkPhysicalDeviceFeatures struct.
void setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&);
-
- void destroyBuffers(VulkanSurface* surface);
-
- bool createSwapchain(VulkanSurface* surface);
- void createBuffers(VulkanSurface* surface, VkFormat format, VkExtent2D extent);
-
- VulkanSurface::BackbufferInfo* getAvailableBackbuffer(VulkanSurface* surface);
-
bool setupDummyCommandBuffer();
// simple wrapper class that exists only to initialize a pointer to NULL
@@ -190,13 +113,6 @@
VkPtr<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR> mGetPhysicalDeviceSurfaceFormatsKHR;
VkPtr<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR> mGetPhysicalDeviceSurfacePresentModesKHR;
- VkPtr<PFN_vkCreateSwapchainKHR> mCreateSwapchainKHR;
- VkPtr<PFN_vkDestroySwapchainKHR> mDestroySwapchainKHR;
- VkPtr<PFN_vkGetSwapchainImagesKHR> mGetSwapchainImagesKHR;
- VkPtr<PFN_vkAcquireNextImageKHR> mAcquireNextImageKHR;
- VkPtr<PFN_vkQueuePresentKHR> mQueuePresentKHR;
- VkPtr<PFN_vkCreateSharedSwapchainsKHR> mCreateSharedSwapchainsKHR;
-
// Instance Functions
VkPtr<PFN_vkEnumerateInstanceVersion> mEnumerateInstanceVersion;
VkPtr<PFN_vkEnumerateInstanceExtensionProperties> mEnumerateInstanceExtensionProperties;
@@ -207,6 +123,7 @@
VkPtr<PFN_vkGetPhysicalDeviceProperties> mGetPhysicalDeviceProperties;
VkPtr<PFN_vkGetPhysicalDeviceQueueFamilyProperties> mGetPhysicalDeviceQueueFamilyProperties;
VkPtr<PFN_vkGetPhysicalDeviceFeatures2> mGetPhysicalDeviceFeatures2;
+ VkPtr<PFN_vkGetPhysicalDeviceImageFormatProperties2> mGetPhysicalDeviceImageFormatProperties2;
VkPtr<PFN_vkCreateDevice> mCreateDevice;
VkPtr<PFN_vkEnumerateDeviceExtensionProperties> mEnumerateDeviceExtensionProperties;
@@ -249,7 +166,9 @@
// Variables saved to populate VkFunctorInitParams.
static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0);
+ std::vector<VkExtensionProperties> mInstanceExtensionsOwner;
std::vector<const char*> mInstanceExtensions;
+ std::vector<VkExtensionProperties> mDeviceExtensionsOwner;
std::vector<const char*> mDeviceExtensions;
VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{};
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
new file mode 100644
index 0000000..c03c3a8
--- /dev/null
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VulkanSurface.h"
+
+#include <algorithm>
+#include <SkSurface.h>
+
+#include "VulkanManager.h"
+#include "utils/TraceUtils.h"
+#include "utils/Color.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+static bool IsTransformSupported(int transform) {
+ // For now, only support pure rotations, not flip or flip-and-rotate, until we have
+ // more time to test them and build sample code. As far as I know we never actually
+ // use anything besides pure rotations anyway.
+ return transform == 0
+ || transform == NATIVE_WINDOW_TRANSFORM_ROT_90
+ || transform == NATIVE_WINDOW_TRANSFORM_ROT_180
+ || transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
+}
+
+static int InvertTransform(int transform) {
+ switch (transform) {
+ case NATIVE_WINDOW_TRANSFORM_ROT_90:
+ return NATIVE_WINDOW_TRANSFORM_ROT_270;
+ case NATIVE_WINDOW_TRANSFORM_ROT_180:
+ return NATIVE_WINDOW_TRANSFORM_ROT_180;
+ case NATIVE_WINDOW_TRANSFORM_ROT_270:
+ return NATIVE_WINDOW_TRANSFORM_ROT_90;
+ default:
+ return 0;
+ }
+}
+
+static int ConvertVkTransformToNative(VkSurfaceTransformFlagsKHR transform) {
+ switch (transform) {
+ case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_270;
+ case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_180;
+ case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_90;
+ case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+ case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+ default:
+ return 0;
+ }
+}
+
+static SkMatrix GetPreTransformMatrix(SkISize windowSize, int transform) {
+ const int width = windowSize.width();
+ const int height = windowSize.height();
+
+ switch (transform) {
+ case 0:
+ return SkMatrix::I();
+ case NATIVE_WINDOW_TRANSFORM_ROT_90:
+ return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
+ case NATIVE_WINDOW_TRANSFORM_ROT_180:
+ return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
+ case NATIVE_WINDOW_TRANSFORM_ROT_270:
+ return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
+ default:
+ LOG_ALWAYS_FATAL("Unsupported Window Transform (%d)", transform);
+ }
+ return SkMatrix::I();
+}
+
+void VulkanSurface::ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
+ const SkISize& maxSize) {
+ SkISize& windowSize = windowInfo->size;
+
+ // clamp width & height to handle currentExtent of -1 and protect us from broken hints
+ if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width()
+ || windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
+ int width = std::min(maxSize.width(), std::max(minSize.width(), windowSize.width()));
+ int height = std::min(maxSize.height(), std::max(minSize.height(), windowSize.height()));
+ ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]",
+ windowSize.width(), windowSize.height(), width, height);
+ windowSize.set(width, height);
+ }
+
+ windowInfo->actualSize = windowSize;
+ if (windowInfo->transform & HAL_TRANSFORM_ROT_90) {
+ windowInfo->actualSize.set(windowSize.height(), windowSize.width());
+ }
+
+ windowInfo->preTransform = GetPreTransformMatrix(windowInfo->size, windowInfo->transform);
+}
+
+static bool ResetNativeWindow(ANativeWindow* window) {
+ // -- Reset the native window --
+ // The native window might have been used previously, and had its properties
+ // changed from defaults. That will affect the answer we get for queries
+ // like MIN_UNDEQUEUED_BUFFERS. Reset to a known/default state before we
+ // attempt such queries.
+
+ int err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+ if (err != 0) {
+ ALOGW("native_window_api_connect failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ // this will match what we do on GL so pick that here.
+ err = window->setSwapInterval(window, 1);
+ if (err != 0) {
+ ALOGW("native_window->setSwapInterval(1) failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ err = native_window_set_shared_buffer_mode(window, false);
+ if (err != 0) {
+ ALOGW("native_window_set_shared_buffer_mode(false) failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ err = native_window_set_auto_refresh(window, false);
+ if (err != 0) {
+ ALOGW("native_window_set_auto_refresh(false) failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ return true;
+}
+
+class VkSurfaceAutoDeleter {
+public:
+ VkSurfaceAutoDeleter(VkInstance instance, VkSurfaceKHR surface,
+ PFN_vkDestroySurfaceKHR destroySurfaceKHR)
+ : mInstance(instance)
+ , mSurface(surface)
+ , mDestroySurfaceKHR(destroySurfaceKHR) {}
+ ~VkSurfaceAutoDeleter() {
+ destroy();
+ }
+
+ void destroy() {
+ if (mSurface != VK_NULL_HANDLE) {
+ mDestroySurfaceKHR(mInstance, mSurface, nullptr);
+ mSurface = VK_NULL_HANDLE;
+ }
+ }
+
+private:
+ VkInstance mInstance;
+ VkSurfaceKHR mSurface;
+ PFN_vkDestroySurfaceKHR mDestroySurfaceKHR;
+};
+
+VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
+ SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
+ GrContext* grContext, const VulkanManager& vkManager) {
+
+ VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
+ memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+ surfaceCreateInfo.pNext = nullptr;
+ surfaceCreateInfo.flags = 0;
+ surfaceCreateInfo.window = window;
+
+ VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+ VkResult res = vkManager.mCreateAndroidSurfaceKHR(vkManager.mInstance, &surfaceCreateInfo,
+ nullptr, &vkSurface);
+ if (VK_SUCCESS != res) {
+ ALOGE("VulkanSurface::Create() vkCreateAndroidSurfaceKHR failed (%d)", res);
+ return nullptr;
+ }
+
+ VkSurfaceAutoDeleter vkSurfaceDeleter(vkManager.mInstance, vkSurface,
+ vkManager.mDestroySurfaceKHR);
+
+ SkDEBUGCODE(VkBool32 supported; res = vkManager.mGetPhysicalDeviceSurfaceSupportKHR(
+ vkManager.mPhysicalDevice, vkManager.mPresentQueueIndex, vkSurface, &supported);
+ // All physical devices and queue families on Android must be capable of
+ // presentation with any native window.
+ SkASSERT(VK_SUCCESS == res && supported););
+
+ // check for capabilities
+ VkSurfaceCapabilitiesKHR caps;
+ res = vkManager.mGetPhysicalDeviceSurfaceCapabilitiesKHR(vkManager.mPhysicalDevice, vkSurface,
+ &caps);
+ if (VK_SUCCESS != res) {
+ ALOGE("VulkanSurface::Create() vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed (%d)", res);
+ return nullptr;
+ }
+
+ LOG_ALWAYS_FATAL_IF(0 == (caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR));
+
+ /*
+ * We must destroy the VK Surface before attempting to update the window as doing so after
+ * will cause the native window to be modified in unexpected ways.
+ */
+ vkSurfaceDeleter.destroy();
+
+ /*
+ * Populate Window Info struct
+ */
+ WindowInfo windowInfo;
+
+ windowInfo.transform = ConvertVkTransformToNative(caps.supportedTransforms);
+ windowInfo.size = SkISize::Make(caps.currentExtent.width, caps.currentExtent.height);
+
+ const SkISize minSize = SkISize::Make(caps.minImageExtent.width, caps.minImageExtent.height);
+ const SkISize maxSize = SkISize::Make(caps.maxImageExtent.width, caps.maxImageExtent.height);
+ ComputeWindowSizeAndTransform(&windowInfo, minSize, maxSize);
+
+ windowInfo.bufferCount = std::max<uint32_t>(VulkanSurface::sMaxBufferCount, caps.minImageCount);
+ if (caps.maxImageCount > 0 && windowInfo.bufferCount > caps.maxImageCount) {
+ // Application must settle for fewer images than desired:
+ windowInfo.bufferCount = caps.maxImageCount;
+ }
+
+ // Currently Skia requires the images to be color attachments and support all transfer
+ // operations.
+ VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ LOG_ALWAYS_FATAL_IF((caps.supportedUsageFlags & usageFlags) != usageFlags);
+
+ windowInfo.dataspace = HAL_DATASPACE_V0_SRGB;
+ if (colorMode == ColorMode::WideColorGamut) {
+ skcms_Matrix3x3 surfaceGamut;
+ LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&surfaceGamut),
+ "Could not get gamut matrix from color space");
+ if (memcmp(&surfaceGamut, &SkNamedGamut::kSRGB, sizeof(surfaceGamut)) == 0) {
+ windowInfo.dataspace = HAL_DATASPACE_V0_SCRGB;
+ } else if (memcmp(&surfaceGamut, &SkNamedGamut::kDCIP3, sizeof(surfaceGamut)) == 0) {
+ windowInfo.dataspace = HAL_DATASPACE_DISPLAY_P3;
+ } else {
+ LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
+ }
+ }
+
+ windowInfo.pixelFormat = ColorTypeToPixelFormat(colorType);
+ VkFormat vkPixelFormat = VK_FORMAT_R8G8B8A8_UNORM;
+ if (windowInfo.pixelFormat == PIXEL_FORMAT_RGBA_FP16) {
+ vkPixelFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
+ }
+
+ uint64_t producerUsage =
+ AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+ uint64_t consumerUsage;
+ native_window_get_consumer_usage(window, &consumerUsage);
+ windowInfo.windowUsageFlags = consumerUsage | producerUsage;
+
+ /*
+ * Now we attempt to modify the window!
+ */
+ if (!UpdateWindow(window, windowInfo)) {
+ return nullptr;
+ }
+
+ return new VulkanSurface(window, windowInfo, minSize, maxSize, grContext);
+}
+
+bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo) {
+ ATRACE_CALL();
+
+ if (!ResetNativeWindow(window)) {
+ return false;
+ }
+
+ // -- Configure the native window --
+ int err = native_window_set_buffers_format(window, windowInfo.pixelFormat);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_format(%d) failed: %s (%d)",
+ windowInfo.pixelFormat, strerror(-err), err);
+ return false;
+ }
+
+ err = native_window_set_buffers_data_space(window, windowInfo.dataspace);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_data_space(%d) "
+ "failed: %s (%d)", windowInfo.dataspace, strerror(-err), err);
+ return false;
+ }
+
+ const SkISize& size = windowInfo.actualSize;
+ err = native_window_set_buffers_dimensions(window, size.width(), size.height());
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_dimensions(%d,%d) "
+ "failed: %s (%d)", size.width(), size.height(), strerror(-err), err);
+ return false;
+ }
+
+ // native_window_set_buffers_transform() expects the transform the app is requesting that
+ // the compositor perform during composition. With native windows, pre-transform works by
+ // rendering with the same transform the compositor is applying (as in Vulkan), but
+ // then requesting the inverse transform, so that when the compositor does
+ // it's job the two transforms cancel each other out and the compositor ends
+ // up applying an identity transform to the app's buffer.
+ err = native_window_set_buffers_transform(window, InvertTransform(windowInfo.transform));
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_transform(%d) "
+ "failed: %s (%d)", windowInfo.transform, strerror(-err), err);
+ return false;
+ }
+
+ // Vulkan defaults to NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, but this is different than
+ // HWUI's expectation
+ err = native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_FREEZE);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_scaling_mode(SCALE_TO_WINDOW) "
+ "failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ // Lower layer insists that we have at least two buffers.
+ err = native_window_set_buffer_count(window, std::max(2, windowInfo.bufferCount));
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%d) failed: %s (%d)",
+ windowInfo.bufferCount, strerror(-err), err);
+ return false;
+ }
+
+ err = native_window_set_usage(window, windowInfo.windowUsageFlags);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_usage failed: %s (%d)",
+ strerror(-err), err);
+ return false;
+ }
+
+ return err == 0;
+}
+
+VulkanSurface::VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo,
+ SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
+ : mNativeWindow(window)
+ , mWindowInfo(windowInfo)
+ , mGrContext(grContext)
+ , mMinWindowSize(minWindowSize)
+ , mMaxWindowSize(maxWindowSize) { }
+
+VulkanSurface::~VulkanSurface() {
+ releaseBuffers();
+
+ // release the native window to be available for use by other clients
+ int err = native_window_api_disconnect(mNativeWindow.get(), NATIVE_WINDOW_API_EGL);
+ ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)", strerror(-err), err);
+}
+
+void VulkanSurface::releaseBuffers() {
+ for (uint32_t i = 0; i < VulkanSurface::sMaxBufferCount; i++) {
+ VulkanSurface::NativeBufferInfo& bufferInfo = mNativeBuffers[i];
+
+ if (bufferInfo.buffer.get() != nullptr && bufferInfo.dequeued) {
+ int err = mNativeWindow->cancelBuffer(mNativeWindow.get(), bufferInfo.buffer.get(),
+ bufferInfo.dequeue_fence);
+ if (err != 0) {
+ ALOGE("cancelBuffer[%u] failed during destroy: %s (%d)", i, strerror(-err), err);
+ }
+ bufferInfo.dequeued = false;
+
+ if (bufferInfo.dequeue_fence >= 0) {
+ close(bufferInfo.dequeue_fence);
+ bufferInfo.dequeue_fence = -1;
+ }
+ }
+
+ LOG_ALWAYS_FATAL_IF(bufferInfo.dequeued);
+ LOG_ALWAYS_FATAL_IF(bufferInfo.dequeue_fence != -1);
+
+ bufferInfo.skSurface.reset();
+ bufferInfo.buffer.clear();
+ bufferInfo.hasValidContents = false;
+ bufferInfo.lastPresentedCount = 0;
+ }
+}
+
+VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
+ // Set the dequeue index to invalid in case of error and only reset it to the correct
+ // value at the end of the function if everything dequeued correctly.
+ mDequeuedIndex = -1;
+
+ //check if the native window has been resized or rotated and update accordingly
+ SkISize newSize = SkISize::MakeEmpty();
+ int transformHint = 0;
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &newSize.fWidth);
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &newSize.fHeight);
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
+ if (newSize != mWindowInfo.actualSize || transformHint != mWindowInfo.transform) {
+ WindowInfo newWindowInfo = mWindowInfo;
+ newWindowInfo.size = newSize;
+ newWindowInfo.transform = IsTransformSupported(transformHint) ? transformHint : 0;
+ ComputeWindowSizeAndTransform(&newWindowInfo, mMinWindowSize, mMaxWindowSize);
+
+ int err = 0;
+ if (newWindowInfo.actualSize != mWindowInfo.actualSize) {
+ // reset the native buffers and update the window
+ err = native_window_set_buffers_dimensions(mNativeWindow.get(),
+ newWindowInfo.actualSize.width(),
+ newWindowInfo.actualSize.height());
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
+ newWindowInfo.actualSize.width(),
+ newWindowInfo.actualSize.height(), strerror(-err), err);
+ return nullptr;
+ }
+ // reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
+ // new NativeBufferInfo storage will be populated lazily as we dequeue each new buffer.
+ releaseBuffers();
+ // TODO should we ask the nativewindow to allocate buffers?
+ }
+
+ if (newWindowInfo.transform != mWindowInfo.transform) {
+ err = native_window_set_buffers_transform(mNativeWindow.get(),
+ InvertTransform(newWindowInfo.transform));
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
+ newWindowInfo.transform, strerror(-err), err);
+ newWindowInfo.transform = mWindowInfo.transform;
+ ComputeWindowSizeAndTransform(&newWindowInfo, mMinWindowSize, mMaxWindowSize);
+ }
+ }
+
+ mWindowInfo = newWindowInfo;
+ }
+
+ ANativeWindowBuffer* buffer;
+ int fence_fd;
+ int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fence_fd);
+ if (err != 0) {
+ ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
+ return nullptr;
+ }
+
+ uint32_t idx;
+ for (idx = 0; idx < mWindowInfo.bufferCount; idx++) {
+ if (mNativeBuffers[idx].buffer.get() == buffer) {
+ mNativeBuffers[idx].dequeued = true;
+ mNativeBuffers[idx].dequeue_fence = fence_fd;
+ break;
+ } else if (mNativeBuffers[idx].buffer.get() == nullptr) {
+ // increasing the number of buffers we have allocated
+ mNativeBuffers[idx].buffer = buffer;
+ mNativeBuffers[idx].dequeued = true;
+ mNativeBuffers[idx].dequeue_fence = fence_fd;
+ break;
+ }
+ }
+ if (idx == mWindowInfo.bufferCount) {
+ ALOGE("dequeueBuffer returned unrecognized buffer");
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+ return nullptr;
+ }
+
+ VulkanSurface::NativeBufferInfo* bufferInfo = &mNativeBuffers[idx];
+
+ if (bufferInfo->skSurface.get() == nullptr) {
+ bufferInfo->skSurface =
+ SkSurface::MakeFromAHardwareBuffer(mGrContext,
+ ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
+ kTopLeft_GrSurfaceOrigin, DataSpaceToColorSpace(mWindowInfo.dataspace),
+ nullptr);
+ if (bufferInfo->skSurface.get() == nullptr) {
+ ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+ return nullptr;
+ }
+ }
+
+ mDequeuedIndex = idx;
+ return bufferInfo;
+}
+
+bool VulkanSurface::presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd) {
+ if (!dirtyRect.isEmpty()) {
+ SkRect transformedRect;
+ mWindowInfo.preTransform.mapRect(&transformedRect, dirtyRect);
+
+ SkIRect transformedIRect;
+ transformedRect.roundOut(&transformedIRect);
+ transformedIRect.intersect(0, 0, mWindowInfo.size.fWidth, mWindowInfo.size.fHeight);
+
+ // map to bottom-left coordinate system
+ android_native_rect_t aRect;
+ aRect.left = transformedIRect.x();
+ aRect.top = mWindowInfo.size.fHeight - (transformedIRect.y() + transformedIRect.height());
+ aRect.right = aRect.left + transformedIRect.width();
+ aRect.bottom = aRect.top - transformedIRect.height();
+
+ int err = native_window_set_surface_damage(mNativeWindow.get(), &aRect, 1);
+ ALOGE_IF(err != 0, "native_window_set_surface_damage failed: %s (%d)", strerror(-err), err);
+ }
+
+ VulkanSurface::NativeBufferInfo& currentBuffer = mNativeBuffers[mDequeuedIndex];
+ int queuedFd = (semaphoreFd != -1) ? semaphoreFd : currentBuffer.dequeue_fence;
+ int err = mNativeWindow->queueBuffer(mNativeWindow.get(), currentBuffer.buffer.get(), queuedFd);
+
+ currentBuffer.dequeued = false;
+ // queueBuffer always closes fence, even on error
+ if (err != 0) {
+ ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), currentBuffer.buffer.get(),
+ currentBuffer.dequeue_fence);
+ } else {
+ currentBuffer.hasValidContents = true;
+ currentBuffer.lastPresentedCount = mPresentCount;
+ mPresentCount++;
+ }
+
+ if (currentBuffer.dequeue_fence >= 0) {
+ close(currentBuffer.dequeue_fence);
+ currentBuffer.dequeue_fence = -1;
+ }
+
+ return err == 0;
+}
+
+int VulkanSurface::getCurrentBuffersAge() {
+ VulkanSurface::NativeBufferInfo& currentBuffer = mNativeBuffers[mDequeuedIndex];
+ return currentBuffer.hasValidContents ? (mPresentCount - currentBuffer.lastPresentedCount) : 0;
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
new file mode 100644
index 0000000..4fd9cd2
--- /dev/null
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#pragma once
+
+#include <system/graphics.h>
+#include <system/window.h>
+#include <vulkan/vulkan.h>
+
+#include <SkSize.h>
+#include <SkRefCnt.h>
+
+#include "IRenderPipeline.h"
+
+class SkSurface;
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class VulkanManager;
+
+class VulkanSurface {
+public:
+ static VulkanSurface* Create(ANativeWindow* window,
+ ColorMode colorMode,
+ SkColorType colorType,
+ sk_sp<SkColorSpace> colorSpace,
+ GrContext* grContext,
+ const VulkanManager& vkManager);
+ ~VulkanSurface();
+
+ sk_sp<SkSurface> getCurrentSkSurface() { return mNativeBuffers[mDequeuedIndex].skSurface; }
+ const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }
+
+private:
+ /*
+ * All structs/methods in this private section are specifically for use by the VulkanManager
+ *
+ */
+ friend VulkanManager;
+ struct NativeBufferInfo {
+ sk_sp<SkSurface> skSurface;
+ sp<ANativeWindowBuffer> buffer;
+ // The fence is only valid when the buffer is dequeued, and should be
+ // -1 any other time. When valid, we own the fd, and must ensure it is
+ // closed: either by closing it explicitly when queueing the buffer,
+ // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
+ int dequeue_fence = -1;
+ bool dequeued = false;
+ uint32_t lastPresentedCount = 0;
+ bool hasValidContents = false;
+ };
+
+ NativeBufferInfo* dequeueNativeBuffer();
+ NativeBufferInfo* getCurrentBufferInfo() { return &mNativeBuffers[mDequeuedIndex]; }
+ bool presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd);
+
+ // The width and height are are the logical width and height for when submitting draws to the
+ // surface. In reality if the window is rotated the underlying window may have the width and
+ // height swapped.
+ int logicalWidth() const { return mWindowInfo.size.width(); }
+ int logicalHeight() const { return mWindowInfo.size.height(); }
+ int getCurrentBuffersAge();
+
+private:
+ /*
+ * All code below this line while logically available to VulkanManager should not be treated
+ * as private to this class.
+ *
+ */
+ static constexpr int sMaxBufferCount = 3;
+
+ struct WindowInfo {
+ SkISize size;
+ PixelFormat pixelFormat;
+ android_dataspace dataspace;
+ int transform;
+ int bufferCount;
+ uint64_t windowUsageFlags;
+
+ // size of the ANativeWindow if the inverse of transform requires us to swap width/height
+ SkISize actualSize;
+ // transform to be applied to the SkSurface to map the coordinates to the provided transform
+ SkMatrix preTransform;
+ };
+
+ VulkanSurface(ANativeWindow* window,
+ const WindowInfo& windowInfo,
+ SkISize minWindowSize,
+ SkISize maxWindowSize,
+ GrContext* grContext);
+ static bool UpdateWindow(ANativeWindow* window,
+ const WindowInfo& windowInfo);
+ static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo,
+ const SkISize& minSize,
+ const SkISize& maxSize);
+ void releaseBuffers();
+
+ NativeBufferInfo mNativeBuffers[VulkanSurface::sMaxBufferCount];
+
+ sp<ANativeWindow> mNativeWindow;
+ WindowInfo mWindowInfo;
+ GrContext* mGrContext;
+
+ int mDequeuedIndex = -1;
+ uint32_t mPresentCount = 0;
+
+ const SkISize mMinWindowSize;
+ const SkISize mMaxWindowSize;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
\ No newline at end of file
diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java
index f6b2031..5cd3621 100644
--- a/media/apex/java/android/media/MediaPlayer2.java
+++ b/media/apex/java/android/media/MediaPlayer2.java
@@ -1985,7 +1985,7 @@
* When the language is unknown or could not be determined,
* ISO-639-2 language code, "und", is returned.
*/
- public @Nullable String getLanguage() {
+ public @NonNull String getLanguage() {
String language = mFormat.getString(MediaFormat.KEY_LANGUAGE);
return language == null ? "und" : language;
}
diff --git a/media/apex/java/android/media/MediaSession2.java b/media/apex/java/android/media/MediaSession2.java
index 148e16c..09ac9ca 100644
--- a/media/apex/java/android/media/MediaSession2.java
+++ b/media/apex/java/android/media/MediaSession2.java
@@ -749,6 +749,10 @@
* You can reject the connection by returning {@code null}. In that case, controller
* receives {@link MediaController2.ControllerCallback#onDisconnected(MediaController2)}
* and cannot be used.
+ * <p>
+ * The controller hasn't connected yet in this method, so calls to the controller
+ * (e.g. {@link #sendSessionCommand}) would be ignored. Override {@link #onPostConnect} for
+ * the custom initialization for the controller instead.
*
* @param session the session for this event
* @param controller controller information.
@@ -763,6 +767,10 @@
/**
* Called immediately after a controller is connected. This is a convenient method to add
* custom initialization between the session and a controller.
+ * <p>
+ * Note that calls to the controller (e.g. {@link #sendSessionCommand}) work here but don't
+ * work in {@link #onConnect} because the controller hasn't connected yet in
+ * {@link #onConnect}.
*
* @param session the session for this event
* @param controller controller information.
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index bc91ca3..4cd8971 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -73,6 +73,12 @@
* Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF and HEIF.
* <p>
* Attribute mutation is supported for JPEG image files.
+ * <p>
+ * Note: It is recommended to use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
+ * <a href="{@docRoot}reference/androidx/exifinterface/media/ExifInterface.html">ExifInterface
+ * Library</a> since it is a superset of this class. In addition to the functionalities of this
+ * class, it supports parsing extra metadata such as exposure and data compression information
+ * as well as setting extra metadata such as GPS and datetime information.
*/
public class ExifInterface {
private static final String TAG = "ExifInterface";
@@ -1316,14 +1322,14 @@
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- private final String mFilename;
- private final FileDescriptor mSeekableFileDescriptor;
- private final AssetManager.AssetInputStream mAssetInputStream;
- private final boolean mIsInputStream;
+ private String mFilename;
+ private FileDescriptor mSeekableFileDescriptor;
+ private AssetManager.AssetInputStream mAssetInputStream;
+ private boolean mIsInputStream;
private int mMimeType;
@UnsupportedAppUsage
private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
- private Set<Integer> mAttributesOffsets = new HashSet<>(EXIF_TAGS.length);
+ private Set<Integer> mHandledIfdOffsets = new HashSet<>(EXIF_TAGS.length);
private ByteOrder mExifByteOrder = ByteOrder.BIG_ENDIAN;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private boolean mHasThumbnail;
@@ -1350,7 +1356,10 @@
* Reads Exif tags from the specified image file.
*/
public ExifInterface(@NonNull File file) throws IOException {
- this(file.getAbsolutePath());
+ if (file == null) {
+ throw new NullPointerException("file cannot be null");
+ }
+ initForFilename(file.getName());
}
/**
@@ -1358,23 +1367,9 @@
*/
public ExifInterface(@NonNull String filename) throws IOException {
if (filename == null) {
- throw new IllegalArgumentException("filename cannot be null");
+ throw new NullPointerException("filename cannot be null");
}
- FileInputStream in = null;
- mAssetInputStream = null;
- mFilename = filename;
- mIsInputStream = false;
- try {
- in = new FileInputStream(filename);
- if (isSeekableFD(in.getFD())) {
- mSeekableFileDescriptor = in.getFD();
- } else {
- mSeekableFileDescriptor = null;
- }
- loadAttributes(in);
- } finally {
- IoUtils.closeQuietly(in);
- }
+ initForFilename(filename);
}
/**
@@ -1384,7 +1379,7 @@
*/
public ExifInterface(@NonNull FileDescriptor fileDescriptor) throws IOException {
if (fileDescriptor == null) {
- throw new IllegalArgumentException("fileDescriptor cannot be null");
+ throw new NullPointerException("fileDescriptor cannot be null");
}
mAssetInputStream = null;
mFilename = null;
@@ -1418,7 +1413,7 @@
*/
public ExifInterface(@NonNull InputStream inputStream) throws IOException {
if (inputStream == null) {
- throw new IllegalArgumentException("inputStream cannot be null");
+ throw new NullPointerException("inputStream cannot be null");
}
mFilename = null;
if (inputStream instanceof AssetManager.AssetInputStream) {
@@ -1443,6 +1438,9 @@
* @param tag the name of the tag.
*/
private @Nullable ExifAttribute getExifAttribute(@NonNull String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
// Retrieves all tag groups. The value from primary image tag group has a higher priority
// than the value from the thumbnail tag group if there are more than one candidates.
for (int i = 0; i < EXIF_TAGS.length; ++i) {
@@ -1461,6 +1459,9 @@
* @param tag the name of the tag.
*/
public @Nullable String getAttribute(@NonNull String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
ExifAttribute attribute = getExifAttribute(tag);
if (attribute != null) {
if (!sTagSetForCompatibility.contains(tag)) {
@@ -1499,6 +1500,9 @@
* @param defaultValue the value to return if the tag is not available.
*/
public int getAttributeInt(@NonNull String tag, int defaultValue) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
ExifAttribute exifAttribute = getExifAttribute(tag);
if (exifAttribute == null) {
return defaultValue;
@@ -1520,6 +1524,9 @@
* @param defaultValue the value to return if the tag is not available.
*/
public double getAttributeDouble(@NonNull String tag, double defaultValue) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
ExifAttribute exifAttribute = getExifAttribute(tag);
if (exifAttribute == null) {
return defaultValue;
@@ -1539,6 +1546,9 @@
* @param value the value of the tag.
*/
public void setAttribute(@NonNull String tag, @Nullable String value) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
// Convert the given value to rational values for backwards compatibility.
if (value != null && sTagSetForCompatibility.contains(tag)) {
if (tag.equals(TAG_GPS_TIMESTAMP)) {
@@ -1708,6 +1718,9 @@
* determine whether the image data format is JPEG or not.
*/
private void loadAttributes(@NonNull InputStream in) throws IOException {
+ if (in == null) {
+ throw new NullPointerException("inputstream shouldn't be null");
+ }
try {
// Initialize mAttributes.
for (int i = 0; i < EXIF_TAGS.length; ++i) {
@@ -2043,6 +2056,9 @@
* that means offsets may have changed.
*/
public @Nullable long[] getAttributeRange(@NonNull String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
if (mModified) {
throw new IllegalStateException(
"The underlying file has been modified since being parsed");
@@ -2064,6 +2080,9 @@
* no tag was found.
*/
public @Nullable byte[] getAttributeBytes(@NonNull String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
final ExifAttribute attribute = getExifAttribute(tag);
if (attribute != null) {
return attribute.bytes;
@@ -2234,6 +2253,24 @@
}
}
+ private void initForFilename(String filename) throws IOException {
+ FileInputStream in = null;
+ mAssetInputStream = null;
+ mFilename = filename;
+ mIsInputStream = false;
+ try {
+ in = new FileInputStream(filename);
+ if (isSeekableFD(in.getFD())) {
+ mSeekableFileDescriptor = in.getFD();
+ } else {
+ mSeekableFileDescriptor = null;
+ }
+ loadAttributes(in);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
// Checks the type of image file
private int getMimeType(BufferedInputStream in) throws IOException {
in.mark(SIGNATURE_CHECK_SIZE);
@@ -3085,6 +3122,9 @@
// Reads image file directory, which is a tag group in EXIF.
private void readImageFileDirectory(ByteOrderedDataInputStream dataInputStream,
@IfdType int ifdType) throws IOException {
+ // Save offset of current IFD to prevent reading an IFD that is already read.
+ mHandledIfdOffsets.add(dataInputStream.mPosition);
+
if (dataInputStream.mPosition + 2 > dataInputStream.mLength) {
// Return if there is no data from the offset.
return;
@@ -3223,9 +3263,7 @@
// 1. Exists within the boundaries of the input stream
// 2. Does not point to a previously read IFD.
if (offset > 0L && offset < dataInputStream.mLength) {
- if (!mAttributesOffsets.contains((int) offset)) {
- // Save offset of current IFD to prevent reading an IFD that is already read
- mAttributesOffsets.add(dataInputStream.mPosition);
+ if (!mHandledIfdOffsets.contains((int) offset)) {
dataInputStream.seek(offset);
readImageFileDirectory(dataInputStream, nextIfdType);
} else {
@@ -3279,9 +3317,7 @@
// 1. Exists within the boundaries of the input stream
// 2. Does not point to a previously read IFD.
if (nextIfdOffset > 0L && nextIfdOffset < dataInputStream.mLength) {
- if (!mAttributesOffsets.contains(nextIfdOffset)) {
- // Save offset of current IFD to prevent reading an IFD that is already read.
- mAttributesOffsets.add(dataInputStream.mPosition);
+ if (!mHandledIfdOffsets.contains(nextIfdOffset)) {
dataInputStream.seek(nextIfdOffset);
// Do not overwrite thumbnail IFD data if it alreay exists.
if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index b302b06..50caf733 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -52,6 +52,10 @@
// parameters of the player that affect AppOps
protected AudioAttributes mAttributes;
+
+ // volumes of the subclass "player volumes", as seen by the client of the subclass
+ // (e.g. what was passed in AudioTrack.setVolume(float)). The actual volume applied is
+ // the combination of the player volume, and the PlayerBase pan and volume multipliers
protected float mLeftVolume = 1.0f;
protected float mRightVolume = 1.0f;
protected float mAuxEffectSendLevel = 0.0f;
@@ -79,6 +83,8 @@
private float mPanMultiplierL = 1.0f;
@GuardedBy("mLock")
private float mPanMultiplierR = 1.0f;
+ @GuardedBy("mLock")
+ private float mVolMultiplier = 1.0f;
/**
* Constructor. Must be given audio attributes, as they are required for AppOps.
@@ -199,18 +205,33 @@
mPanMultiplierR = 1.0f + p;
}
}
- baseSetVolume(mLeftVolume, mRightVolume);
+ updatePlayerVolume();
+ }
+
+ private void updatePlayerVolume() {
+ final float finalLeftVol, finalRightVol;
+ final boolean isRestricted;
+ synchronized (mLock) {
+ finalLeftVol = mVolMultiplier * mLeftVolume * mPanMultiplierL;
+ finalRightVol = mVolMultiplier * mRightVolume * mPanMultiplierR;
+ isRestricted = isRestricted_sync();
+ }
+ playerSetVolume(isRestricted /*muting*/, finalLeftVol, finalRightVol);
+ }
+
+ void setVolumeMultiplier(float vol) {
+ synchronized (mLock) {
+ this.mVolMultiplier = vol;
+ }
+ updatePlayerVolume();
}
void baseSetVolume(float leftVolume, float rightVolume) {
- final boolean isRestricted;
synchronized (mLock) {
mLeftVolume = leftVolume;
mRightVolume = rightVolume;
- isRestricted = isRestricted_sync();
}
- playerSetVolume(isRestricted/*muting*/,
- leftVolume * mPanMultiplierL, rightVolume * mPanMultiplierR);
+ updatePlayerVolume();
}
int baseSetAuxEffectSendLevel(float level) {
@@ -466,7 +487,7 @@
public void setVolume(float vol) {
final PlayerBase pb = mWeakPB.get();
if (pb != null) {
- pb.baseSetVolume(vol, vol);
+ pb.setVolumeMultiplier(vol);
}
}
diff --git a/native/android/OWNERS b/native/android/OWNERS
index b3f50aa..266764a 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,4 +1,4 @@
set noparent
-per-file libandroid_net.map.txt, net.c = codewiz@google.com, ek@google.com, jchalard@google.com
+per-file libandroid_net.map.txt, net.c = codewiz@google.com, jchalard@google.com, junyulai@google.com
per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
diff --git a/native/android/choreographer.cpp b/native/android/choreographer.cpp
index 3fecd53..63e0734 100644
--- a/native/android/choreographer.cpp
+++ b/native/android/choreographer.cpp
@@ -37,6 +37,7 @@
struct FrameCallback {
AChoreographer_frameCallback callback;
+ AChoreographer_frameCallback64 callback64;
void* data;
nsecs_t dueTime;
@@ -50,8 +51,8 @@
class Choreographer : public DisplayEventDispatcher, public MessageHandler {
public:
- void postFrameCallback(AChoreographer_frameCallback cb, void* data);
- void postFrameCallbackDelayed(AChoreographer_frameCallback cb, void* data, nsecs_t delay);
+ void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
+ AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay);
enum {
MSG_SCHEDULE_CALLBACKS = 0,
@@ -107,14 +108,10 @@
DisplayEventDispatcher(looper), mLooper(looper), mThreadId(std::this_thread::get_id()) {
}
-void Choreographer::postFrameCallback(AChoreographer_frameCallback cb, void* data) {
- postFrameCallbackDelayed(cb, data, 0);
-}
-
void Choreographer::postFrameCallbackDelayed(
- AChoreographer_frameCallback cb, void* data, nsecs_t delay) {
+ AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- FrameCallback callback{cb, data, now + delay};
+ FrameCallback callback{cb, cb64, data, now + delay};
{
AutoMutex _l{mLock};
mCallbacks.push(callback);
@@ -156,7 +153,11 @@
}
}
for (const auto& cb : callbacks) {
- cb.callback(timestamp, cb.data);
+ if (cb.callback64 != nullptr) {
+ cb.callback64(timestamp, cb.data);
+ } else if (cb.callback != nullptr) {
+ cb.callback(timestamp, cb.data);
+ }
}
}
@@ -204,10 +205,21 @@
void AChoreographer_postFrameCallback(AChoreographer* choreographer,
AChoreographer_frameCallback callback, void* data) {
- AChoreographer_to_Choreographer(choreographer)->postFrameCallback(callback, data);
+ AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed(
+ callback, nullptr, data, 0);
}
void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
AChoreographer_frameCallback callback, void* data, long delayMillis) {
AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed(
- callback, data, ms2ns(delayMillis));
+ callback, nullptr, data, ms2ns(delayMillis));
+}
+void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
+ AChoreographer_frameCallback64 callback, void* data) {
+ AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed(
+ nullptr, callback, data, 0);
+}
+void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
+ AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) {
+ AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed(
+ nullptr, callback, data, ms2ns(delayMillis));
}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index a3db2d6..e1dc406 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -21,6 +21,8 @@
AChoreographer_getInstance; # introduced=24
AChoreographer_postFrameCallback; # introduced=24
AChoreographer_postFrameCallbackDelayed; # introduced=24
+ AChoreographer_postFrameCallback64; # introduced=29
+ AChoreographer_postFrameCallbackDelayed64; # introduced=29
AConfiguration_copy;
AConfiguration_delete;
AConfiguration_diff;
diff --git a/packages/CaptivePortalLogin/OWNERS b/packages/CaptivePortalLogin/OWNERS
index 7311eee..d3836d4 100644
--- a/packages/CaptivePortalLogin/OWNERS
+++ b/packages/CaptivePortalLogin/OWNERS
@@ -1,8 +1,8 @@
set noparent
codewiz@google.com
-ek@google.com
jchalard@google.com
+junyulai@google.com
lorenzo@google.com
reminv@google.com
satk@google.com
diff --git a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
index ba361c4..46288bb 100644
--- a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
+++ b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
@@ -22,7 +22,6 @@
import android.os.Handler;
import android.provider.DeviceConfig;
import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -128,17 +127,17 @@
}
private void updateFromDeviceConfigFlags() {
- mGenerateReplies = DeviceConfigHelper.getBoolean(
+ mGenerateReplies = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES, DEFAULT_GENERATE_REPLIES);
- mGenerateActions = DeviceConfigHelper.getBoolean(
+ mGenerateActions = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS, DEFAULT_GENERATE_ACTIONS);
- mMaxMessagesToExtract = DeviceConfigHelper.getInteger(
+ mMaxMessagesToExtract = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_MAX_MESSAGES_TO_EXTRACT,
DEFAULT_MAX_MESSAGES_TO_EXTRACT);
- mMaxSuggestions = DeviceConfigHelper.getInteger(
+ mMaxSuggestions = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS, DEFAULT_MAX_SUGGESTIONS);
mOnUpdateRunnable.run();
@@ -170,34 +169,6 @@
mOnUpdateRunnable.run();
}
- static class DeviceConfigHelper {
-
- static int getInteger(String key, int defaultValue) {
- String value = getValue(key);
- if (TextUtils.isEmpty(value)) {
- return defaultValue;
- }
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException ex) {
- return defaultValue;
- }
- }
-
- static boolean getBoolean(String key, boolean defaultValue) {
- String value = getValue(key);
- if (TextUtils.isEmpty(value)) {
- return defaultValue;
- }
- return Boolean.parseBoolean(value);
- }
-
- private static String getValue(String key) {
- return DeviceConfig.getProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI, key);
- }
- }
-
public interface Factory {
AssistantSettings createAndRegister(Handler handler, ContentResolver resolver, int userId,
Runnable onUpdateRunnable);
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
index 293b5b8..ad52e2b 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
@@ -120,7 +120,7 @@
}
@Test
- public void testGenerateRepliesEmptyFlag() {
+ public void testGenerateRepliesNullFlag() {
runWithShellPermissionIdentity(() -> setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
@@ -136,12 +136,12 @@
runWithShellPermissionIdentity(() -> setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
- "",
+ null,
false /* makeDefault */));
mAssistantSettings.onDeviceConfigPropertyChanged(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
- "");
+ null);
// Go back to the default value.
assertTrue(mAssistantSettings.mGenerateReplies);
@@ -178,7 +178,7 @@
}
@Test
- public void testGenerateActionsEmptyFlag() {
+ public void testGenerateActionsNullFlag() {
runWithShellPermissionIdentity(() -> setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
@@ -194,12 +194,12 @@
runWithShellPermissionIdentity(() -> setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
- "",
+ null,
false /* makeDefault */));
mAssistantSettings.onDeviceConfigPropertyChanged(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
- "");
+ null);
// Go back to the default value.
assertTrue(mAssistantSettings.mGenerateActions);
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index f210840..190247a 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -14,12 +14,11 @@
// limitations under the License.
//
-// Library including the network stack, used to compile the network stack app, or linked into the
-// system server on devices that run the stack there
-java_library {
- name: "NetworkStackLib",
+// Library including the network stack, used to compile both variants of the network stack
+android_library {
+ name: "NetworkStackBase",
sdk_version: "system_current",
- installable: true,
+ min_sdk_version: "28",
srcs: [
"src/**/*.java",
":framework-networkstack-shared-srcs",
@@ -29,7 +28,24 @@
"netd_aidl_interface-java",
"networkstack-aidl-interfaces-java",
"datastallprotosnano",
- ]
+ ],
+ manifest: "AndroidManifestBase.xml",
+}
+
+// Non-updatable in-process network stack for devices not using the module
+android_app {
+ name: "InProcessNetworkStack",
+ sdk_version: "system_current",
+ min_sdk_version: "28",
+ certificate: "platform",
+ privileged: true,
+ static_libs: [
+ "NetworkStackBase",
+ ],
+ jarjar_rules: "jarjar-rules-shared.txt",
+ // The permission configuration *must* be included to ensure security of the device
+ required: ["NetworkStackPermissionStub"],
+ manifest: "AndroidManifest_InProcess.xml",
}
// Updatable network stack packaged as an application
@@ -40,9 +56,10 @@
certificate: "networkstack",
privileged: true,
static_libs: [
- "NetworkStackLib"
+ "NetworkStackBase"
],
jarjar_rules: "jarjar-rules-shared.txt",
- manifest: "AndroidManifest.xml",
+ // The permission configuration *must* be included to ensure security of the device
required: ["NetworkStackPermissionStub"],
+ manifest: "AndroidManifest.xml",
}
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 003f1e5..a90db11 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -18,30 +18,14 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack"
- android:sharedUserId="android.uid.networkstack"
- android:versionCode="11"
- android:versionName="Q-initial">
- <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ android:sharedUserId="android.uid.networkstack">
<!-- Signature permission defined in NetworkStackStub -->
<uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
- <!-- Send latency broadcast as current user -->
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
- <uses-permission android:name="android.permission.WAKE_LOCK" />
- <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
- <application
- android:label="NetworkStack"
- android:defaultToDeviceProtectedStorage="true"
- android:directBootAware="true"
- android:usesCleartextTraffic="true">
+ <application>
<service android:name="com.android.server.NetworkStackService">
<intent-filter>
<action android:name="android.net.INetworkStackConnector"/>
</intent-filter>
</service>
</application>
-</manifest>
+</manifest>
\ No newline at end of file
diff --git a/packages/NetworkStack/AndroidManifestBase.xml b/packages/NetworkStack/AndroidManifestBase.xml
new file mode 100644
index 0000000..621d30c
--- /dev/null
+++ b/packages/NetworkStack/AndroidManifestBase.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2019 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.networkstack"
+ android:versionCode="11"
+ android:versionName="Q-initial">
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <!-- Send latency broadcast as current user -->
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+ <application
+ android:label="NetworkStack"
+ android:defaultToDeviceProtectedStorage="true"
+ android:directBootAware="true"
+ android:usesCleartextTraffic="true">
+ </application>
+</manifest>
diff --git a/packages/NetworkStack/AndroidManifest_InProcess.xml b/packages/NetworkStack/AndroidManifest_InProcess.xml
new file mode 100644
index 0000000..48fcecd
--- /dev/null
+++ b/packages/NetworkStack/AndroidManifest_InProcess.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2019 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.networkstack.inprocess"
+ android:sharedUserId="android.uid.system"
+ android:process="system">
+ <application>
+ <service android:name="com.android.server.NetworkStackService" android:process="system">
+ <intent-filter>
+ <action android:name="android.net.INetworkStackConnector.InProcess"/>
+ </intent-filter>
+ </service>
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/packages/NetworkStack/OWNERS b/packages/NetworkStack/OWNERS
index a395465..0e1e65d 100644
--- a/packages/NetworkStack/OWNERS
+++ b/packages/NetworkStack/OWNERS
@@ -1,5 +1,6 @@
codewiz@google.com
jchalard@google.com
+junyulai@google.com
lorenzo@google.com
reminv@google.com
satk@google.com
diff --git a/packages/NetworkStack/TEST_MAPPING b/packages/NetworkStack/TEST_MAPPING
index 55ba591..fe9731fe 100644
--- a/packages/NetworkStack/TEST_MAPPING
+++ b/packages/NetworkStack/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "postsubmit": [
+ "presubmit": [
{
"name": "NetworkStackTests"
}
diff --git a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
index 17a36ad..d1ca109 100644
--- a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
+++ b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.net.captiveportal.CaptivePortalProbeResult;
import android.util.Log;
+import android.util.StatsLog;
import com.android.internal.util.HexDump;
import com.android.server.connectivity.nano.DataStallEventProto;
@@ -36,6 +37,7 @@
*/
public class DataStallStatsUtils {
private static final String TAG = DataStallStatsUtils.class.getSimpleName();
+ private static final int DATA_STALL_EVENT_ID = 121;
private static final boolean DBG = false;
private static int probeResultToEnum(@Nullable final CaptivePortalProbeResult result) {
@@ -61,6 +63,13 @@
Log.d(TAG, "write: " + stats + " with result: " + validationResult
+ ", dns: " + HexDump.toHexString(stats.mDns));
}
- // TODO(b/124613085): Send to Statsd once the public StatsLog API is ready.
+ // TODO(b/124613085): Update API once the public StatsLog API is ready.
+ StatsLog.write(DATA_STALL_EVENT_ID,
+ stats.mEvaluationType,
+ validationResult,
+ stats.mNetworkType,
+ stats.mWifiInfo,
+ stats.mCellularInfo,
+ stats.mDns);
}
}
diff --git a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
index f6eb900..6fbeead 100644
--- a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
+++ b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
@@ -33,7 +33,9 @@
public static void checkNetworkStackCallingPermission() {
// TODO: check that the calling PID is the system server.
final int caller = getCallingUid();
- if (caller != Process.SYSTEM_UID && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
+ if (caller != Process.SYSTEM_UID
+ && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID
+ && UserHandle.getAppId(caller) != Process.PHONE_UID) {
throw new SecurityException("Invalid caller: " + caller);
}
}
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/Android.bp
index f22b647..aadf99e 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/Android.bp
@@ -22,9 +22,8 @@
resource_dirs: ["res"],
static_libs: [
"androidx.test.rules",
- "frameworks-base-testutils",
"mockito-target-extended-minus-junit4",
- "NetworkStackLib",
+ "NetworkStackBase",
"testables",
],
libs: [
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
index 1990229..bd488ea 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
@@ -34,6 +34,7 @@
import static org.mockito.Mockito.when;
import android.app.AlarmManager;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityManager;
@@ -46,14 +47,11 @@
import android.net.shared.InitialConfiguration;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
-import android.provider.Settings;
-import android.test.mock.MockContentResolver;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
-import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.NetworkObserver;
import com.android.server.NetworkObserverRegistry;
@@ -94,7 +92,7 @@
@Mock private IIpClientCallbacks mCb;
@Mock private AlarmManager mAlarm;
@Mock private IpClient.Dependencies mDependencies;
- private MockContentResolver mContentResolver;
+ @Mock private ContentResolver mContentResolver;
private NetworkObserver mObserver;
private InterfaceParams mIfParams;
@@ -109,9 +107,6 @@
when(mDependencies.getNetd(any())).thenReturn(mNetd);
when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
.thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
-
- mContentResolver = new MockContentResolver();
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
mIfParams = null;
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index ee2baf2..34ca6ac 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -525,7 +525,7 @@
wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
makeDnsTimeoutEvent(wrappedMonitor, 5);
assertTrue(wrappedMonitor.isDataStall());
- verify(mDataStallStatsUtils, times(1)).write(any(), any());
+ verify(mDataStallStatsUtils, times(1)).write(makeEmptyDataStallDetectionStats(), any());
}
@Test
@@ -534,7 +534,7 @@
wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
makeDnsTimeoutEvent(wrappedMonitor, 3);
assertFalse(wrappedMonitor.isDataStall());
- verify(mDataStallStatsUtils, never()).write(any(), any());
+ verify(mDataStallStatsUtils, never()).write(makeEmptyDataStallDetectionStats(), any());
}
@Test
@@ -586,6 +586,10 @@
}
}
+ private DataStallDetectionStats makeEmptyDataStallDetectionStats() {
+ return new DataStallDetectionStats.Builder().build();
+ }
+
private void setDataStallEvaluationType(int type) {
when(mDependencies.getSetting(any(),
eq(Settings.Global.DATA_STALL_EVALUATION_TYPE), anyInt())).thenReturn(type);
diff --git a/packages/SettingsLib/res/drawable/ic_smartphone.xml b/packages/SettingsLib/res/drawable/ic_smartphone.xml
new file mode 100644
index 0000000..84a96da
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_smartphone.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="#000000"
+ android:pathData="M17 1.01L7 1c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h10c1.1 0 2 -0.9 2-2V3c0-1.1 -0.9-1.99-2-1.99zM17 19H7V5h10v14z" />
+</vector>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index cfc76b7..835fcc2 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor gegrond op jou gebruik"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor gegrond op jou gebruik (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Sal op grond van jou gebruik waarskynlik hou tot omtrent <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Sal op grond van jou gebruik waarskynlik hou tot omtrent <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Sal waarskynlik hou tot omtrent <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 6e6d58f..11dde97 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ገደማ ቀርቷል"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"በአጠቃቀምዎ መሠረት <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ገደማ ቀርቷል"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"በአጠቃቀምዎ መሠረት <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ገደማ ቀርቷል"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ቀርቷል"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"በአጠቃቀምዎ (<xliff:g id="LEVEL">%2$s</xliff:g>) መሠረት እስከ <xliff:g id="TIME">%1$s</xliff:g> ገደማ መቆየት አለበት"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"በአጠቃቀምዎ መሠረት እስከ <xliff:g id="TIME">%1$s</xliff:g> ገደማ መቆየት አለበት"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"እስከ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ገደማ ድረስ መቆየት አለበት"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 18d47ac..10d4ee5 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"الوقت المتبقي: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك."</string>
<string name="power_discharge_by" msgid="6453537733650125582">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 68f1e6f..dee399e 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"প্রায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি প্ৰায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি প্রায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি বেটাৰি আনুমানিকভাৱে <xliff:g id="TIME">%1$s</xliff:g> লৈকে চলিব (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি বেটাৰি আনুমানিকভাৱে <xliff:g id="TIME">%1$s</xliff:g> লৈকে চলিব"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"বেটাৰি আনুমানিকভাৱে <xliff:g id="TIME">%1$s</xliff:g> লৈকে চলিব (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 8e6e07d..73e3d51 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"İstifadəyə əsasən təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"İstifadəyə əsasən təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"İstifadəyə (<xliff:g id="LEVEL">%2$s</xliff:g>) əsasən təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"İstifadəyə əsasən təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 1cdd1fd..47b536c 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na osnovu korišćenja"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na osnovu korišćenja (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Još <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Trajaće približno do <xliff:g id="TIME">%1$s</xliff:g> na osnovu korišćenja (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Trajaće približno do <xliff:g id="TIME">%1$s</xliff:g> na osnovu korišćenja"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Trajaće približno do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 1a60c3d..ee662fa 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Зараду (<xliff:g id="LEVEL">%2$s</xliff:g>) хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Зараду пры такім выкарыстанні хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Зараду (<xliff:g id="LEVEL">%2$s</xliff:g>) пры такім выкарыстанні хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Хопіць на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Зараду (<xliff:g id="LEVEL">%2$s</xliff:g>) хопіць прыблізна да <xliff:g id="TIME">%1$s</xliff:g> пры цяперашнім узроўні выкарыстання"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Зараду хопіць прыблізна да <xliff:g id="TIME">%1$s</xliff:g> пры цяперашнім узроўні выкарыстання"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Зараду (<xliff:g id="LEVEL">%2$s</xliff:g>) хопіць прыблізна да <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index aaedce4..4e4ac9b 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g> въз основа на използването"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g> въз основа на използването (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Още <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 4f29131..c7d1c0a 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"ব্যবহারের উপর ভিত্তি করে আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"ব্যবহারের উপর ভিত্তি করে আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"আর <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"বর্তমান ব্যবহার অনুযায়ী আনুমানিক <xliff:g id="TIME">%1$s</xliff:g> পর্যন্ত চলবে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"বর্তমান ব্যবহার অনুযায়ী আনুমানিক <xliff:g id="TIME">%1$s</xliff:g> পর্যন্ত চলবে"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"আনুমানিক <xliff:g id="TIME">%1$s</xliff:g> পর্যন্ত চলবে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 4193d52..d5d13d1 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na osnovu vaše potrošnje"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na osnovu vaše potrošnje (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Još <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Trebala bi trajati otprilike do <xliff:g id="TIME">%1$s</xliff:g> na osnovu vaše upotrebe (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Trebala bi trajati otprilike do <xliff:g id="TIME">%1$s</xliff:g> na osnovu vaše upotrebe"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Trebala bi trajati do otprilike <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 9c3e4d9..c000a3c 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Temps restant aproximat: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Temps restant: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"La bateria hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> segons l\'ús que en fas (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"La bateria hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> segons l\'ús que en fas"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"La bateria hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index b6507bc..37b7c51 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Při vašem obvyklém využití zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Při vašem obvyklém využití (<xliff:g id="LEVEL">%2$s</xliff:g>) zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Zbývá <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Při vašem obvyklém využití (<xliff:g id="LEVEL">%2$s</xliff:g>) vydrží asi do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Při vašem obvyklém využití vydrží asi do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Vydrží asi do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index a870cf8..628df26 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage, alt efter hvordan du bruger enheden (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g> baseret på dit forbrug (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g> baseret på dit forbrug"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index bb420a6c..7b63f34 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, basierend auf deiner Nutzung"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, basierend auf deiner Nutzung (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Noch <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Sollte basierend auf deiner Nutzung etwa bis <xliff:g id="TIME">%1$s</xliff:g> reichen (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Sollte basierend auf deiner Nutzung etwa bis <xliff:g id="TIME">%1$s</xliff:g> reichen"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Sollte etwa bis <xliff:g id="TIME">%1$s</xliff:g> reichen (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 22c1b26..7ddd3fc 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, βάσει της χρήσης σας"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, βάσει της χρήσης σας (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Απομένει/ουν <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Θα διαρκέσει μέχρι τις <xliff:g id="TIME">%1$s</xliff:g> περίπου, ανάλογα με τη χρήση σας (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Θα διαρκέσει μέχρι τις <xliff:g id="TIME">%1$s</xliff:g> περίπου, ανάλογα με τη χρήση σας"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Θα διαρκέσει μέχρι τις <xliff:g id="TIME">%1$s</xliff:g> περίπου (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index d4f4e5e..47f31b4 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index d4f4e5e..47f31b4 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index d4f4e5e..47f31b4 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index d4f4e5e..47f31b4 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 98b63ee..bb36101 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index e803abd..22d4748 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g> en función de tu uso"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g> en función de tu uso (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Tiempo restante: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Duración aproximada hasta <xliff:g id="TIME">%1$s</xliff:g> según el uso (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g> según el uso"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Duración aproximada hasta: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index f336f1b..47b1dfa 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Tiempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Tiempo restante aproximado según tu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Tiempo restante aproximado según tu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Tiempo restante: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g> según el uso (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Duración aproximada hasta: <xliff:g id="TIME">%1$s</xliff:g> (según el uso)"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 14ac827..1a704e2 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Teie kasutuse põhjal on jäänud ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Teie kasutuse põhjal on jäänud ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Jäänud on <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Peaks teie kasutuse põhjal kestma kuni <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Peaks teie kasutuse põhjal kestma kuni <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Peaks kestma kuni <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 04710c7..9e1af11 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Erabilera kontuan izanda, <xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Erabilera kontuan izanda, <xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> gelditzen dira"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Erabileraren arabera, ordu honetara arte iraungo du, gutxi gorabehera: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Erabileraren arabera, ordu honetara arte iraungo du, gutxi gorabehera: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Ordu honetara arte iraungo du, gutxi gorabehera: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 8f55092..087a7ff 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"براساس مصرفتان، تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"براساس مصرفتان، تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"با توجه به میزان مصرفتان (<xliff:g id="LEVEL">%2$s</xliff:g>)، باید حدوداً تا <xliff:g id="TIME">%1$s</xliff:g> شارژ داشته باشید"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"باتوجه به میزان مصرفتان، باید حدوداً تا <xliff:g id="TIME">%1$s</xliff:g> شارژ داشته باشید"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"باید حدوداً تا <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) شارژ داشته باشید"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 5802a03..ac1f8a5 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä käyttösi perusteella"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä käyttösi perusteella (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Varaus loppuu käyttösi perusteella noin <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Varaus loppuu käyttösi perusteella noin <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Varaus loppuu noin <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ec8d6b0..acbc028 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> en fonction de votre usage"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> en fonction de votre usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Temps restant : <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>, en fonction de votre usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>, en fonction de votre usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 0b620d8..080074a 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Temps restant : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Temps restant en fonction de votre utilisation (<xliff:g id="LEVEL">%2$s</xliff:g>) : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Temps restant : <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de votre utilisation (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de votre utilisation"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index b4d7fcb..26ee53d 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Tempo restante aproximado (<xliff:g id="LEVEL">%2$s</xliff:g>): <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Tempo restante aproximado en función do uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Tempo restante aproximado en función do uso (<xliff:g id="LEVEL">%2$s</xliff:g>): <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Tempo restante: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"En función do uso, debería durar aproximadamente ata a seguinte hora: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"En función do uso, debería durar aproximadamente ata a seguinte hora: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Debería durar aproximadamente ata a seguinte hora: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 36e04bb..937fc30 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME">%1$s</xliff:g> સુધી ચાલવી જોઈએ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME">%1$s</xliff:g> સુધી ચાલવી જોઈએ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"લગભગ <xliff:g id="TIME">%1$s</xliff:g> સુધી ચાલવી જોઈએ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 8b1ca93..0026d3e 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"बैटरी लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"आपके इस्तेमाल के हिसाब से बैटरी लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"आपके इस्तेमाल के हिसाब से बैटरी लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> में बैटरी खत्म हो जाएगी"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"आपके इस्तेमाल के हिसाब से बैटरी लगभग <xliff:g id="TIME">%1$s</xliff:g> चलेगी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"आपके इस्तेमाल के हिसाब से बैटरी लगभग <xliff:g id="TIME">%1$s</xliff:g> चलेगी"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"बैटरी लगभग <xliff:g id="TIME">%1$s</xliff:g> चलेगी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index b4cbbdb..f06d01d 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na temelju vaše upotrebe"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na temelju vaše upotrebe (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Još <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Otprilike bi trebalo trajati do <xliff:g id="TIME">%1$s</xliff:g> na temelju vaše upotrebe (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Otprilike bi trebalo trajati do <xliff:g id="TIME">%1$s</xliff:g> na temelju vaše upotrebe"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Otprilike bi trebalo trajati do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 589eb59..92b4e20 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra az eszköz használata alapján"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra az eszköz használata alapján (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"A használat alapján nagyjából még ennyit bír: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"A használat alapján nagyjából még ennyit bír: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Nagyjából még ennyit bír: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index ba62c84..b5e5cf5 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Լիցքը կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Լիցքը կբավարարի <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Լիցքը պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index c5d8f30..6bd2876 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi berdasarkan penggunaan Anda (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Akan bertahan kira-kira sampai <xliff:g id="TIME">%1$s</xliff:g> berdasarkan penggunaan Anda (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Akan bertahan kira-kira sampai <xliff:g id="TIME">%1$s</xliff:g> berdasarkan penggunaan Anda"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Akan bertahan kira-kira sampai <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 58505f5..87006ac 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir miðað við notkun þína"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir miðað við notkun þína (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Ætti að endast til u.þ.b. <xliff:g id="TIME">%1$s</xliff:g> miðað við notkun þína (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Ætti að endast til u.þ.b. <xliff:g id="TIME">%1$s</xliff:g> miðað við notkun þína"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Ætti að endast til u.þ.b. <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 6d863aa..b00bada 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Tempo rimanente in base al tuo utilizzo (<xliff:g id="LEVEL">%2$s</xliff:g>): <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Tempo stimato rimanente in base al tuo utilizzo: <xliff:g id="TIME">%1$s</xliff:g> circa (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Tempo stimato rimanente in base al tuo utilizzo: <xliff:g id="TIME">%1$s</xliff:g> circa"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Tempo stimato rimanente: <xliff:g id="TIME">%1$s</xliff:g> circa (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 89d6361..ae16ecb 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"הזמן הנותר על סמך השימוש שלך: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"הזמן הנותר על סמך השימוש שלך: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"הזמן הנותר: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"אמורה להחזיק מעמד בערך עד <xliff:g id="TIME">%1$s</xliff:g> על סמך השימוש במכשיר (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"אמורה להחזיק מעמד בערך עד <xliff:g id="TIME">%1$s</xliff:g> על סמך השימוש במכשיר"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"אמורה להחזיק מעמד בערך עד <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 233e8e8..cc7ff1e 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>(使用状況に基づく)"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>(使用状況に基づく)(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"残り時間: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>(使用状況に基づく)(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>(使用状況に基づく)"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 09bea2a..c54fdfd 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, ბატარეის მოხმარების გათვალისწინებით"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, ბატარეის მოხმარების გათვალისწინებით (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"დარჩენილია <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"უნდა იმუშაოს დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>, ოხმარების გათვალისწინებით (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"უნდა იმუშაოს დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>, მოხმარების გათვალისწინებით"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"უნდა იმუშაოს დაახლოებით <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 8670ec9..e2b40bb 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Пайдалану деректеріңізге сәйкес енді шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Пайдалану деректеріңізге сәйкес енді шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Пайдалануға байланысты шамамен <xliff:g id="TIME">%1$s</xliff:g> уақытқа жетеді (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Пайдалануға байланысты шамамен <xliff:g id="TIME">%1$s</xliff:g> уақытқа жетеді"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) уақытқа жетеді"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 6bf8a0f..1654831 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត ផ្អែកលើការប្រើប្រាស់របស់អ្នក"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត ផ្អែកលើការប្រើប្រាស់របស់អ្នក (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"នៅសល់ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"គួរតែអាចប្រើបានរហូតដល់ម៉ោងប្រហែល <xliff:g id="TIME">%1$s</xliff:g> ដោយផ្អែកលើការប្រើប្រាស់របស់អ្នក (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"គួរតែអាចប្រើបានរហូតដល់ម៉ោងប្រហែល <xliff:g id="TIME">%1$s</xliff:g> ដោយផ្អែកលើការប្រើប្រាស់របស់អ្នក"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"គួរតែអាចប្រើបានរហូតដល់ម៉ោងប្រហែល <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 1e9a0d5..457a163 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"(<xliff:g id="LEVEL">%2$s</xliff:g>) ತಲುಪಲು <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ ಸುಮಾರು <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"ನಿಮ್ಮ ಬಳಕೆಯ (<xliff:g id="LEVEL">%2$s</xliff:g>) ಆಧಾರದ ಮೇಲೆ ಸುಮಾರು <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"ನಿಮ್ಮ ಬಳಕೆ (<xliff:g id="LEVEL">%2$s</xliff:g>) ಆಧರಿಸಿ <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯದವರೆಗೆ ಫೋನ್ ರನ್ ಆಗಬೇಕು"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"ನಿಮ್ಮ ಬಳಕೆ ಆಧರಿಸಿ <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯದವರೆಗೆ ಫೋನ್ ರನ್ ಆಗಬೇಕು"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ಸಮಯದವರೆಗೆ ಫೋನ್ ರನ್ ಆಗಬೇಕು"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 877866c..d19b9f2 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"남은 시간 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"내 사용량을 기준으로 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> 남음"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"내 사용량(<xliff:g id="LEVEL">%2$s</xliff:g>)을 기준으로 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> 남음"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"남은 시간: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"사용량(<xliff:g id="LEVEL">%2$s</xliff:g>)을 기준으로 약 <xliff:g id="TIME">%1$s</xliff:g>까지 사용 가능"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"사용량을 기준으로 약 <xliff:g id="TIME">%1$s</xliff:g>까지 사용 가능"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"약 <xliff:g id="TIME">%1$s</xliff:g>까지 사용 가능(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 9e4a9a8..9bc6d58 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Колдонгонуңузга караганда болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Колдонгонуңузга караганда болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Колдонгонуңузга караганда болжол менен <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) кийин өчөт"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Колдонгонуңузга караганда болжол менен <xliff:g id="TIME">%1$s</xliff:g> кийин өчөт"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) кийин өчөт"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 7e6aaac..5c10aab 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"ເຫຼືອອີກ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 71b8cf0..d437bc7 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, atsižvelgiant į naudojimą"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, atsižvelgiant į naudojimą (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Liko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Pagal tai, kaip naudojama, turėtų išsikrauti maždaug po <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Pagal tai, kaip naudojama, turėtų išsikrauti maždaug po <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Turėtų išsikrauti maždaug po <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 82ec0ae..afa9127 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Ņemot vērā lietojumu, atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Ņemot vērā lietojumu, atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Ņemot vērā lietojumu (<xliff:g id="LEVEL">%2$s</xliff:g>), darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>."</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Ņemot vērā lietojumu, darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index c99ef68..ebc4fda 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> според вашето користење"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> според вашето користење (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Уште <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Треба да трае до околу <xliff:g id="TIME">%1$s</xliff:g> според вашето користење (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Треба да трае до околу <xliff:g id="TIME">%1$s</xliff:g> според вашето користење"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Треба да трае до околу <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index ae97fb2..f04bfcc 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"നിങ്ങളുടെ ഉപയോഗത്തെ അടിസ്ഥാനമാക്കി ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"നിങ്ങളുടെ ഉപയോഗത്തെ അടിസ്ഥാനമാക്കി ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"നിങ്ങളുടെ ഉപയോഗത്തെ അടിസ്ഥാനമാക്കി ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> വരെ നീണ്ടുനിൽക്കേണ്ടതാണ് (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"നിങ്ങളുടെ ഉപയോഗത്തെ അടിസ്ഥാനമാക്കി ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> വരെ നീണ്ടുനിൽക്കേണ്ടതാണ്"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> വരെ നീണ്ടുനിൽക്കേണ്ടതാണ് (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 10c1415..498b855 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Таны хэрэглээнд үндэслэн ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Таны хэрэглээнд үндэслэн ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Таны хэрэглээнд (<xliff:g id="LEVEL">%2$s</xliff:g>) тулгуурлан ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Таны хэрэглээнд тулгуурлан ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 88de8f4..7729f21 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"तुमच्या वापरावर आधारित अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"तुमच्या वापरावर आधारित अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"तुमच्या वापरावर अवलंबून सुमारे <xliff:g id="TIME">%1$s</xliff:g> पर्यंत टिकावी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"तुमच्या वापरावर अवलंबून सुमारे <xliff:g id="TIME">%1$s</xliff:g> पर्यंत टिकावी"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"सुमारे <xliff:g id="TIME">%1$s</xliff:g> पर्यंत टिकेल (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index e98418d..236e30d 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi berdasarkan penggunaan anda"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi berdasarkan penggunaan anda (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Seharusnya boleh digunakan hingga kira-kira <xliff:g id="TIME">%1$s</xliff:g> berdasarkan penggunaan anda (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Seharusnya boleh digunakan hingga kira-kira <xliff:g id="TIME">%1$s</xliff:g> berdasarkan penggunaan anda"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Seharusnya boleh digunakan hingga kira-kira <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index ed2aae6..88eef56 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"သင်၏ အသုံးပြုမှု အပေါ် မူတည်၍ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည်"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"သင်၏ အသုံးပြုမှု အပေါ် မူတည်၍ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ကျန်သည်"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"သင်၏ အသုံးပြုမှုအပေါ် မူတည်၍ <xliff:g id="TIME">%1$s</xliff:g> ခန့်အထိ သုံးနိုင်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"သင်၏ အသုံးပြုမှုအပေါ် အခြေခံ၍ <xliff:g id="TIME">%1$s</xliff:g> ခန့်အထိ သုံးနိုင်သည်"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"<xliff:g id="TIME">%1$s</xliff:g> ခန့်အထိ သုံးနိုင်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 93e53e5..259ed34 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår basert på bruken din"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår basert på bruken din (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g>, basert på bruken din (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g>, basert på bruken din"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index ac15f1b..451691b 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"तपाईंको प्रयोगको आधारमा लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"तपाईंको प्रयोगको आधारमा लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"तपाईंको प्रयोगका आधारमा लगभग <xliff:g id="TIME">%1$s</xliff:g> सम्म टिक्नु पर्छ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"तपाईंको प्रयोगका आधारमा लगभग <xliff:g id="TIME">%1$s</xliff:g> सम्म टिक्नु पर्छ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"ब्याट्री लगभग <xliff:g id="TIME">%1$s</xliff:g> सम्म टिक्नु पर्छ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 959c1ea..00c36de 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend op basis van je gebruik"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend op basis van je gebruik (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> op basis van je gebruik (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> op basis van je gebruik"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 847586e..b24b4a2 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ପାଇଁ (<xliff:g id="LEVEL">%2$s</xliff:g>) ବଳକା ଅଛି"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"ଆପଣଙ୍କ ବ୍ୟବହାରକୁ ଆଧାର କରି ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"ଆପଣଙ୍କର ବ୍ୟବହାରକୁ ଆଧାର କରି (<xliff:g id="LEVEL">%2$s</xliff:g>) ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"ଆପଣଙ୍କର ବ୍ୟବହାରକୁ ଆଧାର କରି ବ୍ୟାଟେରୀ <xliff:g id="TIME">%1$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ ଚାଲିବ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"ଆପଣଙ୍କର ବ୍ୟବହାରକୁ ଆଧାର କରି ବ୍ୟାଟେରୀ <xliff:g id="TIME">%1$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ ଚାଲିବ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"ବ୍ୟାଟେରୀ ପାଖାପାଖି <xliff:g id="TIME">%1$s</xliff:g> ଚାଲିବ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 0675b6b..21a7ab9 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਚੱਲੇਗਾ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਚੱਲੇਗਾ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਚੱਲੇਗਾ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 505e395..e053514 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) (na podstawie Twojego sposobu korzystania)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Jeszcze <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Na podstawie Twojego sposobu korzystania (<xliff:g id="LEVEL">%2$s</xliff:g>) jeszcze około <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Na podstawie Twojego sposobu korzystania jeszcze około <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Powinno wystarczyć do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index c0f31a6..46b2f93 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Tempo restante aproximado, com base no seu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Tempo restante aproximado, com base no seu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Tempo restante: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> com base no seu uso (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> com base no seu uso"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 08c3cc8..dd7861d 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> com base na sua utilização"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> com base na sua utilização (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Resta(m) <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Deve durar até cerca da(s) <xliff:g id="TIME">%1$s</xliff:g> com base na sua utilização (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Deve durar até cerca da(s) <xliff:g id="TIME">%1$s</xliff:g> com base na sua utilização."</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Deve durar até cerca da(s) <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index c0f31a6..46b2f93 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Tempo restante aproximado, com base no seu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Tempo restante aproximado, com base no seu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Tempo restante: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> com base no seu uso (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> com base no seu uso"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 015eb92..3364ce5 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Timp aproximativ rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"În baza utilizării, timpul rămas este de aproximativ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"În baza utilizării, timpul rămas este de aproximativ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Timp rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"În baza utilizării, ar trebui să reziste până la aproximativ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"În baza utilizării, ar trebui să reziste până la aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Ar trebui să reziste până la <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index b0b592c..ffd477d 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Заряда (<xliff:g id="LEVEL">%2$s</xliff:g>) хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Заряда хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g> при текущем уровне расхода"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Заряда (<xliff:g id="LEVEL">%2$s</xliff:g>) хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g> при текущем уровне расхода"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Заряда хватит на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"При текущем уровне использования (<xliff:g id="LEVEL">%2$s</xliff:g>) заряда хватит примерно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"При текущем уровне использования заряда хватит примерно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Заряда (<xliff:g id="LEVEL">%2$s</xliff:g>) хватит примерно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index ca7a962..f3372b3 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ක් පමණ ඉතිරියි (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"ඔබේ භාවිතය මත පදනම්ව <xliff:g id="TIME_REMAINING">%1$s</xliff:g> පමණ ඉතිරිව ඇත"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"ඔබේ භාවිතය මත පදනම්ව <xliff:g id="TIME_REMAINING">%1$s</xliff:g> පමණ ඉතිරිව ඇත (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ඉතිරිව ඇත"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"<xliff:g id="TIME">%1$s</xliff:g> පමණ වන තෙක් (<xliff:g id="LEVEL">%2$s</xliff:g>) ඔබේ භාවිතය මත පදනම්ව තිබිය යුුතුය"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"ඔබේ භාවිතය මත පදනම්ව <xliff:g id="TIME">%1$s</xliff:g> පමන වන තෙක් තිබිය යුතුය"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) පමණ වන තෙක් තිබිය යුතුය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index dd7efdd..5451a0b 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g> – závisí to od intenzity využitia"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g> – závisí to od intenzity využitia (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Zostáva <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Mal by vydržať približne do <xliff:g id="TIME">%1$s</xliff:g> v závislosti od využitia (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Mal by vydržať približne do <xliff:g id="TIME">%1$s</xliff:g> v závislosti od využitia"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Mal by vydržať približne <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index fada686..57265ca 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Glede na način uporabe še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Glede na način uporabe še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Še <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Naprava bi morala glede na način uporabe (<xliff:g id="LEVEL">%2$s</xliff:g>) delovati do približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Naprava bi morala glede na način uporabe delovati do približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Naprava bi morala delovati do približno <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 2132767..231cc1e 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura bazuar në përdorimin tënd (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> bazuar në përdorimin tënd (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> bazuar në përdorimin tënd"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 6cf4b20..42900f7 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g> на основу коришћења"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g> на основу коришћења (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Још <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Трајаће приближно до <xliff:g id="TIME">%1$s</xliff:g> на основу коришћења (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Трајаће приближно до <xliff:g id="TIME">%1$s</xliff:g> на основу коришћења"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Трајаће приближно до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index f2950dc..cc5b76b 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar utifrån din användning"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar utifrån din användning (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Bör räcka ungefär till klockan <xliff:g id="TIME">%1$s</xliff:g> utifrån din användning (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Bör räcka ungefär till klockan <xliff:g id="TIME">%1$s</xliff:g> utifrån din användning"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Bör räcka ungefär till klockan <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d8a74a1..ebe1501 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kulingana na jinsi unavyoitumia"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kulingana na jinsi unavyoitumia (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Zimesalia <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Inapaswa kudumu kwa takribani <xliff:g id="TIME">%1$s</xliff:g> kulingana na jinsi unavyoitumia (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Inapaswa kudumu hadi <xliff:g id="TIME">%1$s</xliff:g> kulingana na jinsi unavyoitumia"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Inapaswa kudumu kwa takribani <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 3cf43c8..951bf99 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"உபயோகத்தின் அடிப்படையில் கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"உபயோகத்தின் அடிப்படையில் கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"நீங்கள் பயன்படுத்துவதன் அடிப்படையில், <xliff:g id="TIME">%1$s</xliff:g> வரை உபயோகிக்க முடியும் (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"நீங்கள் பயன்படுத்துவதன் அடிப்படையில் <xliff:g id="TIME">%1$s</xliff:g> வரை உபயோகிக்க முடியும்"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"<xliff:g id="TIME">%1$s</xliff:g> வரை பயன்படுத்த முடியும் (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index e4dd85f..f7b98d1 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"దాదాపు <xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"మీ వినియోగం ఆధారంగా దాదాపు <xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"మీ వినియోగం ఆధారంగా దాదాపు <xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> మిగిలి ఉంది"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"మీ వినియోగం ఆధారంగా <xliff:g id="TIME">%1$s</xliff:g> వరకు ఉండాలి (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"మీ వినియోగం ఆధారంగా దాదాపు <xliff:g id="TIME">%1$s</xliff:g> వరకు ఉండాలి"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"దాదాపు <xliff:g id="TIME">%1$s</xliff:g> వరకు ఉండాలి (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index cf8362f..7d161bb 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ขึ้นอยู่กับการใช้งานของคุณ"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ขึ้นอยู่กับการใช้งานของคุณ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"เหลืออีก <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> เมื่อดูจากการใช้งานของคุณ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> เมื่อดูจากการใช้งานของคุณ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e690800..e9a2a6f 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira batay sa iyong paggamit"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira batay sa iyong paggamit (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> batay sa iyong paggamit (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> batay sa iyong paggamit"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index ea340e8..73f1c40 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Kullanımınıza göre saat yaklaşık <xliff:g id="TIME">%1$s</xliff:g> olana kadar kullanılabilmelidir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Kullanımınıza göre saat yaklaşık <xliff:g id="TIME">%1$s</xliff:g> olana kadar kullanılabilmelidir"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Saat yaklaşık <xliff:g id="TIME">%1$s</xliff:g> olana kadar kullanılabilmelidir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index cf90ed1..41d6883 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Згідно з даними про використання залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Згідно з даними про використання залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Залишилося <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"На основі даних про використання (<xliff:g id="LEVEL">%2$s</xliff:g>), вистачить приблизно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"На основі даних про використання, вистачить приблизно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Вистачить приблизно до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index c223629..0478a76 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 2851baf..d4eb44b 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Joriy holatda taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Joriy holatda taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 3fb101e..050ee9c 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g> dựa trên mức sử dụng của bạn (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Còn <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Sẽ hết pin cho tới khoảng <xliff:g id="TIME">%1$s</xliff:g> dựa trên mức sử dụng của bạn (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Sẽ hết pin cho tới khoảng <xliff:g id="TIME">%1$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Sẽ hết pin cho tới khoảng <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 0a318d7..e25e4dc 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"大约还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"根据您的使用情况,大约还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"根据您的使用情况,大约还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"根据您的使用情况,估计能用到<xliff:g id="TIME">%1$s</xliff:g>(目前电量为 <xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"根据您的使用情况,估计能用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"目前电量为 <xliff:g id="LEVEL">%2$s</xliff:g>,估计能用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 06bee94..3e357b1 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"根據您的使用情況,還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"根據您的使用情況,還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"還有 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"根據您的使用情況 (<xliff:g id="LEVEL">%2$s</xliff:g>),電量剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"根據您的使用情況,電量剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"電量剩餘約 <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index a5074d9..60330ef 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"目前電量為 <xliff:g id="LEVEL">%2$s</xliff:g>,還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"根據你的使用情形,還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"根據你的使用情形,目前電量為 <xliff:g id="LEVEL">%2$s</xliff:g>,還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"還能使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"根據你的使用情形,目前電量為 <xliff:g id="LEVEL">%2$s</xliff:g>,預估可持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"根據你的使用情形,預估可持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"目前電量 <xliff:g id="LEVEL">%2$s</xliff:g>,預估還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 5892093..a1be06c 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -377,7 +377,8 @@
<string name="power_discharging_duration" msgid="8848256785736335185">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele ngokususelwe ekusebenziseni wakho"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele ngokususelwe ekusebenziseni kwakho (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> esele"</string>
+ <!-- no translation found for power_remaining_duration_only_short (9183070574408359726) -->
+ <skip />
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Kumele ihlale cishe kube ngu-<xliff:g id="TIME">%1$s</xliff:g> kusukela ekusetshenzisweni kwakho (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Kumele ihlale cishe kube ngu-<xliff:g id="TIME">%1$s</xliff:g> kusukela ekusetshenzisweni kwakho"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Kumele ihlale cishe kube ngu-<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f4c7275..bf97d77 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -937,7 +937,7 @@
<string name="power_remaining_duration_only_enhanced">About <xliff:g id="time_remaining">%1$s</xliff:g> left based on your usage</string>
<!-- [CHAR_LIMIT=60] Label for battery level chart when discharging with duration and using enhanced estimate -->
<string name="power_discharging_duration_enhanced">About <xliff:g id="time_remaining">%1$s</xliff:g> left based on your usage (<xliff:g id="level">%2$s</xliff:g>)</string>
- <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging -->
+ <!-- [CHAR_LIMIT=20] Short label for estimated remaining duration of battery charging/discharging -->
<string name="power_remaining_duration_only_short"><xliff:g id="time_remaining">%1$s</xliff:g></string>
<!-- [CHAR_LIMIT=100] Label for enhanced estimated time that phone will run out of battery -->
@@ -948,8 +948,10 @@
<string name="power_discharge_by">Should last until about <xliff:g id="time">%1$s</xliff:g> (<xliff:g id="level">%2$s</xliff:g>)</string>
<!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
<string name="power_discharge_by_only">Should last until about <xliff:g id="time">%1$s</xliff:g></string>
- <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
+ <!-- [CHAR_LIMIT=20] Label for estimated time that phone will run out of battery -->
<string name="power_discharge_by_only_short">Until <xliff:g id="time" example="12 PM">%1$s</xliff:g></string>
+ <!-- [CHAR_LIMIT=100] Extend the battery life past a certain time -->
+ <string name="power_suggestion_extend_battery">Extend battery life past <xliff:g id="time" example="12 PM">%1$s</xliff:g></string>
<!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount -->
<string name="power_remaining_less_than_duration_only">Less than <xliff:g id="threshold">%1$s</xliff:g> remaining</string>
@@ -1151,6 +1153,6 @@
<!-- The notice header of Third-party licenses. not translatable -->
<string name="notice_header" translatable="false"></string>
- <!-- Name of the phone device [CHAR LIMIT=NONE] -->
- <string name="media_transfer_phone_device_name">Phone speaker</string>
+ <!-- Name of the this device. [CHAR LIMIT=30] -->
+ <string name="media_transfer_this_device_name">This device</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index bed3030..785dd56 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -108,12 +108,43 @@
return true;
}
+ /**
+ * Get A2dp devices matching connection states{
+ * @code BluetoothProfile.STATE_CONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTING,
+ * @code BluetoothProfile.STATE_DISCONNECTING}
+ *
+ * @return Matching device list
+ */
public List<BluetoothDevice> getConnectedDevices() {
- if (mService == null) return new ArrayList<BluetoothDevice>(0);
- return mService.getDevicesMatchingConnectionStates(
- new int[] {BluetoothProfile.STATE_CONNECTED,
- BluetoothProfile.STATE_CONNECTING,
- BluetoothProfile.STATE_DISCONNECTING});
+ return getDevicesByStates(new int[] {
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ /**
+ * Get A2dp devices matching connection states{
+ * @code BluetoothProfile.STATE_DISCONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTING,
+ * @code BluetoothProfile.STATE_DISCONNECTING}
+ *
+ * @return Matching device list
+ */
+ public List<BluetoothDevice> getConnectableDevices() {
+ return getDevicesByStates(new int[] {
+ BluetoothProfile.STATE_DISCONNECTED,
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ private List<BluetoothDevice> getDevicesByStates(int[] states) {
+ if (mService == null) {
+ return new ArrayList<BluetoothDevice>(0);
+ }
+ return mService.getDevicesMatchingConnectionStates(states);
}
public boolean connect(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 41c1d60..ebaeb74 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -106,12 +106,43 @@
return true;
}
+ /**
+ * Get Hearing Aid devices matching connection states{
+ * @code BluetoothProfile.STATE_CONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTING,
+ * @code BluetoothProfile.STATE_DISCONNECTING}
+ *
+ * @return Matching device list
+ */
public List<BluetoothDevice> getConnectedDevices() {
- if (mService == null) return new ArrayList<BluetoothDevice>(0);
- return mService.getDevicesMatchingConnectionStates(
- new int[] {BluetoothProfile.STATE_CONNECTED,
- BluetoothProfile.STATE_CONNECTING,
- BluetoothProfile.STATE_DISCONNECTING});
+ return getDevicesByStates(new int[] {
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ /**
+ * Get Hearing Aid devices matching connection states{
+ * @code BluetoothProfile.STATE_DISCONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTING,
+ * @code BluetoothProfile.STATE_DISCONNECTING}
+ *
+ * @return Matching device list
+ */
+ public List<BluetoothDevice> getConnectableDevices() {
+ return getDevicesByStates(new int[] {
+ BluetoothProfile.STATE_DISCONNECTED,
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ private List<BluetoothDevice> getDevicesByStates(int[] states) {
+ if (mService == null) {
+ return new ArrayList<BluetoothDevice>(0);
+ }
+ return mService.getDevicesMatchingConnectionStates(states);
}
public boolean connect(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index 6d0e3ac..3092b99 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -16,6 +16,7 @@
package com.android.settingslib.media;
import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.util.Log;
@@ -42,6 +43,11 @@
}
@Override
+ public String getSummary() {
+ return mCachedDevice.getConnectionSummary();
+ }
+
+ @Override
public int getIcon() {
//TODO(b/117129183): This is not final icon for bluetooth device, just for demo.
return com.android.internal.R.drawable.ic_bt_headphones_a2dp;
@@ -86,4 +92,10 @@
}
return false;
}
+
+ @Override
+ public boolean isConnected() {
+ return mCachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
+ && mCachedDevice.isConnected();
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
index fa2dd88..3a738d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
@@ -41,6 +41,9 @@
private static final String TAG = "BluetoothMediaManager";
+ private final DeviceAttributeChangeCallback mDeviceAttributeChangeCallback =
+ new DeviceAttributeChangeCallback();
+
private LocalBluetoothManager mLocalBluetoothManager;
private LocalBluetoothProfileManager mProfileManager;
private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
@@ -65,7 +68,10 @@
mLocalBluetoothManager.getEventManager().registerCallback(this);
buildBluetoothDeviceList();
dispatchDeviceListAdded();
+ addServiceListenerIfNecessary();
+ }
+ private void addServiceListenerIfNecessary() {
// The profile may not ready when calling startScan().
// Device status are all disconnected since profiles are not ready to connected.
// In this case, we observe onServiceConnected() in LocalBluetoothProfileManager.
@@ -78,18 +84,18 @@
private void buildBluetoothDeviceList() {
mMediaDevices.clear();
- addConnectedA2dpDevices();
- addConnectedHearingAidDevices();
+ addConnectableA2dpDevices();
+ addConnectableHearingAidDevices();
}
- private void addConnectedA2dpDevices() {
+ private void addConnectableA2dpDevices() {
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
if (a2dpProfile == null) {
- Log.w(TAG, "addConnectedA2dpDevices() a2dp profile is null!");
+ Log.w(TAG, "addConnectableA2dpDevices() a2dp profile is null!");
return;
}
- final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
+ final List<BluetoothDevice> devices = a2dpProfile.getConnectableDevices();
for (BluetoothDevice device : devices) {
final CachedBluetoothDevice cachedDevice =
@@ -100,10 +106,12 @@
continue;
}
- Log.d(TAG, "addConnectedA2dpDevices() device : " + cachedDevice.getName()
- + ", is connected : " + cachedDevice.isConnected());
+ Log.d(TAG, "addConnectableA2dpDevices() device : " + cachedDevice.getName()
+ + ", is connected : " + cachedDevice.isConnected()
+ + ", is preferred : " + a2dpProfile.isPreferred(device));
- if (cachedDevice.isConnected()) {
+ if (a2dpProfile.isPreferred(device)
+ && BluetoothDevice.BOND_BONDED == cachedDevice.getBondState()) {
addMediaDevice(cachedDevice);
}
}
@@ -111,15 +119,15 @@
mIsA2dpProfileReady = a2dpProfile.isProfileReady();
}
- private void addConnectedHearingAidDevices() {
+ private void addConnectableHearingAidDevices() {
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
if (hapProfile == null) {
- Log.w(TAG, "addConnectedA2dpDevices() hap profile is null!");
+ Log.w(TAG, "addConnectableHearingAidDevices() hap profile is null!");
return;
}
final List<Long> devicesHiSyncIds = new ArrayList<>();
- final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
+ final List<BluetoothDevice> devices = hapProfile.getConnectableDevices();
for (BluetoothDevice device : devices) {
final CachedBluetoothDevice cachedDevice =
@@ -130,13 +138,16 @@
continue;
}
- Log.d(TAG, "addConnectedHearingAidDevices() device : " + cachedDevice.getName()
- + ", is connected : " + cachedDevice.isConnected());
+ Log.d(TAG, "addConnectableHearingAidDevices() device : " + cachedDevice.getName()
+ + ", is connected : " + cachedDevice.isConnected()
+ + ", is preferred : " + hapProfile.isPreferred(device));
+
final long hiSyncId = hapProfile.getHiSyncId(device);
// device with same hiSyncId should not be shown in the UI.
// So do not add it into connectedDevices.
- if (!devicesHiSyncIds.contains(hiSyncId) && cachedDevice.isConnected()) {
+ if (!devicesHiSyncIds.contains(hiSyncId) && hapProfile.isPreferred(device)
+ && BluetoothDevice.BOND_BONDED == cachedDevice.getBondState()) {
devicesHiSyncIds.add(hiSyncId);
addMediaDevice(cachedDevice);
}
@@ -149,6 +160,7 @@
MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
if (mediaDevice == null) {
mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice);
+ cachedDevice.registerCallback(mDeviceAttributeChangeCallback);
mLastAddedDevice = mediaDevice;
mMediaDevices.add(mediaDevice);
}
@@ -157,6 +169,14 @@
@Override
public void stopScan() {
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+ unregisterDeviceAttributeChangeCallback();
+ }
+
+ private void unregisterDeviceAttributeChangeCallback() {
+ for (MediaDevice device : mMediaDevices) {
+ ((BluetoothMediaDevice) device).getCachedDevice()
+ .unregisterCallback(mDeviceAttributeChangeCallback);
+ }
}
@Override
@@ -164,12 +184,13 @@
if (BluetoothAdapter.STATE_ON == bluetoothState) {
buildBluetoothDeviceList();
dispatchDeviceListAdded();
+ addServiceListenerIfNecessary();
} else if (BluetoothAdapter.STATE_OFF == bluetoothState) {
final List<MediaDevice> removeDevicesList = new ArrayList<>();
for (MediaDevice device : mMediaDevices) {
- if (device instanceof BluetoothMediaDevice) {
- removeDevicesList.add(device);
- }
+ ((BluetoothMediaDevice) device).getCachedDevice()
+ .unregisterCallback(mDeviceAttributeChangeCallback);
+ removeDevicesList.add(device);
}
mMediaDevices.removeAll(removeDevicesList);
dispatchDeviceListRemoved(removeDevicesList);
@@ -212,6 +233,7 @@
private void removeMediaDevice(CachedBluetoothDevice cachedDevice) {
final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
if (mediaDevice != null) {
+ cachedDevice.unregisterCallback(mDeviceAttributeChangeCallback);
mLastRemovedDevice = mediaDevice;
mMediaDevices.remove(mediaDevice);
}
@@ -230,12 +252,17 @@
Log.d(TAG, "onProfileConnectionStateChanged() device: " + cachedDevice
+ ", state: " + state + ", bluetoothProfile: " + bluetoothProfile);
- if (isCachedDeviceConnected(cachedDevice)) {
- addMediaDevice(cachedDevice);
- dispatchDeviceAdded(cachedDevice);
- } else {
+ updateMediaDeviceListIfNecessary(cachedDevice);
+ }
+
+ private void updateMediaDeviceListIfNecessary(CachedBluetoothDevice cachedDevice) {
+ if (BluetoothDevice.BOND_NONE == cachedDevice.getBondState()) {
removeMediaDevice(cachedDevice);
dispatchDeviceRemoved(cachedDevice);
+ } else {
+ if (findMediaDevice(MediaDeviceUtils.getId(cachedDevice)) != null) {
+ dispatchDataChanged();
+ }
}
}
@@ -243,13 +270,7 @@
public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
Log.d(TAG, "onAclConnectionStateChanged() device: " + cachedDevice + ", state: " + state);
- if (isCachedDeviceConnected(cachedDevice)) {
- addMediaDevice(cachedDevice);
- dispatchDeviceAdded(cachedDevice);
- } else {
- removeMediaDevice(cachedDevice);
- dispatchDeviceRemoved(cachedDevice);
- }
+ updateMediaDeviceListIfNecessary(cachedDevice);
}
@Override
@@ -281,4 +302,16 @@
public void onServiceDisconnected() {
}
+
+ /**
+ * This callback is for update {@link BluetoothMediaDevice} summary when
+ * {@link CachedBluetoothDevice} connection state is changed.
+ */
+ private class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
+
+ @Override
+ public void onDeviceAttributesChanged() {
+ dispatchDataChanged();
+ }
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 99d9d1c..95f3d3d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -41,6 +41,11 @@
}
@Override
+ public String getSummary() {
+ return null;
+ }
+
+ @Override
public int getIcon() {
//TODO(b/121083246): This is not final icon for cast device, just for demo.
return com.android.internal.R.drawable.ic_settings_print;
@@ -63,4 +68,9 @@
public void disconnect() {
//TODO(b/121083246): disconnected last select device
}
+
+ @Override
+ public boolean isConnected() {
+ return true;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 44d945a..4e16c66 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -58,7 +58,6 @@
private Context mContext;
private BluetoothMediaManager mBluetoothMediaManager;
- private InfoMediaManager mInfoMediaManager;
private LocalBluetoothManager mLocalBluetoothManager;
@VisibleForTesting
@@ -97,7 +96,6 @@
mBluetoothMediaManager =
new BluetoothMediaManager(context, mLocalBluetoothManager, notification);
- mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
}
@VisibleForTesting
@@ -106,7 +104,6 @@
mContext = context;
mLocalBluetoothManager = localBluetoothManager;
mBluetoothMediaManager = bluetoothMediaManager;
- mInfoMediaManager = infoMediaManager;
}
/**
@@ -115,6 +112,15 @@
*/
public void connectDevice(MediaDevice connectDevice) {
final MediaDevice device = getMediaDeviceById(mMediaDevices, connectDevice.getId());
+ if (device instanceof BluetoothMediaDevice) {
+ final CachedBluetoothDevice cachedDevice =
+ ((BluetoothMediaDevice) device).getCachedDevice();
+ if (!cachedDevice.isConnected() && !cachedDevice.isBusy()) {
+ cachedDevice.connect(true);
+ return;
+ }
+ }
+
if (device == mCurrentConnectedDevice) {
Log.d(TAG, "connectDevice() this device all ready connected! : " + device.getName());
return;
@@ -150,9 +156,7 @@
public void startScan() {
mMediaDevices.clear();
mBluetoothMediaManager.registerCallback(mMediaDeviceCallback);
- mInfoMediaManager.registerCallback(mMediaDeviceCallback);
mBluetoothMediaManager.startScan();
- mInfoMediaManager.startScan();
}
private void addPhoneDeviceIfNecessary() {
@@ -186,9 +190,7 @@
*/
public void stopScan() {
mBluetoothMediaManager.unregisterCallback(mMediaDeviceCallback);
- mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
mBluetoothMediaManager.stopScan();
- mInfoMediaManager.stopScan();
}
/**
@@ -252,9 +254,17 @@
}
addPhoneDeviceIfNecessary();
mCurrentConnectedDevice = updateCurrentConnectedDevice();
+ updatePhoneMediaDeviceSummary();
dispatchDeviceListUpdate();
}
+ private void updatePhoneMediaDeviceSummary() {
+ if (mPhoneDevice != null) {
+ ((PhoneMediaDevice) mPhoneDevice)
+ .updateSummary(mCurrentConnectedDevice == mPhoneDevice);
+ }
+ }
+
@Override
public void onDeviceRemoved(MediaDevice device) {
if (mMediaDevices.contains(device)) {
@@ -272,21 +282,22 @@
}
@Override
- public void onDeviceAttributesChanged() {
- dispatchDeviceListUpdate();
- }
-
- @Override
public void onConnectedDeviceChanged(String id) {
final MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id);
if (connectDevice == mCurrentConnectedDevice) {
- Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected! : "
- + connectDevice.getName());
+ Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected!");
return;
}
mCurrentConnectedDevice = connectDevice;
+ updatePhoneMediaDeviceSummary();
+ dispatchDeviceListUpdate();
+ }
+ @Override
+ public void onDeviceAttributesChanged() {
+ addPhoneDeviceIfNecessary();
+ removePhoneMediaDeviceIfNecessary();
dispatchDeviceListUpdate();
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index f35c30e..9b9e803 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -34,9 +34,9 @@
MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
MediaDeviceType.TYPE_PHONE_DEVICE})
public @interface MediaDeviceType {
- int TYPE_CAST_DEVICE = 1;
- int TYPE_BLUETOOTH_DEVICE = 2;
- int TYPE_PHONE_DEVICE = 3;
+ int TYPE_PHONE_DEVICE = 1;
+ int TYPE_CAST_DEVICE = 2;
+ int TYPE_BLUETOOTH_DEVICE = 3;
}
private int mConnectedRecord;
@@ -63,6 +63,13 @@
public abstract String getName();
/**
+ * Get summary from MediaDevice.
+ *
+ * @return summary of MediaDevice.
+ */
+ public abstract String getSummary();
+
+ /**
* Get resource id of MediaDevice.
*
* @return resource id of MediaDevice.
@@ -94,6 +101,13 @@
public abstract void disconnect();
/**
+ * According the MediaDevice type to check whether we are connected to this MediaDevice.
+ *
+ * @return Whether it is connected.
+ */
+ public abstract boolean isConnected();
+
+ /**
* Rules:
* 1. If there is one of the connected devices identified as a carkit, this carkit will
* be always on the top of the device list. Rule 2 and Rule 3 can’t overrule this rule.
@@ -103,9 +117,11 @@
* 3. For devices with usage record.
* The most recent used one + device group with usage info sorted by how many times the
* device has been used.
+ * 4. Phone device always in the top and the connected Bluetooth devices, cast devices and
+ * phone device will be always above on the disconnect Bluetooth devices.
*
- * So the device list will look like 4 slots ranked as below.
- * Rule 1 + the most recently used device + Rule 3 + Rule 2
+ * So the device list will look like 5 slots ranked as below.
+ * Rule 4 + Rule 1 + the most recently used device + Rule 3 + Rule 2
* Any slot could be empty. And available device will belong to one of the slots.
*
* @return a negative integer, zero, or a positive integer
@@ -113,6 +129,21 @@
*/
@Override
public int compareTo(MediaDevice another) {
+ // Check Bluetooth device is have same connection state
+ if (isConnected() ^ another.isConnected()) {
+ if (isConnected()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ // Phone device always in the top.
+ if (mType == MediaDeviceType.TYPE_PHONE_DEVICE) {
+ return -1;
+ } else if (another.mType == MediaDeviceType.TYPE_PHONE_DEVICE) {
+ return 1;
+ }
// Check carkit
if (isCarKitDevice()) {
return -1;
@@ -138,7 +169,7 @@
final String s2 = another.getName();
return s1.compareToIgnoreCase(s2);
}
- // Both devices have never been used, the priority is Cast > Bluetooth > Phone
+ // Both devices have never been used, the priority is Phone > Cast > Bluetooth
return mType - another.mType;
}
@@ -149,4 +180,13 @@
protected boolean isCarKitDevice() {
return false;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof MediaDevice)) {
+ return false;
+ }
+ final MediaDevice otherDevice = (MediaDevice) obj;
+ return otherDevice.getId().equals(getId());
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
index 2c3a96c..7898982 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
@@ -117,6 +117,14 @@
}
}
+ protected void dispatchDataChanged() {
+ synchronized (mCallbacks) {
+ for (MediaDeviceCallback callback : mCallbacks) {
+ callback.onDeviceAttributesChanged();
+ }
+ }
+ }
+
/**
* Callback for notifying device is added, removed and attributes changed.
*/
@@ -150,15 +158,16 @@
void onDeviceListRemoved(List<MediaDevice> devices);
/**
- * Callback for notifying MediaDevice attributes is changed.
- */
- void onDeviceAttributesChanged();
-
- /**
* Callback for notifying connected MediaDevice is changed.
*
* @param id the id of MediaDevice
*/
void onConnectedDeviceChanged(String id);
+
+ /**
+ * Callback for notifying that MediaDevice attributes
+ * (e.g: device name, connection state, subtitle) is changed.
+ */
+ void onDeviceAttributesChanged();
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index 8ec2a7f..da140aa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.util.Log;
+import com.android.settingslib.R;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -34,6 +35,7 @@
private LocalBluetoothProfileManager mProfileManager;
private LocalBluetoothManager mLocalBluetoothManager;
+ private String mSummary = "";
PhoneMediaDevice(Context context, LocalBluetoothManager localBluetoothManager) {
super(context, MediaDeviceType.TYPE_PHONE_DEVICE);
@@ -45,14 +47,17 @@
@Override
public String getName() {
- return mContext
- .getString(com.android.settingslib.R.string.media_transfer_phone_device_name);
+ return mContext.getString(R.string.media_transfer_this_device_name);
+ }
+
+ @Override
+ public String getSummary() {
+ return mSummary;
}
@Override
public int getIcon() {
- //TODO(b/117129183): This is not final icon for phone device, just for demo.
- return com.android.internal.R.drawable.ic_phone;
+ return R.drawable.ic_smartphone;
}
@Override
@@ -69,6 +74,7 @@
if (hapProfile != null && a2dpProfile != null) {
isConnected = hapProfile.setActiveDevice(null) && a2dpProfile.setActiveDevice(null);
+ updateSummary(true);
setConnectedRecord();
}
Log.d(TAG, "connect() device : " + getName() + ", is selected : " + isConnected);
@@ -77,6 +83,20 @@
@Override
public void disconnect() {
- //TODO(b/117129183): disconnected last select device
+ updateSummary(false);
+ }
+
+ @Override
+ public boolean isConnected() {
+ return true;
+ }
+
+ /**
+ * According current active device is {@link PhoneMediaDevice} or not to update summary.
+ */
+ public void updateSummary(boolean isActive) {
+ mSummary = isActive
+ ? mContext.getString(R.string.bluetooth_active_no_battery_level)
+ : "";
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index 52d7e2c..7046d23 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -101,7 +101,29 @@
if (drainTimeMs <= ONE_DAY_MILLIS) {
return getRegularTimeRemainingShortString(context, drainTimeMs);
} else {
- return getMoreThanOneDayShortString(context, drainTimeMs);
+ return getMoreThanOneDayShortString(context, drainTimeMs,
+ R.string.power_remaining_duration_only_short);
+ }
+ }
+
+ /**
+ * This method produces the text used in Settings battery tip to describe the effect after
+ * use the tip.
+ *
+ * @param context
+ * @param drainTimeMs The estimated time remaining before the phone dies in milliseconds.
+ * @return a properly formatted and localized string
+ */
+ public static String getBatteryTipStringFormatted(Context context, long drainTimeMs) {
+ if (drainTimeMs <= 0) {
+ return null;
+ }
+ if (drainTimeMs <= ONE_DAY_MILLIS) {
+ return context.getString(R.string.power_suggestion_extend_battery,
+ getDateTimeStringFromMs(context, drainTimeMs));
+ } else {
+ return getMoreThanOneDayShortString(context, drainTimeMs,
+ R.string.power_remaining_only_more_than_subtext);
}
}
@@ -144,12 +166,13 @@
}
}
- private static String getMoreThanOneDayShortString(Context context, long drainTimeMs) {
+ private static String getMoreThanOneDayShortString(Context context, long drainTimeMs,
+ int resId) {
final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, ONE_HOUR_MILLIS);
CharSequence timeString = StringUtil.formatElapsedTime(context, roundedTimeMs,
false /* withSeconds */);
- return context.getString(R.string.power_remaining_duration_only_short, timeString);
+ return context.getString(resId, timeString);
}
private static String getMoreThanTwoDaysString(Context context, String percentageString) {
@@ -169,17 +192,8 @@
private static String getRegularTimeRemainingString(Context context, long drainTimeMs,
String percentageString, boolean basedOnUsage) {
- // Get the time of day we think device will die rounded to the nearest 15 min.
- final long roundedTimeOfDayMs =
- roundTimeToNearestThreshold(
- System.currentTimeMillis() + drainTimeMs,
- FIFTEEN_MINUTES_MILLIS);
- // convert the time to a properly formatted string.
- String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
- DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
- Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
- CharSequence timeString = fmt.format(date);
+ CharSequence timeString = getDateTimeStringFromMs(context, drainTimeMs);
if (TextUtils.isEmpty(percentageString)) {
int id = basedOnUsage
@@ -194,13 +208,34 @@
}
}
- private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) {
- // Get the time remaining rounded to the nearest 15 min
- final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, FIFTEEN_MINUTES_MILLIS);
- CharSequence timeString = StringUtil.formatElapsedTime(context, roundedTimeMs,
- false /* withSeconds */);
+ private static CharSequence getDateTimeStringFromMs(Context context, long drainTimeMs) {
+ // Get the time of day we think device will die rounded to the nearest 15 min.
+ final long roundedTimeOfDayMs =
+ roundTimeToNearestThreshold(
+ System.currentTimeMillis() + drainTimeMs,
+ FIFTEEN_MINUTES_MILLIS);
- return context.getString(R.string.power_remaining_duration_only_short, timeString);
+ // convert the time to a properly formatted string.
+ String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
+ DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
+ Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
+ return fmt.format(date);
+ }
+
+ private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) {
+ // Get the time of day we think device will die rounded to the nearest 15 min.
+ final long roundedTimeOfDayMs =
+ roundTimeToNearestThreshold(
+ System.currentTimeMillis() + drainTimeMs,
+ FIFTEEN_MINUTES_MILLIS);
+
+ // convert the time to a properly formatted string.
+ String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
+ DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
+ Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
+ CharSequence timeString = fmt.format(date);
+
+ return context.getString(R.string.power_discharge_by_only_short, timeString);
}
public static long convertUsToMs(long timeUs) {
@@ -231,4 +266,4 @@
return time - remainder + multiple;
}
}
-}
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index d9b4885..59fbb72 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1076,7 +1076,7 @@
return (info.isOsuAp() && mOsuStatus != null);
} else if (info.isPasspointAp() || isPasspoint()) {
return (info.isPasspointAp() && isPasspoint()
- && TextUtils.equals(info.getFqdn(), mConfig.FQDN));
+ && TextUtils.equals(info.getPasspointFqdn(), mConfig.FQDN));
}
if (networkId != WifiConfiguration.INVALID_NETWORK_ID) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 3c10688..2ab369c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -118,7 +118,7 @@
mWifiInfo = mWifiManager.getConnectionInfo();
if (mWifiInfo != null) {
if (mWifiInfo.isPasspointAp() || mWifiInfo.isOsuAp()) {
- ssid = mWifiInfo.getProviderFriendlyName();
+ ssid = mWifiInfo.getPasspointProviderFriendlyName();
} else {
ssid = getValidSsid(mWifiInfo);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
index e5d1b18..e0e2fd6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
@@ -20,6 +20,7 @@
import static org.mockito.Mockito.when;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
@@ -66,4 +67,20 @@
assertThat(mBluetoothMediaDevice.connect()).isFalse();
}
+
+ @Test
+ public void isCachedBluetoothDeviceConnected_deviceConnected_returnTrue() {
+ when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice.isConnected()).thenReturn(true);
+
+ assertThat(mBluetoothMediaDevice.isConnected()).isTrue();
+ }
+
+ @Test
+ public void isCachedBluetoothDeviceConnected_deviceNotConnected_returnFalse() {
+ when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice.isConnected()).thenReturn(false);
+
+ assertThat(mBluetoothMediaDevice.isConnected()).isFalse();
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
index a20e22b..48449f2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
@@ -87,15 +87,16 @@
}
@Test
- public void startScan_haveA2dpProfileConnectedBluetoothDevice_shouldAddDevice() {
+ public void startScan_haveA2dpProfileDeviceIsPreferredAndBonded_shouldAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
devices.add(bluetoothDevice);
- when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
+ when(mA2dpProfile.getConnectableDevices()).thenReturn(devices);
when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
- when(cachedDevice.isConnected()).thenReturn(true);
+ when(cachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mA2dpProfile.isPreferred(bluetoothDevice)).thenReturn(true);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
@@ -103,15 +104,16 @@
}
@Test
- public void startScan_haveA2dpProfileDisconnectedBluetoothDevice_shouldNotAddDevice() {
+ public void startScan_haveA2dpProfileDeviceIsPreferredAndBondNone_shouldNotAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
devices.add(bluetoothDevice);
- when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
+ when(mA2dpProfile.getConnectableDevices()).thenReturn(devices);
when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
- when(cachedDevice.isConnected()).thenReturn(false);
+ when(cachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+ when(mA2dpProfile.isPreferred(bluetoothDevice)).thenReturn(true);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
@@ -122,7 +124,7 @@
public void startScan_noA2dpProfileBluetoothDevice_shouldNotAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
- when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
+ when(mA2dpProfile.getConnectableDevices()).thenReturn(devices);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
@@ -130,15 +132,16 @@
}
@Test
- public void startScan_haveHapProfileConnectedBluetoothDevice_shouldAddDevice() {
+ public void startScan_haveHapProfileDeviceIsPreferredAndBonded_shouldAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
devices.add(bluetoothDevice);
- when(mHapProfile.getConnectedDevices()).thenReturn(devices);
+ when(mHapProfile.getConnectableDevices()).thenReturn(devices);
when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
- when(cachedDevice.isConnected()).thenReturn(true);
+ when(cachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mHapProfile.isPreferred(bluetoothDevice)).thenReturn(true);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
@@ -149,7 +152,7 @@
public void startScan_noHapProfileBluetoothDevice_shouldNotAddDevice() {
final List<BluetoothDevice> devices = new ArrayList<>();
- when(mHapProfile.getConnectedDevices()).thenReturn(devices);
+ when(mHapProfile.getConnectableDevices()).thenReturn(devices);
assertThat(mMediaManager.mMediaDevices).isEmpty();
mMediaManager.startScan();
@@ -230,9 +233,14 @@
public void onBluetoothStateChanged_bluetoothStateIsOff_callOnDeviceListRemoved() {
final BluetoothMediaDevice device1 = mock(BluetoothMediaDevice.class);
final BluetoothMediaDevice device2 = mock(BluetoothMediaDevice.class);
+ final CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
+ final CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class);
mMediaManager.mMediaDevices.add(device1);
mMediaManager.mMediaDevices.add(device2);
+ when(device1.getCachedDevice()).thenReturn(cachedDevice1);
+ when(device2.getCachedDevice()).thenReturn(cachedDevice2);
+
mMediaManager.registerCallback(mCallback);
mMediaManager.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
@@ -311,28 +319,30 @@
}
@Test
- public void onProfileConnectionStateChanged_cachedDeviceIsConnect_callOnDeviceAdded() {
- final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
-
- when(device.isConnectedHearingAidDevice()).thenReturn(true);
- when(device.isConnectedA2dpDevice()).thenReturn(true);
-
- assertThat(mMediaManager.mMediaDevices).isEmpty();
- mMediaManager.registerCallback(mCallback);
- mMediaManager.onProfileConnectionStateChanged(device, 0, 0);
-
- assertThat(mMediaManager.mMediaDevices).hasSize(1);
- verify(mCallback).onDeviceAdded(any());
- }
-
- @Test
- public void onProfileConnectionStateChanged_cachedDeviceIsDisconnect_callOnDeviceRemoved() {
+ public void onProfileConnectionStateChanged_cachedDeviceIsBonded_callDeviceAttributesChanged() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
- when(device.isConnectedHearingAidDevice()).thenReturn(false);
- when(device.isConnectedA2dpDevice()).thenReturn(false);
+ when(device.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(device.getAddress()).thenReturn(TEST_ADDRESS);
+ when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
+
+ assertThat(mMediaManager.mMediaDevices).hasSize(1);
+ mMediaManager.registerCallback(mCallback);
+ mMediaManager.onProfileConnectionStateChanged(device, 0, 0);
+
+ assertThat(mMediaManager.mMediaDevices).hasSize(1);
+ verify(mCallback).onDeviceAttributesChanged();
+ }
+
+ @Test
+ public void onProfileConnectionStateChanged_cachedDeviceIsBondNone_callOnDeviceRemoved() {
+ final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
+ final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
+ mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
+
+ when(device.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
@@ -345,28 +355,30 @@
}
@Test
- public void onAclConnectionStateChanged_cachedDeviceIsConnect_callOnDeviceAdded() {
- final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
-
- when(device.isConnectedHearingAidDevice()).thenReturn(true);
- when(device.isConnectedA2dpDevice()).thenReturn(true);
-
- assertThat(mMediaManager.mMediaDevices).isEmpty();
- mMediaManager.registerCallback(mCallback);
- mMediaManager.onAclConnectionStateChanged(device, 0);
-
- assertThat(mMediaManager.mMediaDevices).hasSize(1);
- verify(mCallback).onDeviceAdded(any());
- }
-
- @Test
- public void onAclConnectionStateChanged_cachedDeviceIsDisconnect_callOnDeviceRemoved() {
+ public void onAclConnectionStateChanged_cachedDeviceIsBonded_callDeviceAttributesChanged() {
final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
- when(device.isConnectedHearingAidDevice()).thenReturn(false);
- when(device.isConnectedA2dpDevice()).thenReturn(false);
+ when(device.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(device.getAddress()).thenReturn(TEST_ADDRESS);
+ when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
+
+ assertThat(mMediaManager.mMediaDevices).hasSize(1);
+ mMediaManager.registerCallback(mCallback);
+ mMediaManager.onAclConnectionStateChanged(device, 0);
+
+ assertThat(mMediaManager.mMediaDevices).hasSize(1);
+ verify(mCallback).onDeviceAttributesChanged();
+ }
+
+ @Test
+ public void onAclConnectionStateChanged_cachedDeviceIsBondNone_callOnDeviceRemoved() {
+ final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
+ final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
+ mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
+
+ when(device.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
when(device.getAddress()).thenReturn(TEST_ADDRESS);
when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 3556814..98bb74a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -28,6 +28,7 @@
import android.content.Context;
import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
@@ -113,6 +114,23 @@
}
@Test
+ public void connectDevice_bluetoothDeviceNotConnected_connectBluetoothDevice() {
+ final MediaDevice device = mock(BluetoothMediaDevice.class);
+ final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
+ mLocalMediaManager.mMediaDevices.add(device);
+
+ when(device.getId()).thenReturn(TEST_DEVICE_ID_1);
+ when(((BluetoothMediaDevice) device).getCachedDevice()).thenReturn(cachedDevice);
+ when(cachedDevice.isConnected()).thenReturn(false);
+ when(cachedDevice.isBusy()).thenReturn(false);
+
+ mLocalMediaManager.registerCallback(mCallback);
+ mLocalMediaManager.connectDevice(device);
+
+ verify(cachedDevice).connect(true);
+ }
+
+ @Test
public void getMediaDeviceById_idExist_shouldReturnMediaDevice() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
@@ -322,15 +340,6 @@
}
@Test
- public void onDeviceAttributesChanged_shouldDispatchDeviceListUpdate() {
- mLocalMediaManager.registerCallback(mCallback);
-
- mLocalMediaManager.mMediaDeviceCallback.onDeviceAttributesChanged();
-
- verify(mCallback).onDeviceListUpdate(any());
- }
-
- @Test
public void onConnectedDeviceChanged_connectedAndCurrentDeviceAreDifferent_notifyThemChanged() {
final MediaDevice device1 = mock(MediaDevice.class);
final MediaDevice device2 = mock(MediaDevice.class);
@@ -366,4 +375,13 @@
verify(mCallback, never()).onDeviceListUpdate(any());
}
+
+ @Test
+ public void onDeviceAttributesChanged_shouldDispatchDeviceListUpdate() {
+ mLocalMediaManager.registerCallback(mCallback);
+
+ mLocalMediaManager.mMediaDeviceCallback.onDeviceAttributesChanged();
+
+ verify(mCallback).onDeviceListUpdate(any());
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index fc514f0..23d2c74 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -114,6 +114,12 @@
when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
when(mCachedDevice3.getDevice()).thenReturn(mDevice3);
+ when(mCachedDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mCachedDevice1.isConnected()).thenReturn(true);
+ when(mCachedDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mCachedDevice2.isConnected()).thenReturn(true);
+ when(mCachedDevice3.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mCachedDevice3.isConnected()).thenReturn(true);
when(mRouteInfo1.getId()).thenReturn(ROUTER_ID_1);
when(mRouteInfo2.getId()).thenReturn(ROUTER_ID_2);
when(mRouteInfo3.getId()).thenReturn(ROUTER_ID_3);
@@ -158,12 +164,25 @@
}
@Test
- public void compareTo_carKit_phone_carKitFirst() {
+ public void compareTo_carKit_phone_phoneFirst() {
when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
- mMediaDevices.add(mPhoneMediaDevice);
mMediaDevices.add(mBluetoothMediaDevice1);
+ mMediaDevices.add(mPhoneMediaDevice);
+ assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+ Collections.sort(mMediaDevices, COMPARATOR);
assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
+ }
+
+ @Test
+ public void compareTo_carKitIsDisConnected_nonCarKitBluetooth_nonCarKitBluetoothFirst() {
+ when(mDevice1.getBluetoothClass()).thenReturn(mHeadreeClass);
+ when(mDevice2.getBluetoothClass()).thenReturn(mCarkitClass);
+ when(mCachedDevice2.isConnected()).thenReturn(false);
+ mMediaDevices.add(mBluetoothMediaDevice1);
+ mMediaDevices.add(mBluetoothMediaDevice2);
+
+ assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
Collections.sort(mMediaDevices, COMPARATOR);
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
}
@@ -178,6 +197,7 @@
Collections.sort(mMediaDevices, COMPARATOR);
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
}
+
@Test
public void compareTo_connectionRecord_sortByRecord() {
mMediaDevices.add(mBluetoothMediaDevice1);
@@ -196,6 +216,25 @@
}
@Test
+ public void compareTo_sortByRecord_connectedDeviceFirst() {
+ mMediaDevices.add(mBluetoothMediaDevice1);
+ mMediaDevices.add(mBluetoothMediaDevice2);
+ when(mCachedDevice2.isConnected()).thenReturn(false);
+
+ mBluetoothMediaDevice1.connect();
+ mBluetoothMediaDevice2.connect();
+ mBluetoothMediaDevice2.connect();
+ // Reset last selected record
+ ConnectionRecordManager.getInstance().setConnectionRecord(mContext, null, 0);
+
+ assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+ assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice2);
+ Collections.sort(mMediaDevices, COMPARATOR);
+ assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+ assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice2);
+ }
+
+ @Test
public void compareTo_info_bluetooth_infoFirst() {
mMediaDevices.add(mBluetoothMediaDevice1);
mMediaDevices.add(mInfoMediaDevice1);
@@ -206,13 +245,13 @@
}
@Test
- public void compareTo_bluetooth_phone_bluetoothFirst() {
- mMediaDevices.add(mPhoneMediaDevice);
+ public void compareTo_bluetooth_phone_phoneFirst() {
mMediaDevices.add(mBluetoothMediaDevice1);
+ mMediaDevices.add(mPhoneMediaDevice);
- assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
- Collections.sort(mMediaDevices, COMPARATOR);
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+ Collections.sort(mMediaDevices, COMPARATOR);
+ assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
}
@Test
@@ -235,6 +274,17 @@
assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
}
+ @Test
+ public void compareTo_sortByAlphabet_connectDeviceFirst() {
+ mMediaDevices.add(mBluetoothMediaDevice2);
+ mMediaDevices.add(mBluetoothMediaDevice1);
+ when(mCachedDevice1.isConnected()).thenReturn(false);
+
+ assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
+ Collections.sort(mMediaDevices, COMPARATOR);
+ assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
+ }
+
// 1.mInfoMediaDevice1: Last Selected device
// 2.mBluetoothMediaDevice1: CarKit device
// 3.mInfoMediaDevice2: * 2 times usage
@@ -242,7 +292,7 @@
// 5.mBluetoothMediaDevice2: * 2 times usage
// 6.mBluetoothMediaDevice3: * 1 time usage
// 7.mPhoneMediaDevice: * 0 time usage
- // Order: 2 -> 1 -> 3 -> 5 -> 4 -> 6 -> 7
+ // Order: 7 -> 2 -> 1 -> 3 -> 5 -> 4 -> 6
@Test
public void compareTo_mixedDevices_carKitFirst() {
when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
@@ -264,13 +314,55 @@
mInfoMediaDevice1.connect();
Collections.sort(mMediaDevices, COMPARATOR);
- assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+ assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
+ assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice1);
+ assertThat(mMediaDevices.get(2)).isEqualTo(mInfoMediaDevice1);
+ assertThat(mMediaDevices.get(3)).isEqualTo(mInfoMediaDevice2);
+ assertThat(mMediaDevices.get(4)).isEqualTo(mBluetoothMediaDevice2);
+ assertThat(mMediaDevices.get(5)).isEqualTo(mInfoMediaDevice3);
+ assertThat(mMediaDevices.get(6)).isEqualTo(mBluetoothMediaDevice3);
+ }
+
+ // 1.mInfoMediaDevice1: Last Selected device
+ // 2.mBluetoothMediaDevice1: CarKit device not connected
+ // 3.mInfoMediaDevice2: * 2 times usage
+ // 4.mInfoMediaDevice3: * 1 time usage
+ // 5.mBluetoothMediaDevice2: * 4 times usage not connected
+ // 6.mBluetoothMediaDevice3: * 1 time usage
+ // 7.mPhoneMediaDevice: * 0 time usage
+ // Order: 7 -> 1 -> 3 -> 4 -> 6 -> 2 -> 5
+ @Test
+ public void compareTo_mixedDevices_connectDeviceFirst() {
+ when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
+ when(mDevice2.getBluetoothClass()).thenReturn(mHeadreeClass);
+ when(mDevice3.getBluetoothClass()).thenReturn(mHeadreeClass);
+ when(mCachedDevice1.isConnected()).thenReturn(false);
+ when(mCachedDevice2.isConnected()).thenReturn(false);
+ mMediaDevices.add(mBluetoothMediaDevice1);
+ mMediaDevices.add(mBluetoothMediaDevice2);
+ mMediaDevices.add(mBluetoothMediaDevice3);
+ mMediaDevices.add(mInfoMediaDevice1);
+ mMediaDevices.add(mInfoMediaDevice2);
+ mMediaDevices.add(mInfoMediaDevice3);
+ mMediaDevices.add(mPhoneMediaDevice);
+ mBluetoothMediaDevice3.connect();
+ mBluetoothMediaDevice2.connect();
+ mBluetoothMediaDevice2.connect();
+ mBluetoothMediaDevice2.connect();
+ mBluetoothMediaDevice2.connect();
+ mInfoMediaDevice3.connect();
+ mInfoMediaDevice2.connect();
+ mInfoMediaDevice2.connect();
+ mInfoMediaDevice1.connect();
+
+ Collections.sort(mMediaDevices, COMPARATOR);
+ assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
assertThat(mMediaDevices.get(1)).isEqualTo(mInfoMediaDevice1);
assertThat(mMediaDevices.get(2)).isEqualTo(mInfoMediaDevice2);
- assertThat(mMediaDevices.get(3)).isEqualTo(mBluetoothMediaDevice2);
- assertThat(mMediaDevices.get(4)).isEqualTo(mInfoMediaDevice3);
- assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice3);
- assertThat(mMediaDevices.get(6)).isEqualTo(mPhoneMediaDevice);
+ assertThat(mMediaDevices.get(3)).isEqualTo(mInfoMediaDevice3);
+ assertThat(mMediaDevices.get(4)).isEqualTo(mBluetoothMediaDevice3);
+ assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice1);
+ assertThat(mMediaDevices.get(6)).isEqualTo(mBluetoothMediaDevice2);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
index 98eccb5..ead2be4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
@@ -111,6 +111,15 @@
}
@Test
+ public void dispatchDataChanged_registerCallback_shouldDispatchCallback() {
+ mMediaManager.registerCallback(mCallback);
+
+ mMediaManager.dispatchDataChanged();
+
+ verify(mCallback).onDeviceAttributesChanged();
+ }
+
+ @Test
public void findMediaDevice_idExist_shouldReturnMediaDevice() {
mMediaManager.mMediaDevices.add(mDevice);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
index 5ba33f5..50a6a9d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
@@ -23,6 +23,7 @@
import android.bluetooth.BluetoothDevice;
import android.content.Context;
+import com.android.settingslib.R;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -97,4 +98,19 @@
assertThat(mPhoneMediaDevice.connect()).isFalse();
}
+
+ @Test
+ public void updateSummary_isActiveIsTrue_returnActiveString() {
+ mPhoneMediaDevice.updateSummary(true);
+
+ assertThat(mPhoneMediaDevice.getSummary())
+ .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
+ }
+
+ @Test
+ public void updateSummary_notActive_returnEmpty() {
+ mPhoneMediaDevice.updateSummary(false);
+
+ assertThat(mPhoneMediaDevice.getSummary()).isEmpty();
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
index 7ef31df..61fdbd5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
@@ -42,6 +42,7 @@
private static final long THIRTY_HOURS_MILLIS = Duration.ofHours(30).toMillis();
private static final String NORMAL_CASE_EXPECTED_PREFIX = "Should last until about";
private static final String ENHANCED_SUFFIX = " based on your usage";
+ private static final String EXTEND_PREFIX = "Extend battery life past";
// matches a time (ex: '1:15 PM', '2 AM', '23:00')
private static final String TIME_OF_DAY_REGEX = " (\\d)+:?(\\d)* ((AM)*)|((PM)*)";
// matches a percentage with parenthesis (ex: '(10%)')
@@ -176,6 +177,24 @@
}
@Test
+ public void getBatteryTipStringFormatted_moreThanOneDay_usesCorrectString() {
+ String info = PowerUtil.getBatteryTipStringFormatted(mContext,
+ THREE_DAYS_MILLIS);
+
+ assertThat(info).isEqualTo("More than 3 days remaining");
+ }
+
+ @Test
+ public void getBatteryTipStringFormatted_lessThanOneDay_usesCorrectString() {
+ String info = PowerUtil.getBatteryTipStringFormatted(mContext,
+ SEVENTEEN_MIN_MILLIS);
+
+ // ex: Extend battery life past 1:15 PM
+ assertThat(info).containsMatch(Pattern.compile(
+ EXTEND_PREFIX + TIME_OF_DAY_REGEX));
+ }
+
+ @Test
public void testRoundToNearestThreshold_roundsCorrectly() {
// test some pretty normal values
assertThat(PowerUtil.roundTimeToNearestThreshold(1200, 1000)).isEqualTo(1000);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 2d5606c..a33f9a8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1919,6 +1919,36 @@
dumpSetting(s, p,
Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED,
SecureSettingsProto.ENHANCED_VOICE_PRIVACY_ENABLED);
+
+ final long gestureToken = p.start(SecureSettingsProto.GESTURE);
+ dumpSetting(s, p,
+ Settings.Secure.AWARE_ENABLED,
+ SecureSettingsProto.Gesture.AWARE_ENABLED);
+
+ dumpSetting(s, p,
+ Settings.Secure.SILENCE_ALARMS_GESTURE_COUNT,
+ SecureSettingsProto.Gesture.SILENCE_ALARMS_COUNT);
+ dumpSetting(s, p,
+ Settings.Secure.SILENCE_CALL_GESTURE_COUNT,
+ SecureSettingsProto.Gesture.SILENCE_CALLS_COUNT);
+ dumpSetting(s, p,
+ Settings.Secure.SILENCE_GESTURE,
+ SecureSettingsProto.Gesture.SILENCE_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.SILENCE_NOTIFICATION_GESTURE_COUNT,
+ SecureSettingsProto.Gesture.SILENCE_NOTIFICATION_COUNT);
+ dumpSetting(s, p,
+ Settings.Secure.SILENCE_TIMER_GESTURE_COUNT,
+ SecureSettingsProto.Gesture.SILENCE_TIMER_COUNT);
+
+ dumpSetting(s, p,
+ Settings.Secure.SKIP_GESTURE_COUNT,
+ SecureSettingsProto.Gesture.SKIP_COUNT);
+ dumpSetting(s, p,
+ Settings.Secure.SKIP_GESTURE,
+ SecureSettingsProto.Gesture.SKIP_ENABLED);
+ p.end(gestureToken);
+
dumpSetting(s, p,
Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
SecureSettingsProto.IMMERSIVE_MODE_CONFIRMATIONS);
@@ -2284,6 +2314,9 @@
Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
SecureSettingsProto.SYSTEM_NAVIGATION_KEYS_ENABLED);
dumpSetting(s, p,
+ Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
+ SecureSettingsProto.THEME_CUSTOMIZATION_OVERLAY_PACKAGES);
+ dumpSetting(s, p,
Settings.Secure.TRUST_AGENTS_INITIALIZED,
SecureSettingsProto.TRUST_AGENTS_INITIALIZED);
@@ -2401,22 +2434,6 @@
SecureSettingsProto.Zen.SETTINGS_SUGGESTION_VIEWED);
p.end(zenToken);
- dumpSetting(s, p,
- Settings.Secure.SKIP_GESTURE,
- SecureSettingsProto.SKIP_GESTURE_ENABLED);
-
- dumpSetting(s, p,
- Settings.Secure.SILENCE_GESTURE,
- SecureSettingsProto.SILENCE_GESTURE_ENABLED);
-
- dumpSetting(s, p,
- Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
- SecureSettingsProto.THEME_CUSTOMIZATION_OVERLAY_PACKAGES);
-
- dumpSetting(s, p,
- Settings.Secure.AWARE_ENABLED,
- SecureSettingsProto.AWARE_ENABLED);
-
// Please insert new settings using the same order as in SecureSettingsProto.
p.end(token);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9d6fc9ed..6df6c73 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -135,6 +135,7 @@
<uses-permission android:name="android.permission.MANAGE_BIOMETRIC" />
<uses-permission android:name="android.permission.MANAGE_SLICE_PERMISSIONS" />
<uses-permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS" />
+ <uses-permission android:name="android.permission.GET_RUNTIME_PERMISSIONS" />
<!-- Needed for WallpaperManager.clear in ImageWallpaper.updateWallpaperLocked -->
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
diff --git a/packages/SystemUI/res-keyguard/layout/type_clock.xml b/packages/SystemUI/res-keyguard/layout/type_aod_clock.xml
similarity index 73%
rename from packages/SystemUI/res-keyguard/layout/type_clock.xml
rename to packages/SystemUI/res-keyguard/layout/type_aod_clock.xml
index 89bbc09..28ff5a2 100644
--- a/packages/SystemUI/res-keyguard/layout/type_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/type_aod_clock.xml
@@ -19,13 +19,5 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <com.android.keyguard.clock.TypographicClock
- android:id="@+id/type_clock"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="50dp"
- android:textAlignment="viewStart"
- style="@style/widget_big"
- android:textSize="40dp"
- />
+ <include layout="@layout/typographic_clock" />
</com.android.keyguard.clock.ClockLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/type_clock.xml b/packages/SystemUI/res-keyguard/layout/typographic_clock.xml
similarity index 63%
copy from packages/SystemUI/res-keyguard/layout/type_clock.xml
copy to packages/SystemUI/res-keyguard/layout/typographic_clock.xml
index 89bbc09..73bb4b9 100644
--- a/packages/SystemUI/res-keyguard/layout/type_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/typographic_clock.xml
@@ -14,18 +14,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.keyguard.clock.ClockLayout
+<com.android.keyguard.clock.TypographicClock
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/type_clock"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- <com.android.keyguard.clock.TypographicClock
- android:id="@+id/type_clock"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="50dp"
- android:textAlignment="viewStart"
- style="@style/widget_big"
- android:textSize="40dp"
- />
-</com.android.keyguard.clock.ClockLayout>
+ android:layout_height="wrap_content"
+ android:paddingStart="50dp"
+ android:textAlignment="viewStart"
+ style="@style/widget_big"
+ android:textSize="40dp"
+ />
diff --git a/packages/SystemUI/res/drawable/ic_media_projection_permission.xml b/packages/SystemUI/res/drawable/ic_media_projection_permission.xml
new file mode 100644
index 0000000..f46d137
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_media_projection_permission.xml
@@ -0,0 +1,26 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="2.5dp"
+ android:insetRight="2.5dp">
+ <vector android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path android:fillColor="#FF000000" android:pathData="M1,18v3h3C4,19.34 2.66,18 1,18zM1,14v2c2.76,0 5,2.24 5,5h2C8,17.13 4.87,14 1,14zM1,10v2c4.97,0 9,4.03 9,9h2C12,14.92 7.07,10 1,10zM21,3H3C1.9,3 1,3.9 1,5v3h2V5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2V5C23,3.9 22.1,3 21,3z"/>
+ <path android:fillColor="#FF0000" android:pathData="M19,7H5v1.63c3.96,1.28 7.09,4.41 8.37,8.37H19V7z"/>
+ </vector>
+</inset>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item.xml b/packages/SystemUI/res/layout/global_actions_grid_item.xml
index 5dee09d..999c7b8 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item.xml
@@ -35,7 +35,7 @@
android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
- android:scaleType="center"
+ android:scaleType="centerInside"
android:alpha="?android:attr/primaryContentAlpha"
/>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index d4957c9..adc0b41 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -83,7 +83,7 @@
android:layout_height="@dimen/keyguard_lock_height"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="@dimen/keyguard_lock_padding"
- android:src="@*android:drawable/ic_lock_24dp"
+ android:src="@*android:drawable/ic_lock"
android:contentDescription="@string/accessibility_unlock_button"
android:scaleType="center" />
diff --git a/packages/SystemUI/res/values-sw392dp-land/dimens.xml b/packages/SystemUI/res/values-sw392dp-land/dimens.xml
new file mode 100644
index 0000000..c718614
--- /dev/null
+++ b/packages/SystemUI/res/values-sw392dp-land/dimens.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_vertical_padding">3dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">0dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">6dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">10dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw392dp/dimens.xml b/packages/SystemUI/res/values-sw392dp/dimens.xml
new file mode 100644
index 0000000..6fa6692
--- /dev/null
+++ b/packages/SystemUI/res/values-sw392dp/dimens.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_container_bottom_margin">4dp</dimen>
+
+ <dimen name="global_actions_grid_vertical_padding">0dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">3dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">10dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">6dp</dimen>
+ <dimen name="global_actions_grid_item_width">72dp</dimen>
+ <dimen name="global_actions_grid_item_height">72dp</dimen>
+
+ <dimen name="global_actions_grid_item_icon_width">22dp</dimen>
+ <dimen name="global_actions_grid_item_icon_height">22dp</dimen>
+ <dimen name="global_actions_grid_item_icon_top_margin">12dp</dimen>
+ <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
+ <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 121cdd8..33e1974 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -40,6 +40,9 @@
<!-- Whether or not we show the number in the bar. -->
<bool name="config_statusBarShowNumber">false</bool>
+ <!-- If the lock screen should be dismissed after biometric auth. -->
+ <bool name="config_faceAuthDismissesKeyguard">false</bool>
+
<!-- Vibrator pattern for camera gesture launch. -->
<integer-array translatable="false" name="config_cameraLaunchGestureVibePattern">
<item>0</item>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4457440..c83cb59 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -677,9 +677,9 @@
<dimen name="keyguard_affordance_width">56dp</dimen>
<!-- The width/height of the unlock icon view on keyguard. -->
- <dimen name="keyguard_lock_height">32dp</dimen>
- <dimen name="keyguard_lock_width">32dp</dimen>
- <dimen name="keyguard_lock_padding">24dp</dimen>
+ <dimen name="keyguard_lock_height">42dp</dimen>
+ <dimen name="keyguard_lock_width">42dp</dimen>
+ <dimen name="keyguard_lock_padding">19dp</dimen>
<dimen name="keyguard_indication_margin_bottom">65dp</dimen>
@@ -872,9 +872,6 @@
<!-- Global actions grid layout -->
<dimen name="global_actions_grid_side_margin">4dp</dimen>
- <!-- Global actions panel -->
- <dimen name="global_actions_panel_top_margin">85dp</dimen>
-
<!-- The maximum offset in either direction that elements are moved horizontally to prevent
burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_x">8dp</dimen>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b985b6b..4adece9 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -287,7 +287,6 @@
<item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
<item name="passwordStyle">@style/PasswordTheme</item>
<item name="backgroundProtectedStyle">@style/BackgroundProtectedStyle</item>
- <item name="android:forceDarkAllowed">false</item>
<!-- Needed for MediaRoute chooser dialog -->
<item name="*android:isLightTheme">false</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 10996e88..794c30a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -217,4 +217,11 @@
WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
DEFAULT_DISPLAY, mPinnedStackListenerForwarder);
}
+
+ /**
+ * Removes a pinned stack listener.
+ */
+ public void removePinnedStackListener(IPinnedStackListener listener) {
+ mPinnedStackListenerForwarder.removeListener(listener);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
index 4d8cf96..59ee267 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
@@ -76,8 +76,10 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- final float offsetX = getBurnInOffset(mBurnInPreventionOffsetX, true);
- final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY, false);
+ final float offsetX = getBurnInOffset(mBurnInPreventionOffsetX * 2, true)
+ - mBurnInPreventionOffsetX;
+ final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY * 2, false)
+ - mBurnInPreventionOffsetY;
// Put digital clock in two left corner of the screen.
if (mDigitalClock != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
index 69f86c7..387f265 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
@@ -51,7 +51,7 @@
/**
* Small clock shown on lock screen above stack scroller.
*/
- private View mLockClockContainer;
+ private TypographicClock mLockClock;
/**
* Controller for transition into dark state.
@@ -69,13 +69,15 @@
}
private void createViews() {
- mView = mLayoutInflater.inflate(R.layout.type_clock, null);
+ mView = mLayoutInflater.inflate(R.layout.type_aod_clock, null);
mTypeClock = mView.findViewById(R.id.type_clock);
// For now, this view is used to hide the default digital clock.
// Need better transition to lock screen.
- mLockClockContainer = mLayoutInflater.inflate(R.layout.digital_clock, null);
- mLockClockContainer.setVisibility(View.GONE);
+ mLockClock = (TypographicClock) mLayoutInflater.inflate(R.layout.typographic_clock, null);
+ mLockClock.setVisibility(View.GONE);
+
+ mDarkController = new CrossFadeDarkController(mView, mLockClock);
}
@Override
@@ -95,10 +97,10 @@
@Override
public View getView() {
- if (mLockClockContainer == null) {
+ if (mLockClock == null) {
createViews();
}
- return mLockClockContainer;
+ return mLockClock;
}
@Override
@@ -115,6 +117,7 @@
@Override
public void setTextColor(int color) {
mTypeClock.setTextColor(color);
+ mLockClock.setTextColor(color);
}
@Override
@@ -122,21 +125,28 @@
if (colorPalette == null || colorPalette.length == 0) {
return;
}
- final int length = colorPalette.length;
- mTypeClock.setClockColor(colorPalette[Math.max(0, length - 5)]);
+ final int color = colorPalette[Math.max(0, colorPalette.length - 5)];
+ mTypeClock.setClockColor(color);
+ mLockClock.setClockColor(color);
}
@Override
public void onTimeTick() {
mTypeClock.onTimeChanged();
+ mLockClock.onTimeChanged();
}
@Override
- public void setDarkAmount(float darkAmount) {}
+ public void setDarkAmount(float darkAmount) {
+ if (mDarkController != null) {
+ mDarkController.setDarkAmount(darkAmount);
+ }
+ }
@Override
public void onTimeZoneChanged(TimeZone timeZone) {
mTypeClock.onTimeZoneChanged(timeZone);
+ mLockClock.onTimeZoneChanged(timeZone);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
index 7bce3c5..572ab30 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
@@ -119,4 +119,12 @@
mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
onTimeChanged();
}
+
+ /**
+ * Overriding hasOverlappingRendering as false to improve performance of crossfading.
+ */
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index c013df3..ace086f 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -20,6 +20,7 @@
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
@@ -203,26 +204,37 @@
}
/**
+ * Does the app-op item refer to a user sensitive permission. Only user sensitive permission
+ * should be shown to the user by default.
+ *
+ * @param item The item
+ *
+ * @return {@code true} iff the app-op item is user sensitive
+ */
+ private boolean isUserSensitive(AppOpItem item) {
+ String permission = AppOpsManager.opToPermission(item.getCode());
+ if (permission == null) {
+ return false;
+ }
+ int permFlags = mContext.getPackageManager().getPermissionFlags(permission,
+ item.getPackageName(), UserHandle.getUserHandleForUid(item.getUid()));
+ return (permFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0;
+ }
+
+ /**
* Returns a copy of the list containing all the active AppOps that the controller tracks.
*
* @return List of active AppOps information
*/
public List<AppOpItem> getActiveAppOps() {
- ArrayList<AppOpItem> active;
- synchronized (mActiveItems) {
- active = new ArrayList<>(mActiveItems);
- }
- synchronized (mNotedItems) {
- active.addAll(mNotedItems);
- }
- return active;
+ return getActiveAppOpsForUser(UserHandle.USER_ALL);
}
/**
* Returns a copy of the list containing all the active AppOps that the controller tracks, for
* a given user id.
*
- * @param userId User id to track
+ * @param userId User id to track, can be {@link UserHandle#USER_ALL}
*
* @return List of active AppOps information for that user id
*/
@@ -232,7 +244,8 @@
final int numActiveItems = mActiveItems.size();
for (int i = 0; i < numActiveItems; i++) {
AppOpItem item = mActiveItems.get(i);
- if (UserHandle.getUserId(item.getUid()) == userId) {
+ if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId)
+ && isUserSensitive(item)) {
list.add(item);
}
}
@@ -241,7 +254,8 @@
final int numNotedItems = mNotedItems.size();
for (int i = 0; i < numNotedItems; i++) {
AppOpItem item = mNotedItems.get(i);
- if (UserHandle.getUserId(item.getUid()) == userId) {
+ if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId)
+ && isUserSensitive(item)) {
list.add(item);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 03e453f..eb85589 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -23,8 +23,9 @@
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.notification.NotificationAlertingManager.alertAgain;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
@@ -43,6 +44,7 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import androidx.annotation.IntDef;
import androidx.annotation.MainThread;
import com.android.internal.annotations.VisibleForTesting;
@@ -60,7 +62,7 @@
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import java.util.List;
+import java.lang.annotation.Retention;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -73,10 +75,22 @@
*/
@Singleton
public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener {
- private static final int MAX_BUBBLES = 5; // TODO: actually enforce this
private static final String TAG = "BubbleController";
+ private static final int MAX_BUBBLES = 5; // TODO: actually enforce this
+
+ @Retention(SOURCE)
+ @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
+ DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION})
+ @interface DismissReason {}
+ static final int DISMISS_USER_GESTURE = 1;
+ static final int DISMISS_AGED = 2;
+ static final int DISMISS_TASK_FINISHED = 3;
+ static final int DISMISS_BLOCKED = 4;
+ static final int DISMISS_NOTIF_CANCEL = 5;
+ static final int DISMISS_ACCESSIBILITY_ACTION = 6;
+
// Enables some subset of notifs to automatically become bubbles
private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
@@ -251,11 +265,11 @@
/**
* Tell the stack of bubbles to be dismissed, this will remove all of the bubbles in the stack.
*/
- void dismissStack() {
+ void dismissStack(@DismissReason int reason) {
if (mStackView == null) {
return;
}
- mStackView.stackDismissed();
+ mStackView.stackDismissed(reason);
updateVisibility();
mNotificationEntryManager.updateNotifications();
@@ -307,9 +321,9 @@
* Must be called from the main thread.
*/
@MainThread
- void removeBubble(String key) {
+ void removeBubble(String key, int reason) {
if (mStackView != null) {
- mStackView.removeBubble(key);
+ mStackView.removeBubble(key, reason);
}
mNotificationEntryManager.updateNotifications();
updateVisibility();
@@ -323,7 +337,7 @@
boolean samePackage = entry.notification.getPackageName().equals(
e.notification.getPackageName());
if (samePackage) {
- removeBubble(entry.key);
+ removeBubble(entry.key, DISMISS_BLOCKED);
}
}
}
@@ -380,7 +394,7 @@
}
if (!removedByUser) {
// This was a cancel so we should remove the bubble
- removeBubble(entry.key);
+ removeBubble(entry.key, DISMISS_NOTIF_CANCEL);
}
}
};
@@ -491,24 +505,6 @@
@MainThread
private class BubbleTaskStackListener extends TaskStackChangeListener {
- @Nullable
- private ActivityManager.StackInfo findStackInfo(int taskId) throws RemoteException {
- final List<ActivityManager.StackInfo> stackInfoList =
- mActivityTaskManager.getAllStackInfos();
- // Iterate through stacks from top to bottom.
- final int stackCount = stackInfoList.size();
- for (int stackIndex = 0; stackIndex < stackCount; stackIndex++) {
- final ActivityManager.StackInfo stackInfo = stackInfoList.get(stackIndex);
- // Iterate through tasks from top to bottom.
- for (int taskIndex = stackInfo.taskIds.length - 1; taskIndex >= 0; taskIndex--) {
- if (stackInfo.taskIds[taskIndex] == taskId) {
- return stackInfo;
- }
- }
- }
- return null;
- }
-
@Override
public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
if (mStackView != null && taskInfo.displayId == Display.DEFAULT_DISPLAY) {
@@ -516,15 +512,8 @@
}
}
- /**
- * This is a workaround for the case when the activity had to be created in a new task.
- * Existing code in ActivityStackSupervisor checks the display where the activity
- * ultimately ended up, displays an error message toast, and calls this method instead of
- * onTaskMovedToFront.
- */
@Override
- public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) {
- // TODO(b/124058588): move to ActivityView.StateCallback, filter on virtualDisplay ID
+ public void onActivityLaunchOnSecondaryDisplayRerouted() {
if (mStackView != null) {
mStackView.collapseStack();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 25ee87a..856b9d6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -135,7 +135,8 @@
public void onTaskRemovalStarted(int taskId) {
if (mEntry != null) {
// Must post because this is called from a binder thread.
- post(() -> mBubbleController.removeBubble(mEntry.key));
+ post(() -> mBubbleController.removeBubble(mEntry.key,
+ BubbleController.DISMISS_TASK_FINISHED));
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 97aa786..888e3fe 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -19,6 +19,8 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import android.app.Notification;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
@@ -49,6 +51,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.R;
+import com.android.systemui.bubbles.BubbleController.DismissReason;
import com.android.systemui.bubbles.animation.ExpandedAnimationController;
import com.android.systemui.bubbles.animation.PhysicsAnimationLayout;
import com.android.systemui.bubbles.animation.StackAnimationController;
@@ -62,26 +65,7 @@
*/
public class BubbleStackView extends FrameLayout {
private static final String TAG = "BubbleStackView";
-
- /**
- * Friction applied to fling animations. Since the stack must land on one of the sides of the
- * screen, we want less friction horizontally so that the stack has a better chance of making it
- * to the side without needing a spring.
- */
- private static final float FLING_FRICTION_X = 1.15f;
- private static final float FLING_FRICTION_Y = 1.5f;
-
- /**
- * Damping ratio to use for the stack spring animation used to spring the stack to its final
- * position after a fling.
- */
- private static final float SPRING_DAMPING_RATIO = 0.85f;
-
- /**
- * Minimum fling velocity required to trigger moving the stack from one side of the screen to
- * the other.
- */
- private static final float ESCAPE_VELOCITY = 750f;
+ private static final boolean DEBUG = false;
private Point mDisplaySize;
@@ -252,7 +236,7 @@
}
switch (action) {
case AccessibilityNodeInfo.ACTION_DISMISS:
- stackDismissed();
+ stackDismissed(BubbleController.DISMISS_ACCESSIBILITY_ACTION);
return true;
case AccessibilityNodeInfo.ACTION_COLLAPSE:
collapseStack();
@@ -376,18 +360,12 @@
/**
* Remove a bubble from the stack.
*/
- public void removeBubble(String key) {
+ public void removeBubble(String key, int reason) {
Bubble b = mBubbleData.removeBubble(key);
if (b == null) {
return;
}
- b.entry.setBubbleDismissed(true);
-
- // Remove it from the views
- int removedIndex = mBubbleContainer.indexOfChild(b.iconView);
- b.expandedView.cleanUpExpandedState();
- mBubbleContainer.removeView(b.iconView);
-
+ int removedIndex = dismissBubble(b, reason);
int bubbleCount = mBubbleContainer.getChildCount();
if (bubbleCount == 0) {
// If no bubbles remain, collapse the entire stack.
@@ -405,26 +383,63 @@
mExpandedBubble = null;
}
}
+ // TODO: consider logging reason code
logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
}
/**
* Dismiss the stack of bubbles.
*/
- public void stackDismissed() {
+ public void stackDismissed(int reason) {
for (Bubble bubble : mBubbleData.getBubbles()) {
- bubble.entry.setBubbleDismissed(true);
- bubble.expandedView.cleanUpExpandedState();
+ dismissBubble(bubble, reason);
}
mBubbleData.clear();
collapseStack();
mBubbleContainer.removeAllViews();
mExpandedViewContainer.removeAllViews();
+ // TODO: consider logging reason code
logBubbleEvent(null /* no bubble associated with bubble stack dismiss */,
StatsLog.BUBBLE_UICHANGED__ACTION__STACK_DISMISSED);
}
/**
+ * Marks the notification entry as dismissed, cleans up Bubble icon and expanded view UI
+ * elements and calls deleteIntent if necessary.
+ *
+ * <p>Note: This does not remove the Bubble from BubbleData.
+ *
+ * @param bubble the Bubble being dismissed
+ * @param reason code for the reason the dismiss was triggered
+ * @see BubbleController.DismissReason
+ */
+ private int dismissBubble(Bubble bubble, @DismissReason int reason) {
+ if (DEBUG) {
+ Log.d(TAG, "dismissBubble: " + bubble + " reason=" + reason);
+ }
+ bubble.entry.setBubbleDismissed(true);
+ bubble.expandedView.cleanUpExpandedState();
+
+ // Remove it from the views
+ int removedIndex = mBubbleContainer.indexOfChild(bubble.iconView);
+ mBubbleContainer.removeViewAt(removedIndex);
+
+ if (reason == BubbleController.DISMISS_USER_GESTURE) {
+ Notification.BubbleMetadata bubbleMetadata = bubble.entry.getBubbleMetadata();
+ PendingIntent deleteIntent = bubbleMetadata.getDeleteIntent();
+ if (deleteIntent != null) {
+ try {
+ deleteIntent.send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.w(TAG, "Failed to send delete intent for bubble with key: "
+ + (bubble.entry != null ? bubble.entry.key : " null entry"));
+ }
+ }
+ }
+ return removedIndex;
+ }
+
+ /**
* Updates a bubble in the stack.
*
* @param entry the entry to update in the stack.
@@ -653,50 +668,7 @@
return;
}
- final boolean stackOnLeftSide = x
- - mBubbleContainer.getChildAt(0).getWidth() / 2
- < mDisplaySize.x / 2;
-
- final boolean stackShouldFlingLeft = stackOnLeftSide
- ? velX < ESCAPE_VELOCITY
- : velX < -ESCAPE_VELOCITY;
-
- final RectF stackBounds = mStackAnimationController.getAllowableStackPositionRegion();
-
- // Target X translation (either the left or right side of the screen).
- final float destinationRelativeX = stackShouldFlingLeft
- ? stackBounds.left : stackBounds.right;
-
- // Minimum velocity required for the stack to make it to the side of the screen.
- final float escapeVelocity = getMinXVelocity(
- x,
- destinationRelativeX,
- FLING_FRICTION_X);
-
- // Use the touch event's velocity if it's sufficient, otherwise use the minimum velocity so
- // that it'll make it all the way to the side of the screen.
- final float startXVelocity = stackShouldFlingLeft
- ? Math.min(escapeVelocity, velX)
- : Math.max(escapeVelocity, velX);
-
- mStackAnimationController.flingThenSpringFirstBubbleWithStackFollowing(
- DynamicAnimation.TRANSLATION_X,
- startXVelocity,
- FLING_FRICTION_X,
- new SpringForce()
- .setStiffness(SpringForce.STIFFNESS_LOW)
- .setDampingRatio(SPRING_DAMPING_RATIO),
- destinationRelativeX);
-
- mStackAnimationController.flingThenSpringFirstBubbleWithStackFollowing(
- DynamicAnimation.TRANSLATION_Y,
- velY,
- FLING_FRICTION_Y,
- new SpringForce()
- .setStiffness(SpringForce.STIFFNESS_LOW)
- .setDampingRatio(SPRING_DAMPING_RATIO),
- /* destination */ null);
-
+ mStackAnimationController.flingStackThenSpringToEdge(x, velX, velY);
logBubbleEvent(null /* no bubble associated with bubble stack move */,
StatsLog.BUBBLE_UICHANGED__ACTION__STACK_MOVED);
}
@@ -741,20 +713,6 @@
}
}
- /**
- * Minimum velocity, in pixels/second, required to get from x to destX while being slowed by a
- * given frictional force.
- *
- * This is not derived using real math, I just made it up because the math in FlingAnimation
- * looks hard and this seems to work. It doesn't actually matter because if it doesn't make it
- * to the edge via Fling, it'll get Spring'd there anyway.
- *
- * TODO(tsuji, or someone who likes math): Figure out math.
- */
- private float getMinXVelocity(float x, float destX, float friction) {
- return (destX - x) * (friction * 5) + ESCAPE_VELOCITY;
- }
-
@Override
public void getBoundsOnScreen(Rect outRect) {
if (!mIsExpanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index c8eebac..a7170d0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -140,7 +140,7 @@
case MotionEvent.ACTION_UP:
trackMovement(event);
if (mInDismissTarget && isStack) {
- mController.dismissStack();
+ mController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
} else if (mMovedEnough) {
mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000);
final float velX = mVelocityTracker.getXVelocity();
@@ -152,7 +152,8 @@
mStack.onBubbleDragFinish(
mTouchedView, viewX, viewY, velX, velY, /* dismissed */ dismissed);
if (dismissed) {
- mController.removeBubble(((BubbleView) mTouchedView).getKey());
+ mController.removeBubble(((BubbleView) mTouchedView).getKey(),
+ BubbleController.DISMISS_USER_GESTURE);
}
}
} else if (mTouchedView == mStack.getExpandedBubbleView()) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index af5035b..3c4bc72 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -61,12 +61,35 @@
private static final float DEFAULT_BOUNCINESS = 0.85f;
/**
+ * Friction applied to fling animations. Since the stack must land on one of the sides of the
+ * screen, we want less friction horizontally so that the stack has a better chance of making it
+ * to the side without needing a spring.
+ */
+ private static final float FLING_FRICTION_X = 1.15f;
+ private static final float FLING_FRICTION_Y = 1.5f;
+
+ /**
+ * Damping ratio to use for the stack spring animation used to spring the stack to its final
+ * position after a fling.
+ */
+ private static final float SPRING_DAMPING_RATIO = 0.85f;
+
+ /**
+ * Minimum fling velocity required to trigger moving the stack from one side of the screen to
+ * the other.
+ */
+ private static final float ESCAPE_VELOCITY = 750f;
+
+ /**
* The canonical position of the stack. This is typically the position of the first bubble, but
* we need to keep track of it separately from the first bubble's translation in case there are
* no bubbles, or the first bubble was just added and being animated to its new position.
*/
private PointF mStackPosition = new PointF();
+ /** The most recent position in which the stack was resting on the edge of the screen. */
+ private PointF mRestingStackPosition;
+
/** The height of the most recently visible IME. */
private float mImeHeight = 0f;
@@ -135,6 +158,65 @@
}
/**
+ * Flings the stack starting with the given velocities, springing it to the nearest edge
+ * afterward.
+ */
+ public void flingStackThenSpringToEdge(float x, float velX, float velY) {
+ final boolean stackOnLeftSide = x - mIndividualBubbleSize / 2 < mLayout.getWidth() / 2;
+
+ final boolean stackShouldFlingLeft = stackOnLeftSide
+ ? velX < ESCAPE_VELOCITY
+ : velX < -ESCAPE_VELOCITY;
+
+ final RectF stackBounds = getAllowableStackPositionRegion();
+
+ // Target X translation (either the left or right side of the screen).
+ final float destinationRelativeX = stackShouldFlingLeft
+ ? stackBounds.left : stackBounds.right;
+
+ // Minimum velocity required for the stack to make it to the targeted side of the screen,
+ // taking friction into account (4.2f is the number that friction scalars are multiplied by
+ // in DynamicAnimation.DragForce). This is an estimate - it could possibly be slightly off,
+ // but the SpringAnimation at the end will ensure that it reaches the destination X
+ // regardless.
+ final float minimumVelocityToReachEdge =
+ (destinationRelativeX - x) * (FLING_FRICTION_X * 4.2f);
+
+ // Use the touch event's velocity if it's sufficient, otherwise use the minimum velocity so
+ // that it'll make it all the way to the side of the screen.
+ final float startXVelocity = stackShouldFlingLeft
+ ? Math.min(minimumVelocityToReachEdge, velX)
+ : Math.max(minimumVelocityToReachEdge, velX);
+
+ flingThenSpringFirstBubbleWithStackFollowing(
+ DynamicAnimation.TRANSLATION_X,
+ startXVelocity,
+ FLING_FRICTION_X,
+ new SpringForce()
+ .setStiffness(SpringForce.STIFFNESS_LOW)
+ .setDampingRatio(SPRING_DAMPING_RATIO),
+ destinationRelativeX);
+
+ flingThenSpringFirstBubbleWithStackFollowing(
+ DynamicAnimation.TRANSLATION_Y,
+ velY,
+ FLING_FRICTION_Y,
+ new SpringForce()
+ .setStiffness(SpringForce.STIFFNESS_LOW)
+ .setDampingRatio(SPRING_DAMPING_RATIO),
+ /* destination */ null);
+
+ mLayout.setEndListenerForProperties(
+ (animation, canceled, value, velocity) -> {
+ mRestingStackPosition = new PointF();
+ mRestingStackPosition.set(mStackPosition);
+ mLayout.removeEndListenerForProperty(DynamicAnimation.TRANSLATION_X);
+ mLayout.removeEndListenerForProperty(DynamicAnimation.TRANSLATION_Y);
+ },
+ DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ }
+
+ /**
* Where the stack would be if it were snapped to the nearest horizontal edge (left or right).
*/
public PointF getStackPositionAlongNearestHorizontalEdge() {
@@ -152,7 +234,7 @@
* reducing momentum - a SpringAnimation takes over to snap the bubble to the given final
* position.
*/
- public void flingThenSpringFirstBubbleWithStackFollowing(
+ protected void flingThenSpringFirstBubbleWithStackFollowing(
DynamicAnimation.ViewProperty property,
float vel,
float friction,
@@ -341,7 +423,7 @@
.setDampingRatio(BubbleController.getBubbleBounciness(
mLayout.getContext(), DEFAULT_BOUNCINESS))
.setStiffness(BubbleController.getBubbleStiffness(
- mLayout.getContext(), (int) (DEFAULT_STIFFNESS * 100f)));
+ mLayout.getContext(), (int) DEFAULT_STIFFNESS));
}
@Override
@@ -360,8 +442,7 @@
@Override
void onChildRemoved(View child, int index, Runnable finishRemoval) {
// Animate the child out, actually removing it once its alpha is zero.
- mLayout.animateValueForChild(
- DynamicAnimation.ALPHA, child, 0f, finishRemoval);
+ mLayout.animateValueForChild(DynamicAnimation.ALPHA, child, 0f, finishRemoval);
mLayout.animateValueForChild(DynamicAnimation.SCALE_X, child, ANIMATE_IN_STARTING_SCALE);
mLayout.animateValueForChild(DynamicAnimation.SCALE_Y, child, ANIMATE_IN_STARTING_SCALE);
@@ -378,10 +459,13 @@
/** Moves the stack, without any animation, to the starting position. */
private void moveStackToStartPosition(Runnable after) {
// Post to ensure that the layout's width and height have been calculated.
+ mLayout.setVisibility(View.INVISIBLE);
mLayout.post(() -> {
setStackPosition(
- getAllowableStackPositionRegion().right,
- getAllowableStackPositionRegion().top + mStackStartingVerticalOffset);
+ mRestingStackPosition == null
+ ? getDefaultStartPosition()
+ : mRestingStackPosition);
+ mLayout.setVisibility(View.VISIBLE);
after.run();
});
}
@@ -410,9 +494,9 @@
}
/** Moves the stack to a position instantly, with no animation. */
- private void setStackPosition(float x, float y) {
- Log.d(TAG, String.format("Setting position to (%f, %f).", x, y));
- mStackPosition.set(x, y);
+ private void setStackPosition(PointF pos) {
+ Log.d(TAG, String.format("Setting position to (%f, %f).", pos.x, pos.y));
+ mStackPosition.set(pos.x, pos.y);
cancelStackPositionAnimations();
@@ -420,11 +504,18 @@
final float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
final float yOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_Y);
for (int i = 0; i < mLayout.getChildCount(); i++) {
- mLayout.getChildAt(i).setTranslationX(x + (i * xOffset));
- mLayout.getChildAt(i).setTranslationY(y + (i * yOffset));
+ mLayout.getChildAt(i).setTranslationX(pos.x + (i * xOffset));
+ mLayout.getChildAt(i).setTranslationY(pos.y + (i * yOffset));
}
}
+ /** Returns the default stack position, which is on the top right. */
+ private PointF getDefaultStartPosition() {
+ return new PointF(
+ getAllowableStackPositionRegion().right,
+ getAllowableStackPositionRegion().top + mStackStartingVerticalOffset);
+ }
+
/** Animates in the given bubble. */
private void animateInBubble(View child) {
child.setTranslationY(mStackPosition.y);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index c3d4b0f..847182d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -39,7 +39,6 @@
*/
public class DozeUi implements DozeMachine.Part {
- private static final String TAG = "DozeUi";
private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
private final Context mContext;
private final DozeHost mHost;
@@ -94,11 +93,13 @@
new DozeHost.PulseCallback() {
@Override
public void onPulseStarted() {
- if (mMachine.getState() != DozeMachine.State.DOZE_REQUEST_PULSE) {
- Log.w(TAG, "Pulse was cancelled before it could have been started");
- return;
+ try {
+ mMachine.requestState(DozeMachine.State.DOZE_PULSING);
+ } catch (IllegalStateException e) {
+ // It's possible that the pulse was asynchronously cancelled while
+ // we were waiting for it to start (under stress conditions.)
+ // In those cases we should just ignore it. b/127657926
}
- mMachine.requestState(DozeMachine.State.DOZE_PULSING);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 3273253..b07f909 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -89,6 +89,7 @@
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
+import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.ExtensionController.Extension;
@@ -1533,7 +1534,7 @@
View panelView = initializePanel();
if (panelView == null) {
mBackgroundDrawable = new GradientDrawable(context);
- mScrimAlpha = 0.7f;
+ mScrimAlpha = ScrimController.GRADIENT_SCRIM_ALPHA;
} else {
mBackgroundDrawable = context.getDrawable(
com.android.systemui.R.drawable.global_action_panel_scrim);
@@ -1556,8 +1557,6 @@
new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
- panelParams.topMargin = mContext.getResources().getDimensionPixelSize(
- com.android.systemui.R.dimen.global_actions_panel_top_margin);
panelContainer.addView(panelView, panelParams);
return panelContainer;
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
index c6b5377..6c106df 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
@@ -40,8 +40,6 @@
public class ListGridLayout extends LinearLayout {
private static final String TAG = "ListGridLayout";
private int mExpectedCount;
- private int mRows;
- private int mColumns;
public ListGridLayout(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -63,7 +61,7 @@
* Get the parent view associated with the item which should be placed at the given position.
*/
public ViewGroup getParentView(int index, boolean reverseSublists, boolean swapRowsAndColumns) {
- if (mRows == 0) {
+ if (getRowCount() == 0) {
return null;
}
int column = getParentViewIndex(index, reverseSublists, swapRowsAndColumns);
@@ -77,10 +75,11 @@
private int getParentViewIndex(int index, boolean reverseSublists, boolean swapRowsAndColumns) {
int sublistIndex;
ViewGroup row;
+ int rows = getRowCount();
if (swapRowsAndColumns) {
- sublistIndex = (int) Math.floor(index / mRows);
+ sublistIndex = (int) Math.floor(index / rows);
} else {
- sublistIndex = index % mRows;
+ sublistIndex = index % rows;
}
if (reverseSublists) {
sublistIndex = reverseSublistIndex(sublistIndex);
@@ -93,11 +92,9 @@
*/
public void setExpectedCount(int count) {
mExpectedCount = count;
- mRows = getRowCount();
- mColumns = getColumnCount();
for (int i = 0; i < getChildCount(); i++) {
- if (i <= mColumns) {
+ if (i <= getColumnCount()) {
setSublistVisibility(i, true);
} else {
setSublistVisibility(i, false);
@@ -113,10 +110,18 @@
}
private int getRowCount() {
+ // special case for 3 to use a single row
+ if (mExpectedCount == 3) {
+ return 1;
+ }
return (int) Math.ceil(Math.sqrt(mExpectedCount));
}
private int getColumnCount() {
+ // special case for 3 to use a single row
+ if (mExpectedCount == 3) {
+ return 3;
+ }
return (int) Math.round(Math.sqrt(mExpectedCount));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 7295008..9df6ba5 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -29,6 +29,7 @@
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.util.Log;
+import android.util.MathUtils;
import com.android.systemui.ImageWallpaper;
import com.android.systemui.ImageWallpaper.ImageGLView;
@@ -43,6 +44,8 @@
public class ImageWallpaperRenderer implements GLSurfaceView.Renderer,
ImageWallpaper.WallpaperStatusListener, ImageRevealHelper.RevealStateListener {
private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
+ private static final float SCALE_VIEWPORT_MIN = 0.98f;
+ private static final float SCALE_VIEWPORT_MAX = 1f;
private final WallpaperManager mWallpaperManager;
private final ImageGLProgram mProgram;
@@ -52,6 +55,8 @@
private final ImageGLView mGLView;
private float mXOffset = 0f;
private float mYOffset = 0f;
+ private int mWidth = 0;
+ private int mHeight = 0;
public ImageWallpaperRenderer(Context context, ImageGLView glView) {
mWallpaperManager = context.getSystemService(WallpaperManager.class);
@@ -87,6 +92,8 @@
Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height
+ ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
}
+ mWidth = width;
+ mHeight = height;
mWallpaper.adjustTextureCoordinates(mWallpaperManager.getBitmap(),
width, height, mXOffset, mYOffset);
}
@@ -102,10 +109,21 @@
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), per85);
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
+ scaleViewport(reveal);
mWallpaper.useTexture();
mWallpaper.draw();
}
+ private void scaleViewport(float reveal) {
+ // Interpolation between SCALE_VIEWPORT_MAX and SCALE_VIEWPORT_MIN by reveal.
+ float vpScaled = MathUtils.lerp(SCALE_VIEWPORT_MAX, SCALE_VIEWPORT_MIN, reveal);
+ // Calculate the offset amount from the lower left corner.
+ float offset = (SCALE_VIEWPORT_MAX - vpScaled) / 2;
+ // Change the viewport.
+ glViewport((int) (mWidth * offset), (int) (mHeight * offset),
+ (int) (mWidth * vpScaled), (int) (mHeight * vpScaled));
+ }
+
@Override
public void onAmbientModeChanged(boolean inAmbientMode, long duration) {
mImageRevealHelper.updateAwake(!inAmbientMode, duration);
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 9bca2cc..9f0f53e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -135,7 +135,7 @@
mDialog = new AlertDialog.Builder(this)
.setTitle(dialogTitle)
- .setIcon(aInfo.loadIcon(packageManager))
+ .setIcon(R.drawable.ic_media_projection_permission)
.setMessage(message)
.setPositiveButton(R.string.media_projection_action_text, this)
.setNegativeButton(android.R.string.cancel, this)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index bed0c45..341461b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -42,9 +42,11 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
@@ -743,6 +745,15 @@
return (x - flashDurationPct) / (1f - flashDurationPct);
}
};
+
+ Resources r = mContext.getResources();
+ if ((r.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES) {
+ mScreenshotView.getBackground().setTint(Color.BLACK);
+ } else {
+ mScreenshotView.getBackground().setTintList(null);
+ }
+
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index b820dc0..a630e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -461,9 +461,6 @@
}
public boolean shouldKeepForRemoteInputHistory(NotificationEntry entry) {
- if (entry.isDismissed()) {
- return false;
- }
if (!FORCE_REMOTE_INPUT_HISTORY) {
return false;
}
@@ -471,9 +468,6 @@
}
public boolean shouldKeepForSmartReplyHistory(NotificationEntry entry) {
- if (entry.isDismissed()) {
- return false;
- }
if (!FORCE_REMOTE_INPUT_HISTORY) {
return false;
}
@@ -661,9 +655,6 @@
protected class RemoteInputActiveExtender extends RemoteInputExtender {
@Override
public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
- if (entry.isDismissed()) {
- return false;
- }
return mRemoteInputController.isRemoteInputActive(entry);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 4ed9ae4..7d224fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -159,16 +159,19 @@
}
public void performRemoveNotification(StatusBarNotification n) {
- final int rank = mNotificationData.getRank(n.getKey());
- final int count = mNotificationData.getActiveNotifications().size();
- NotificationVisibility.NotificationLocation location =
- NotificationLogger.getNotificationLocation(getNotificationData().get(n.getKey()));
- final NotificationVisibility nv = NotificationVisibility.obtain(n.getKey(), rank, count,
- true, location);
+ final NotificationVisibility nv = obtainVisibility(n.getKey());
removeNotificationInternal(
n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */);
}
+ private NotificationVisibility obtainVisibility(String key) {
+ final int rank = mNotificationData.getRank(key);
+ final int count = mNotificationData.getActiveNotifications().size();
+ NotificationVisibility.NotificationLocation location =
+ NotificationLogger.getNotificationLocation(getNotificationData().get(key));
+ return NotificationVisibility.obtain(key, rank, count, true, location);
+ }
+
private void abortExistingInflation(String key) {
if (mPendingNotifications.containsKey(key)) {
NotificationEntry entry = mPendingNotifications.get(key);
@@ -226,8 +229,8 @@
@Override
public void removeNotification(String key, NotificationListenerService.RankingMap ranking) {
- removeNotificationInternal(
- key, ranking, null, false /* forceRemove */, false /* removedByUser */);
+ removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */,
+ false /* removedByUser */);
}
private void removeNotificationInternal(
@@ -245,7 +248,8 @@
if (entry != null) {
// If a manager needs to keep the notification around for whatever reason, we
// keep the notification
- if (!forceRemove) {
+ boolean entryDismissed = entry.isRowDismissed();
+ if (!forceRemove && !entryDismissed) {
for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
if (extender.shouldExtendLifetime(entry)) {
mLatestRankingMap = ranking;
@@ -272,6 +276,7 @@
mNotificationData.remove(key, ranking);
updateNotifications();
Dependency.get(LeakDetector.class).trackGarbage(entry);
+ removedByUser |= entryDismissed;
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onEntryRemoved(entry, visibility, removedByUser);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index 7cbe1a3..059c3f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -22,10 +22,12 @@
import android.app.NotificationManager;
import android.content.Context;
import android.database.ContentObserver;
+import android.hardware.display.AmbientDisplayConfiguration;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
@@ -54,6 +56,7 @@
private final StatusBarStateController mStatusBarStateController =
Dependency.get(StatusBarStateController.class);
private final NotificationFilter mNotificationFilter = Dependency.get(NotificationFilter.class);
+ private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private final Context mContext;
private final PowerManager mPowerManager;
@@ -73,17 +76,20 @@
this(context,
(PowerManager) context.getSystemService(Context.POWER_SERVICE),
IDreamManager.Stub.asInterface(
- ServiceManager.checkService(DreamService.DREAM_SERVICE)));
+ ServiceManager.checkService(DreamService.DREAM_SERVICE)),
+ new AmbientDisplayConfiguration(context));
}
@VisibleForTesting
protected NotificationInterruptionStateProvider(
Context context,
PowerManager powerManager,
- IDreamManager dreamManager) {
+ IDreamManager dreamManager,
+ AmbientDisplayConfiguration ambientDisplayConfiguration) {
mContext = context;
mPowerManager = powerManager;
mDreamManager = dreamManager;
+ mAmbientDisplayConfiguration = ambientDisplayConfiguration;
}
/** Sets up late-binding dependencies for this component. */
@@ -232,6 +238,13 @@
public boolean shouldPulse(NotificationEntry entry) {
StatusBarNotification sbn = entry.notification;
+ if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
+ if (DEBUG) {
+ Log.d(TAG, "No pulsing: disabled by setting: " + sbn.getKey());
+ }
+ return false;
+ }
+
if (!getShadeController().isDozing()) {
if (DEBUG) {
Log.d(TAG, "No pulsing: not dozing: " + sbn.getKey());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 5cd1210..f1373d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -543,14 +543,6 @@
return row == null || row.isRemoved();
}
- /**
- * @return {@code true} if the row is null or dismissed
- */
- public boolean isDismissed() {
- //TODO: recycling
- return row == null || row.isDismissed();
- }
-
public boolean isRowPinned() {
return row != null && row.isPinned();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 2162ea7..410eeae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -22,17 +22,21 @@
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Trace;
+import android.provider.Settings;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.tuner.TunerService;
import java.io.PrintWriter;
@@ -95,6 +99,17 @@
*/
private static final float BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
+ /**
+ * If face unlock dismisses the lock screen or keeps user on keyguard by default on this device.
+ */
+ private final boolean mFaceDismissesKeyguardByDefault;
+
+ /**
+ * If face unlock dismisses the lock screen or keeps user on keyguard for the current user.
+ */
+ @VisibleForTesting
+ protected boolean mFaceDismissesKeyguard;
+
private final NotificationMediaManager mMediaManager;
private final PowerManager mPowerManager;
private final Handler mHandler;
@@ -115,14 +130,42 @@
private boolean mPendingShowBouncer;
private boolean mHasScreenTurnedOnSinceAuthenticating;
+ private final TunerService.Tunable mFaceDismissedKeyguardTunable = new TunerService.Tunable() {
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ int defaultValue = mFaceDismissesKeyguardByDefault ? 1 : 0;
+ mFaceDismissesKeyguard = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD,
+ defaultValue, KeyguardUpdateMonitor.getCurrentUser()) != 0;
+ }
+ };
+
public BiometricUnlockController(Context context,
+ DozeScrimController dozeScrimController,
+ KeyguardViewMediator keyguardViewMediator,
+ ScrimController scrimController,
+ StatusBar statusBar,
+ UnlockMethodCache unlockMethodCache, Handler handler,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ TunerService tunerService) {
+ this(context, dozeScrimController, keyguardViewMediator, scrimController, statusBar,
+ unlockMethodCache, handler, keyguardUpdateMonitor, tunerService,
+ context.getResources()
+ .getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze),
+ context.getResources().getBoolean(R.bool.config_faceAuthDismissesKeyguard));
+ }
+
+ @VisibleForTesting
+ protected BiometricUnlockController(Context context,
DozeScrimController dozeScrimController,
KeyguardViewMediator keyguardViewMediator,
ScrimController scrimController,
StatusBar statusBar,
UnlockMethodCache unlockMethodCache, Handler handler,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- int wakeUpDelay) {
+ TunerService tunerService,
+ int wakeUpDelay,
+ boolean faceDismissesKeyguard) {
mContext = context;
mPowerManager = context.getSystemService(PowerManager.class);
mUpdateMonitor = keyguardUpdateMonitor;
@@ -138,6 +181,9 @@
mUnlockMethodCache = unlockMethodCache;
mHandler = handler;
mWakeUpDelay = wakeUpDelay;
+ mFaceDismissesKeyguardByDefault = faceDismissesKeyguard;
+ tunerService.addTunable(mFaceDismissedKeyguardTunable,
+ Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD);
}
public void setStatusBarKeyguardViewManager(
@@ -344,27 +390,28 @@
private int calculateMode(BiometricSourceType biometricSourceType) {
boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed();
boolean deviceDreaming = mUpdateMonitor.isDreaming();
- boolean isFace = biometricSourceType == BiometricSourceType.FACE;
+ boolean faceStayingOnKeyguard = biometricSourceType == BiometricSourceType.FACE
+ && !mFaceDismissesKeyguard;
if (!mUpdateMonitor.isDeviceInteractive()) {
if (!mStatusBarKeyguardViewManager.isShowing()) {
return MODE_ONLY_WAKE;
} else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
- return isFace ? MODE_NONE : MODE_WAKE_AND_UNLOCK_PULSING;
+ return faceStayingOnKeyguard ? MODE_NONE : MODE_WAKE_AND_UNLOCK_PULSING;
} else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
return MODE_WAKE_AND_UNLOCK;
} else {
return MODE_SHOW_BOUNCER;
}
}
- if (unlockingAllowed && deviceDreaming && !isFace) {
+ if (unlockingAllowed && deviceDreaming && !faceStayingOnKeyguard) {
return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
}
if (mStatusBarKeyguardViewManager.isShowing()) {
if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
return MODE_DISMISS_BOUNCER;
} else if (unlockingAllowed) {
- return isFace ? MODE_ONLY_WAKE : MODE_UNLOCK;
+ return faceStayingOnKeyguard ? MODE_ONLY_WAKE : MODE_UNLOCK;
} else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
return MODE_SHOW_BOUNCER;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 64e76d3..b7d1fc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -203,10 +203,10 @@
case STATE_SCANNING_FACE:
// Error animation also starts and ands on the padlock.
case STATE_BIOMETRICS_ERROR:
- iconRes = com.android.internal.R.drawable.ic_lock_24dp;
+ iconRes = com.android.internal.R.drawable.ic_lock;
break;
case STATE_LOCK_OPEN:
- iconRes = com.android.internal.R.drawable.ic_lock_open_24dp;
+ iconRes = com.android.internal.R.drawable.ic_lock_open;
break;
default:
throw new IllegalArgumentException();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index c389082..b540fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -42,6 +42,7 @@
import android.annotation.SuppressLint;
import android.app.StatusBarManager;
import android.content.Context;
+import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Point;
@@ -59,6 +60,8 @@
import android.util.SparseArray;
import android.view.Display;
import android.view.Gravity;
+import android.view.IPinnedStackController;
+import android.view.IPinnedStackListener;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
@@ -355,6 +358,46 @@
}
};
+ private final IPinnedStackListener.Stub mImeChangedListener = new IPinnedStackListener.Stub() {
+ @Override
+ public void onListenerRegistered(IPinnedStackController controller) {
+ }
+
+ @Override
+ public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+ post(() -> {
+ // When the ime changes visibility, resize the edge panels to not cover the ime
+ final int width = mPrototypeController.getEdgeSensitivityWidth();
+ final int height = mContext.getDisplay().getHeight() - imeHeight
+ - getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
+ if (mLeftEdgePanel != null) {
+ mLeftEdgePanel.setDimensions(width, height);
+ }
+ if (mRightEdgePanel != null) {
+ mRightEdgePanel.setDimensions(width, height);
+ }
+ });
+ }
+
+ @Override
+ public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+ }
+
+ @Override
+ public void onMinimizedStateChanged(boolean isMinimized) {
+ }
+
+ @Override
+ public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+ Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment,
+ int displayRotation) {
+ }
+
+ @Override
+ public void onActionsChanged(ParceledListSlice actions) {
+ }
+ };
+
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -1296,13 +1339,19 @@
int height = mPrototypeController.getEdgeSensitivityHeight();
// Explicitly left and right, not start and end as this is device relative.
mLeftEdgePanel = NavigationBarEdgePanel.create(getContext(), width, height,
- Gravity.LEFT | Gravity.BOTTOM);
+ Gravity.LEFT | Gravity.TOP);
mRightEdgePanel = NavigationBarEdgePanel.create(getContext(), width, height,
- Gravity.RIGHT | Gravity.BOTTOM);
+ Gravity.RIGHT | Gravity.TOP);
mLeftEdgePanel.setOnTouchListener(mEdgePanelTouchListener);
mRightEdgePanel.setOnTouchListener(mEdgePanelTouchListener);
wm.addView(mLeftEdgePanel, mLeftEdgePanel.getLayoutParams());
wm.addView(mRightEdgePanel, mRightEdgePanel.getLayoutParams());
+
+ try {
+ WindowManagerWrapper.getInstance().addPinnedStackListener(mImeChangedListener);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to register pinned stack listener", e);
+ }
}
}
@@ -1327,6 +1376,7 @@
if (mRightEdgePanel != null) {
wm.removeView(mRightEdgePanel);
}
+ WindowManagerWrapper.getInstance().removePinnedStackListener(mImeChangedListener);
}
private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 8714a51..1949bad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -90,6 +90,10 @@
*/
public static final float GRADIENT_SCRIM_ALPHA = 0.2f;
/**
+ * Scrim opacity when the phone is about to wake-up.
+ */
+ public static final float AOD2_SCRIM_ALPHA = 0.6f;
+ /**
* A scrim varies its opacity based on a busyness factor, for example
* how many notifications are currently visible.
*/
@@ -421,6 +425,8 @@
interpolatedFract);
mCurrentInFrontAlpha = 0;
}
+ mCurrentBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
+ mState.getBehindTint(), interpolatedFract);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index bbeebd6..2f161d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -54,6 +54,8 @@
} else {
mAnimationDuration = ScrimController.ANIMATION_DURATION;
}
+ mCurrentInFrontTint = Color.BLACK;
+ mCurrentBehindTint = Color.BLACK;
mCurrentBehindAlpha = mScrimBehindAlphaKeyguard;
mCurrentInFrontAlpha = 0;
}
@@ -131,11 +133,10 @@
|| mPulseReason == DozeLog.PULSE_REASON_DOCKING
|| mPulseReason == DozeLog.PULSE_REASON_INTENT) {
mCurrentBehindAlpha = previousState.getBehindAlpha();
- mCurrentBehindTint = Color.BLACK;
} else {
- mCurrentBehindAlpha = mScrimBehindAlphaKeyguard;
- mCurrentBehindTint = Color.TRANSPARENT;
+ mCurrentBehindAlpha = ScrimController.AOD2_SCRIM_ALPHA;
}
+ mCurrentBehindTint = Color.BLACK;
mBlankScreen = mDisplayRequiresBlanking;
}
},
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 0ca4e73..60b1659 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -225,6 +225,7 @@
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.volume.VolumeComponent;
@@ -1208,8 +1209,7 @@
mBiometricUnlockController = new BiometricUnlockController(mContext,
mDozeScrimController, keyguardViewMediator,
mScrimController, this, UnlockMethodCache.getInstance(mContext),
- new Handler(), mKeyguardUpdateMonitor, mContext.getResources().getInteger(
- com.android.internal.R.integer.config_wakeUpDelayDoze));
+ new Handler(), mKeyguardUpdateMonitor, Dependency.get(TunerService.class));
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
getBouncerContainer(), mNotificationPanel, mBiometricUnlockController);
mKeyguardIndicationController
@@ -3881,7 +3881,7 @@
return;
}
- boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN;
+ boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_NOTIFICATION;
// Set the state to pulsing, so ScrimController will know what to do once we ask it to
// execute the transition. The pulse callback will then be invoked when the scrims
// are black, indicating that StatusBar is ready to present the rest of the UI.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index 73ee0bd..b9afea1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -22,11 +22,14 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
+import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -47,12 +50,15 @@
@TestableLooper.RunWithLooper
public class AppOpsControllerTest extends SysuiTestCase {
private static final String TEST_PACKAGE_NAME = "test";
- private static final int TEST_UID = 0;
- private static final int TEST_UID_OTHER = 500000;
+ private static final int TEST_UID = UserHandle.getUid(0, 0);
+ private static final int TEST_UID_OTHER = UserHandle.getUid(1, 0);
+ private static final int TEST_UID_NON_USER_SENSITIVE = UserHandle.getUid(2, 0);
@Mock
private AppOpsManager mAppOpsManager;
@Mock
+ private PackageManager mPackageManager;
+ @Mock
private AppOpsController.Callback mCallback;
@Mock
private AppOpsControllerImpl.H mMockHandler;
@@ -65,6 +71,18 @@
getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
+ // All permissions of TEST_UID and TEST_UID_OTHER are user sensitive. None of
+ // TEST_UID_NON_USER_SENSITIVE are user sensitive.
+ getContext().setMockPackageManager(mPackageManager);
+ when(mPackageManager.getPermissionFlags(anyString(), anyString(),
+ eq(UserHandle.getUserHandleForUid(TEST_UID)))).thenReturn(
+ PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED);
+ when(mPackageManager.getPermissionFlags(anyString(), anyString(),
+ eq(UserHandle.getUserHandleForUid(TEST_UID_OTHER)))).thenReturn(
+ PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED);
+ when(mPackageManager.getPermissionFlags(anyString(), anyString(),
+ eq(UserHandle.getUserHandleForUid(TEST_UID_NON_USER_SENSITIVE)))).thenReturn(0);
+
mController = new AppOpsControllerImpl(mContext, Dependency.get(Dependency.BG_LOOPER));
}
@@ -157,6 +175,14 @@
}
@Test
+ public void nonUserSensitiveOpsAreIgnored() {
+ mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
+ TEST_UID_NON_USER_SENSITIVE, TEST_PACKAGE_NAME, true);
+ assertEquals(0, mController.getActiveAppOpsForUser(
+ UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE)).size());
+ }
+
+ @Test
public void opNotedScheduledForRemoval() {
mController.setBGHandler(mMockHandler);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 0fd7834..42c221a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -20,10 +20,13 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.IActivityManager;
+import android.app.PendingIntent;
import android.content.Context;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -83,6 +86,9 @@
@Mock
private BubbleController.BubbleExpandListener mBubbleExpandListener;
+ @Mock
+ private PendingIntent mDeleteIntent;
+
private BubbleData mBubbleData;
@Before
@@ -98,9 +104,9 @@
// Need notifications for bubbles
mNotificationTestHelper = new NotificationTestHelper(mContext);
- mRow = mNotificationTestHelper.createBubble();
- mRow2 = mNotificationTestHelper.createBubble();
- mNoChannelRow = mNotificationTestHelper.createBubble();
+ mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
+ mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
+ mNoChannelRow = mNotificationTestHelper.createBubble(mDeleteIntent);
// Return non-null notification data from the NEM
when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
@@ -141,11 +147,10 @@
verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
- mBubbleController.removeBubble(mRow.getEntry().key);
+ mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
assertFalse(mStatusBarWindowController.getBubblesShowing());
assertTrue(mRow.getEntry().isBubbleDismissed());
verify(mNotificationEntryManager).updateNotifications();
-
verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
}
@@ -155,7 +160,7 @@
mBubbleController.updateBubble(mRow2.getEntry(), true /* updatePosition */);
assertTrue(mBubbleController.hasBubbles());
- mBubbleController.dismissStack();
+ mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
assertFalse(mStatusBarWindowController.getBubblesShowing());
verify(mNotificationEntryManager).updateNotifications();
assertTrue(mRow.getEntry().isBubbleDismissed());
@@ -271,7 +276,8 @@
assertFalse(mRow2.getEntry().showInShadeWhenBubble());
// Dismiss currently expanded
- mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey());
+ mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
+ BubbleController.DISMISS_USER_GESTURE);
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
// Make sure next bubble is selected
@@ -279,7 +285,8 @@
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
// Dismiss that one
- mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey());
+ mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
+ BubbleController.DISMISS_USER_GESTURE);
// Make sure state changes and collapse happens
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
@@ -299,6 +306,28 @@
assertTrue(mRow.getEntry().showInShadeWhenBubble());
}
+ @Test
+ public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
+ mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
+ mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_AGED);
+ verify(mDeleteIntent, never()).send();
+ }
+
+ @Test
+ public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
+ mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
+ mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+ verify(mDeleteIntent, times(1)).send();
+ }
+
+ @Test
+ public void testDeleteIntent_dismissStack() throws PendingIntent.CanceledException {
+ mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
+ mBubbleController.updateBubble(mRow2.getEntry(), true /* updatePosition */);
+ mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
+ verify(mDeleteIntent, times(2)).send();
+ }
+
static class TestableBubbleController extends BubbleController {
TestableBubbleController(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index cf25a9d..2ee73f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -198,6 +198,26 @@
assertEquals(0, mLayout.getChildAt(0).getTranslationX(), .1f);
}
+ @Test
+ public void testRestoredAtRestingPosition() throws InterruptedException {
+ mStackController.flingStackThenSpringToEdge(0, 5000, 5000);
+
+ waitForPropertyAnimations(
+ DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ waitForLayoutMessageQueue();
+
+ final PointF prevStackPos = mStackController.getStackPosition();
+
+ mLayout.removeAllViews();
+ mLayout.addView(new FrameLayout(getContext()));
+
+ waitForLayoutMessageQueue();
+ waitForPropertyAnimations(
+ DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+
+ assertEquals(prevStackPos, mStackController.getStackPosition());
+ }
+
/**
* Checks every child view to make sure it's stacked at the given coordinates, off to the left
* or right side depending on offset multiplier.
@@ -217,7 +237,7 @@
*/
private class TestableStackController extends StackAnimationController {
@Override
- public void flingThenSpringFirstBubbleWithStackFollowing(
+ protected void flingThenSpringFirstBubbleWithStackFollowing(
DynamicAnimation.ViewProperty property, float vel, float friction,
SpringForce spring, Float finalPosition) {
mMainThreadHandler.post(() ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index cef78db..de15505 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -23,6 +23,7 @@
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.Notification;
+import android.app.Notification.BubbleMetadata;
import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.content.Context;
@@ -152,8 +153,18 @@
* Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
*/
public ExpandableNotificationRow createBubble() throws Exception {
+ return createBubble(null);
+ }
+
+ /**
+ * Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
+ *
+ * @param deleteIntent the intent to assign to {@link BubbleMetadata#deleteIntent}
+ */
+ public ExpandableNotificationRow createBubble(@Nullable PendingIntent deleteIntent)
+ throws Exception {
Notification n = createNotification(false /* isGroupSummary */,
- null /* groupKey */, true /* isBubble */);
+ null /* groupKey */, true /* isBubble */, deleteIntent);
return generateRow(n, PKG, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH);
}
@@ -196,7 +207,8 @@
* @return a notification that is in the group specified or standalone if unspecified
*/
private Notification createNotification(boolean isGroupSummary, @Nullable String groupKey) {
- return createNotification(isGroupSummary, groupKey, false /* isBubble */);
+ return createNotification(isGroupSummary, groupKey, false /* isBubble */,
+ null /* bubbleDeleteIntent */);
}
/**
@@ -208,7 +220,8 @@
* @return a notification that is in the group specified or standalone if unspecified
*/
private Notification createNotification(boolean isGroupSummary,
- @Nullable String groupKey, boolean isBubble) {
+ @Nullable String groupKey, boolean isBubble,
+ @Nullable PendingIntent bubbleDeleteIntent) {
Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
R.drawable.ic_person)
.setCustomContentView(new RemoteViews(mContext.getPackageName(),
@@ -227,7 +240,8 @@
notificationBuilder.setGroup(groupKey);
}
if (isBubble) {
- notificationBuilder.setBubbleMetadata(makeBubbleMetadata());
+ BubbleMetadata metadata = makeBubbleMetadata(bubbleDeleteIntent);
+ notificationBuilder.setBubbleMetadata(metadata);
}
return notificationBuilder.build();
}
@@ -291,11 +305,13 @@
return row;
}
- private Notification.BubbleMetadata makeBubbleMetadata() {
+ private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) {
Intent target = new Intent(mContext, BubblesTestActivity.class);
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, 0);
- return new Notification.BubbleMetadata.Builder()
+
+ return new BubbleMetadata.Builder()
.setIntent(bubbleIntent)
+ .setDeleteIntent(deleteIntent)
.setTitle("bubble title")
.setIcon(Icon.createWithResource(mContext, 1))
.setDesiredHeight(314)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 5543744..c8005dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -347,7 +347,7 @@
verify(mPresenter).updateNotificationViews();
verify(mEntryListener).onEntryRemoved(
- mEntry, null, false /* removedByUser */);
+ eq(mEntry), any(), eq(false) /* removedByUser */);
verify(mRow).setRemoved();
assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
@@ -360,7 +360,7 @@
mEntryManager.removeNotification("not_a_real_key", mRankingMap);
verify(mEntryListener, never()).onEntryRemoved(
- mEntry, null, false /* removedByUser */);
+ eq(mEntry), any(), eq(false) /* removedByUser */);
}
@Test
@@ -373,7 +373,7 @@
mEntryManager.removeNotification(mSbn.getKey(), mRankingMap);
verify(mEntryListener, never()).onEntryRemoved(
- mEntry, null, false /* removedByUser */);
+ eq(mEntry), any(), eq(false /* removedByUser */));
}
@Test
@@ -455,7 +455,7 @@
verify(extender).setShouldManageLifetime(mEntry, true);
// THEN the notification is retained
assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
- verify(mEntryListener, never()).onEntryRemoved(mEntry, null, false);
+ verify(mEntryListener, never()).onEntryRemoved(eq(mEntry), any(), eq(false));
}
@Test
@@ -474,7 +474,7 @@
// THEN the notification is removed
assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
- verify(mEntryListener).onEntryRemoved(mEntry, null, false);
+ verify(mEntryListener).onEntryRemoved(eq(mEntry), any(), eq(false));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 7be4756..057f752 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -36,6 +36,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.tuner.TunerService;
import org.junit.Before;
import org.junit.Test;
@@ -68,6 +69,8 @@
private StatusBar mStatusBar;
@Mock
private UnlockMethodCache mUnlockMethodCache;
+ @Mock
+ private TunerService mTunerService;
private BiometricUnlockController mBiometricUnlockController;
@Before
@@ -79,9 +82,8 @@
mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager);
mDependency.injectTestDependency(StatusBarWindowController.class,
mStatusBarWindowController);
- mBiometricUnlockController = new BiometricUnlockController(mContext, mDozeScrimController,
- mKeyguardViewMediator, mScrimController, mStatusBar, mUnlockMethodCache,
- new Handler(), mUpdateMonitor, 0 /* wakeUpDelay */);
+ mBiometricUnlockController = new TestableBiometricUnlockController(
+ false /* faceDismissesKeyguard */);
mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
}
@@ -136,6 +138,19 @@
}
@Test
+ public void onBiometricAuthenticated_whenFace_dismissingKeyguard() {
+ mBiometricUnlockController = new TestableBiometricUnlockController(
+ true /* faceDismissesKeyguard */);
+ mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
+
+ when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+ mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+ BiometricSourceType.FACE);
+
+ verify(mStatusBarKeyguardViewManager).animateCollapsePanels(anyFloat());
+ }
+
+ @Test
public void onBiometricAuthenticated_whenFaceOnBouncer_dismissBouncer() {
when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
@@ -156,4 +171,15 @@
verify(mStatusBarKeyguardViewManager, never()).animateCollapsePanels(anyFloat());
}
+
+ private class TestableBiometricUnlockController extends BiometricUnlockController {
+
+ TestableBiometricUnlockController(boolean faceDismissesKeyguard) {
+ super(mContext, mDozeScrimController,
+ mKeyguardViewMediator, mScrimController, mStatusBar, mUnlockMethodCache,
+ new Handler(), mUpdateMonitor, mTunerService, 0 /* wakeUpDelay */,
+ faceDismissesKeyguard);
+ mFaceDismissesKeyguard = faceDismissesKeyguard;
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 6db3624..539851f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -51,6 +51,7 @@
import com.android.systemui.util.wakelock.WakeLock;
import com.android.systemui.utils.os.FakeHandler;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -99,12 +100,13 @@
visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
mScrimController.setHasBackdrop(false);
mScrimController.setWallpaperSupportsAmbientMode(false);
+ mScrimController.transitionTo(ScrimState.KEYGUARD);
+ mScrimController.finishAnimationsImmediately();
}
- @Test
- public void initialState() {
- Assert.assertEquals("ScrimController should start initialized",
- mScrimController.getState(), ScrimState.UNINITIALIZED);
+ @After
+ public void tearDown() {
+ mScrimController.finishAnimationsImmediately();
}
@Test
@@ -114,7 +116,7 @@
// Front scrim should be transparent
// Back scrim should be visible without tint
assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
- assertScrimTint(mScrimBehind, false /* tinted */);
+ assertScrimTint(mScrimBehind, true /* tinted */);
}
@Test
@@ -230,7 +232,7 @@
// Back scrim should be semi-transparent so the user can see the wallpaper
// Pulse callback should have been invoked
assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
- assertScrimTint(mScrimBehind, false /* tinted */);
+ assertScrimTint(mScrimBehind, true /* tinted */);
}
@Test
@@ -307,13 +309,13 @@
reset(mScrimBehind);
mScrimController.setPanelExpansion(0f);
mScrimController.setPanelExpansion(1.0f);
- mScrimController.onPreDraw();
+ mScrimController.finishAnimationsImmediately();
Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
mScrimController.setPanelExpansion(0f);
- mScrimController.onPreDraw();
+ mScrimController.finishAnimationsImmediately();
Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
@@ -336,6 +338,7 @@
mScrimController.setExpansionAffectsAlpha(true);
mScrimController.setPanelExpansion(0.1f);
+ mScrimController.finishAnimationsImmediately();
Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
+ "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index f8bfc54..1ded6c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -41,6 +41,7 @@
import android.app.StatusBarManager;
import android.app.trust.TrustManager;
import android.content.Context;
+import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.fingerprint.FingerprintManager;
import android.metrics.LogMaker;
import android.os.Binder;
@@ -169,6 +170,8 @@
private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
@Mock
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private TestableStatusBar mStatusBar;
private FakeMetricsLogger mMetricsLogger;
@@ -205,7 +208,7 @@
mNotificationInterruptionStateProvider =
new TestableNotificationInterruptionStateProvider(mContext, mPowerManager,
- mDreamManager);
+ mDreamManager, mAmbientDisplayConfiguration);
mDependency.injectTestDependency(NotificationInterruptionStateProvider.class,
mNotificationInterruptionStateProvider);
mDependency.injectMockDependency(NavigationBarController.class);
@@ -641,10 +644,10 @@
@Test
public void testPulseWhileDozing_notifyAuthInterrupt() {
HashSet<Integer> reasonsWantingAuth = new HashSet<>(
- Collections.singletonList(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN));
+ Collections.singletonList(DozeLog.PULSE_REASON_NOTIFICATION));
HashSet<Integer> reasonsSkippingAuth = new HashSet<>(
Arrays.asList(DozeLog.PULSE_REASON_INTENT,
- DozeLog.PULSE_REASON_NOTIFICATION,
+ DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
DozeLog.PULSE_REASON_SENSOR_SIGMOTION,
DozeLog.REASON_SENSOR_PICKUP,
DozeLog.REASON_SENSOR_DOUBLE_TAP,
@@ -832,8 +835,9 @@
public TestableNotificationInterruptionStateProvider(
Context context,
PowerManager powerManager,
- IDreamManager dreamManager) {
- super(context, powerManager, dreamManager);
+ IDreamManager dreamManager,
+ AmbientDisplayConfiguration ambientDisplayConfiguration) {
+ super(context, powerManager, dreamManager, ambientDisplayConfiguration);
mUseHeadsUp = true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index 043b832..00d87c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -22,6 +22,7 @@
import static org.mockito.Mockito.when;
import android.os.SystemClock;
+import android.testing.TestableLooper;
import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
@@ -35,13 +36,12 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
+@TestableLooper.RunWithLooper
@SmallTest
-@Ignore
public class StatusBarWindowViewTest extends SysuiTestCase {
private StatusBarWindowView mView;
@@ -62,7 +62,6 @@
}
@Test
- @Ignore
public void testDragDownHelperCalledWhenDraggingDown() throws Exception {
when(Dependency.get(StatusBarStateController.class).getState())
.thenReturn(StatusBarState.SHADE);
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 91b161d..9673a84 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7087,6 +7087,9 @@
//ACTION: Log result for each card's eligibility check
ACTION_CONTEXTUAL_CARD_ELIGIBILITY = 1686;
+ // Panel for Wifi
+ PANEL_WIFI = 1687;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index f106ced..9f049cf 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -1798,6 +1798,9 @@
// Prediction horizon (in second) of Wifi usability score provided by external
// system app
optional int32 last_prediction_horizon_sec = 12 [default = -1];
+
+ // Whether screen status is on when WifiIsUnusableEvent happens.
+ optional bool screen_on = 13 [default = false];
}
message PasspointProfileTypeCount {
diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
index 45ea86f..922b327 100644
--- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
+++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
@@ -46,7 +46,8 @@
ComponentName componentName, int userId,
RemoteAppPredictionServiceCallbacks callback, boolean bindInstantServiceAllowed,
boolean verbose) {
- super(context, serviceInterface, componentName, userId, callback, bindInstantServiceAllowed,
+ super(context, serviceInterface, componentName, userId, callback,
+ context.getMainThreadHandler(), bindInstantServiceAllowed,
verbose, /* initialCapacity= */ 1);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 245e2c9..0e852f8 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -479,13 +479,16 @@
private void setDeviceConfigProperties() {
synchronized (mLock) {
- mAugmentedServiceIdleUnbindTimeoutMs = Helper.getIntDeviceConfigProperty(
+ mAugmentedServiceIdleUnbindTimeoutMs = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_AUTOFILL,
AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT,
(int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
- mAugmentedServiceRequestTimeoutMs = Helper.getIntDeviceConfigProperty(
+ mAugmentedServiceRequestTimeoutMs = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_AUTOFILL,
AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT,
DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS);
- mSupportedSmartSuggestionModes = Helper.getIntDeviceConfigProperty(
+ mSupportedSmartSuggestionModes = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_AUTOFILL,
AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES,
AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM);
if (verbose) {
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index d300bf2..3c0da7d 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -22,11 +22,9 @@
import android.app.assist.AssistStructure.ViewNode;
import android.content.ComponentName;
import android.metrics.LogMaker;
-import android.provider.DeviceConfig;
import android.service.autofill.Dataset;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Log;
import android.util.Slog;
import android.view.WindowManager;
import android.view.autofill.AutofillId;
@@ -207,21 +205,6 @@
}
}
- /**
- * Gets the value of a device config property from the Autofill namespace.
- */
- static int getIntDeviceConfigProperty(@NonNull String key, int defaultValue) {
- final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_AUTOFILL, key);
- if (value == null) return defaultValue;
-
- try {
- return Integer.parseInt(value);
- } catch (Exception e) {
- Log.w(TAG, "error parsing value (" + value + ") of property " + key + ": " + e);
- return defaultValue;
- }
- }
-
private interface ViewNodeFilter {
boolean matches(ViewNode node);
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index a38c3cf..aaba1ed 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -55,7 +55,7 @@
boolean bindInstantServiceAllowed, boolean verbose, int idleUnbindTimeoutMs,
int requestTimeoutMs) {
super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks,
- bindInstantServiceAllowed, verbose);
+ context.getMainThreadHandler(), bindInstantServiceAllowed, verbose);
mIdleUnbindTimeoutMs = idleUnbindTimeoutMs;
mRequestTimeoutMs = requestTimeoutMs;
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index e8a52b4..b8a7d44 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -64,7 +64,7 @@
RemoteFillService(Context context, ComponentName componentName, int userId,
FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed) {
super(context, AutofillService.SERVICE_INTERFACE, componentName, userId, callbacks,
- bindInstantServiceAllowed, sVerbose);
+ context.getMainThreadHandler(), bindInstantServiceAllowed, sVerbose);
mCallbacks = callbacks;
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 0205ad8..c75b4c6 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -234,18 +234,23 @@
private void setFineTuneParamsFromDeviceConfig() {
synchronized (mLock) {
- mDevCfgMaxBufferSize = ContentCaptureHelper.getIntDeviceConfigProperty(
+ mDevCfgMaxBufferSize = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE);
- mDevCfgIdleFlushingFrequencyMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+ mDevCfgIdleFlushingFrequencyMs = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY,
ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS);
- mDevCfgTextChangeFlushingFrequencyMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+ mDevCfgTextChangeFlushingFrequencyMs = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY,
ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS);
- mDevCfgLogHistorySize = ContentCaptureHelper.getIntDeviceConfigProperty(
+ mDevCfgLogHistorySize = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
- mDevCfgIdleUnbindTimeoutMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+ mDevCfgIdleUnbindTimeoutMs = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
(int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
if (verbose) {
@@ -260,7 +265,8 @@
}
private void setLoggingLevelFromDeviceConfig() {
- mDevCfgLoggingLevel = ContentCaptureHelper.getIntDeviceConfigProperty(
+ mDevCfgLoggingLevel = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
ContentCaptureHelper.getDefaultLoggingLevel());
ContentCaptureHelper.setLoggingLevel(mDevCfgLoggingLevel);
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index f7ac7b8c..1d2d625 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -46,7 +46,8 @@
ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
boolean verbose, int idleUnbindTimeoutMs) {
super(context, serviceInterface, serviceComponentName, userId, callbacks,
- bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
+ context.getMainThreadHandler(), bindInstantServiceAllowed, verbose,
+ /* initialCapacity= */ 2);
mServerCallback = callback.asBinder();
mIdleUnbindTimeoutMs = idleUnbindTimeoutMs;
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index 58dbea4..69b4672 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -32,6 +32,7 @@
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Slog;
import com.android.server.LocalServices;
@@ -63,7 +64,8 @@
public ContentSuggestionsManagerService(Context context) {
super(context, new FrameworkResourcesServiceNameResolver(context,
- com.android.internal.R.string.config_defaultContentSuggestionsService), null);
+ com.android.internal.R.string.config_defaultContentSuggestionsService),
+ UserManager.DISALLOW_CONTENT_SUGGESTIONS);
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
}
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerServiceShellCommand.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerServiceShellCommand.java
index e34f1ea..08cc69d 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerServiceShellCommand.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerServiceShellCommand.java
@@ -43,29 +43,13 @@
}
final PrintWriter pw = getOutPrintWriter();
switch (cmd) {
- case "set": {
- final String what = getNextArgRequired();
- switch (what) {
- case "temporary-service": {
- final int userId = Integer.parseInt(getNextArgRequired());
- String serviceName = getNextArg();
- if (serviceName == null) {
- mService.resetTemporaryService(userId);
- return 0;
- }
- final int duration = Integer.parseInt(getNextArgRequired());
- mService.setTemporaryService(userId, serviceName, duration);
- pw.println("ContentSuggestionsService temporarily set to " + serviceName
- + " for " + duration + "ms");
- break;
- }
- }
- }
- break;
+ case "set":
+ return requestSet(pw);
+ case "get":
+ return requestGet(pw);
default:
return handleDefaultCommands(cmd);
}
- return 0;
}
@Override
@@ -76,9 +60,72 @@
pw.println(" Prints this help text.");
pw.println("");
pw.println(" set temporary-service USER_ID [COMPONENT_NAME DURATION]");
- pw.println(" Temporarily (for DURATION ms) changes the service implemtation.");
+ pw.println(" Temporarily (for DURATION ms) changes the service implementation.");
pw.println(" To reset, call with just the USER_ID argument.");
pw.println("");
+ pw.println(" set default-service-enabled USER_ID [true|false]");
+ pw.println(" Enable / disable the default service for the user.");
+ pw.println("");
+ pw.println(" get default-service-enabled USER_ID");
+ pw.println(" Checks whether the default service is enabled for the user.");
+ pw.println("");
}
}
+
+ private int requestSet(PrintWriter pw) {
+ final String what = getNextArgRequired();
+
+ switch(what) {
+ case "temporary-service":
+ return setTemporaryService(pw);
+ case "default-service-enabled":
+ return setDefaultServiceEnabled();
+ default:
+ pw.println("Invalid set: " + what);
+ return -1;
+ }
+ }
+
+ private int requestGet(PrintWriter pw) {
+ final String what = getNextArgRequired();
+ switch(what) {
+ case "default-service-enabled":
+ return getDefaultServiceEnabled(pw);
+ default:
+ pw.println("Invalid get: " + what);
+ return -1;
+ }
+ }
+
+ private int setTemporaryService(PrintWriter pw) {
+ final int userId = Integer.parseInt(getNextArgRequired());
+ String serviceName = getNextArg();
+ if (serviceName == null) {
+ mService.resetTemporaryService(userId);
+ return 0;
+ }
+ final int duration = Integer.parseInt(getNextArgRequired());
+ mService.setTemporaryService(userId, serviceName, duration);
+ pw.println("ContentSuggestionsService temporarily set to " + serviceName
+ + " for " + duration + "ms");
+ return 0;
+ }
+
+ private int setDefaultServiceEnabled() {
+ final int userId = getNextIntArgRequired();
+ final boolean enabled = Boolean.parseBoolean(getNextArg());
+ mService.setDefaultServiceEnabled(userId, enabled);
+ return 0;
+ }
+
+ private int getDefaultServiceEnabled(PrintWriter pw) {
+ final int userId = getNextIntArgRequired();
+ final boolean enabled = mService.isDefaultServiceEnabled(userId);
+ pw.println(enabled);
+ return 0;
+ }
+
+ private int getNextIntArgRequired() {
+ return Integer.parseInt(getNextArgRequired());
+ }
}
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
index bf48d76..442972a 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
@@ -47,7 +47,8 @@
int userId, Callbacks callbacks,
boolean bindInstantServiceAllowed, boolean verbose) {
super(context, ContentSuggestionsService.SERVICE_INTERFACE, serviceName, userId, callbacks,
- bindInstantServiceAllowed, verbose, /* initialCapacity= */ 1);
+ context.getMainThreadHandler(), bindInstantServiceAllowed, verbose,
+ /* initialCapacity= */ 1);
}
@Override
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 219e046..199477c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -71,6 +71,7 @@
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkProperties;
@@ -3798,6 +3799,22 @@
mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
}
+ /** Register tethering event callback. */
+ @Override
+ public void registerTetheringEventCallback(ITetheringEventCallback callback,
+ String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+ mTethering.registerTetheringEventCallback(callback);
+ }
+
+ /** Unregister tethering event callback. */
+ @Override
+ public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
+ String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+ mTethering.unregisterTetheringEventCallback(callback);
+ }
+
// Called when we lose the default network and have no replacement yet.
// This will automatically be cleared after X seconds or a new default network
// becomes CONNECTED, whichever happens first. The timer is started by the
diff --git a/services/core/java/com/android/server/DynamicAndroidService.java b/services/core/java/com/android/server/DynamicAndroidService.java
index 12a3f02..8488941 100644
--- a/services/core/java/com/android/server/DynamicAndroidService.java
+++ b/services/core/java/com/android/server/DynamicAndroidService.java
@@ -118,7 +118,9 @@
if (gsiService.isGsiRunning()) {
return gsiService.disableGsiInstall();
} else {
- return gsiService.setGsiBootable() == 0;
+ final int status = gsiService.getGsiBootStatus();
+ final boolean singleBoot = (status == IGsiService.BOOT_STATUS_SINGLE_BOOT);
+ return gsiService.setGsiBootable(singleBoot) == 0;
}
}
@@ -129,6 +131,6 @@
@Override
public boolean commit() throws RemoteException {
- return getGsiService().setGsiBootable() == 0;
+ return getGsiService().setGsiBootable(true) == 0;
}
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index bbd51ad..c2a0611 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -3210,18 +3210,6 @@
continue;
}
- if (!reportLocationAccessNoThrow(
- receiver.mCallerIdentity.mPid,
- receiver.mCallerIdentity.mUid,
- receiver.mCallerIdentity.mPackageName,
- receiver.mAllowedResolutionLevel)) {
- if (D) {
- Log.d(TAG, "skipping loc update for no op app: " +
- receiver.mCallerIdentity.mPackageName);
- }
- continue;
- }
-
Location notifyLocation;
if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
notifyLocation = coarseLocation; // use coarse location
@@ -3238,6 +3226,20 @@
} else {
lastLoc.set(notifyLocation);
}
+ // Report location access before delivering location to the client. This will
+ // note location delivery to appOps, so it should be called only when a
+ // location is really being delivered to the client.
+ if (!reportLocationAccessNoThrow(
+ receiver.mCallerIdentity.mPid,
+ receiver.mCallerIdentity.mUid,
+ receiver.mCallerIdentity.mPackageName,
+ receiver.mAllowedResolutionLevel)) {
+ if (D) {
+ Log.d(TAG, "skipping loc update for no op app: "
+ + receiver.mCallerIdentity.mPackageName);
+ }
+ continue;
+ }
if (!receiver.callLocationChangedLocked(notifyLocation)) {
Slog.w(TAG, "RemoteException calling onLocationChanged on "
+ receiver);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index dc394d0..5582ad7 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -2512,6 +2512,10 @@
modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
}
}
+
+ // IPv6 link local should be activated always.
+ modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
+ new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
}
@Override
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 9fa0053..d6fdbe3 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1803,7 +1803,7 @@
synchronized (mRecords) {
TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
Context.TELEPHONY_SERVICE);
- mEmergencyNumberList = tm.getCurrentEmergencyNumberList();
+ mEmergencyNumberList = tm.getEmergencyNumberList();
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
new file mode 100644
index 0000000..e64ab78
--- /dev/null
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.INetd;
+import android.net.ITestNetworkManager;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
+import android.net.StringNetworkSpecifier;
+import android.net.TestNetworkInterface;
+import android.net.util.NetdService;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.UncheckedIOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/** @hide */
+class TestNetworkService extends ITestNetworkManager.Stub {
+ @NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
+ @NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
+ @NonNull private static final String TEST_TUN_PREFIX = "testtun";
+ @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
+
+ @NonNull private final Context mContext;
+ @NonNull private final INetworkManagementService mNMS;
+ @NonNull private final INetd mNetd;
+
+ @NonNull private final HandlerThread mHandlerThread;
+ @NonNull private final Handler mHandler;
+
+ // Native method stubs
+ private static native int jniCreateTun(@NonNull String iface);
+
+ @VisibleForTesting
+ protected TestNetworkService(
+ @NonNull Context context, @NonNull INetworkManagementService netManager) {
+ mHandlerThread = new HandlerThread("TestNetworkServiceThread");
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
+
+ mContext = checkNotNull(context, "missing Context");
+ mNMS = checkNotNull(netManager, "missing INetworkManagementService");
+ mNetd = checkNotNull(NetdService.getInstance(), "could not get netd instance");
+ }
+
+ /**
+ * Create a TUN interface with the given interface name and link addresses
+ *
+ * <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
+ * TUN interface.
+ */
+ @Override
+ public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
+ enforceTestNetworkPermissions(mContext);
+
+ checkNotNull(linkAddrs, "missing linkAddrs");
+
+ String iface = TEST_TUN_PREFIX + sTestTunIndex.getAndIncrement();
+ return Binder.withCleanCallingIdentity(
+ () -> {
+ try {
+ ParcelFileDescriptor tunIntf =
+ ParcelFileDescriptor.adoptFd(jniCreateTun(iface));
+ for (LinkAddress addr : linkAddrs) {
+ mNetd.interfaceAddAddress(
+ iface,
+ addr.getAddress().getHostAddress(),
+ addr.getPrefixLength());
+ }
+
+ return new TestNetworkInterface(tunIntf, iface);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ });
+ }
+
+ // Tracker for TestNetworkAgents
+ @GuardedBy("mTestNetworkTracker")
+ @NonNull
+ private final SparseArray<TestNetworkAgent> mTestNetworkTracker = new SparseArray<>();
+
+ public class TestNetworkAgent extends NetworkAgent implements IBinder.DeathRecipient {
+ private static final int NETWORK_SCORE = 1; // Use a low, non-zero score.
+
+ private final int mUid;
+ @NonNull private final NetworkInfo mNi;
+ @NonNull private final NetworkCapabilities mNc;
+ @NonNull private final LinkProperties mLp;
+
+ @GuardedBy("mBinderLock")
+ @NonNull
+ private IBinder mBinder;
+
+ @NonNull private final Object mBinderLock = new Object();
+
+ private TestNetworkAgent(
+ @NonNull Looper looper,
+ @NonNull Context context,
+ @NonNull NetworkInfo ni,
+ @NonNull NetworkCapabilities nc,
+ @NonNull LinkProperties lp,
+ int uid,
+ @NonNull IBinder binder)
+ throws RemoteException {
+ super(looper, context, TEST_NETWORK_TYPE, ni, nc, lp, NETWORK_SCORE);
+
+ mUid = uid;
+ mNi = ni;
+ mNc = nc;
+ mLp = lp;
+
+ synchronized (mBinderLock) {
+ mBinder = binder; // Binder null-checks in create()
+
+ try {
+ mBinder.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ binderDied();
+ throw e; // Abort, signal failure up the stack.
+ }
+ }
+ }
+
+ /**
+ * If the Binder object dies, this function is called to free the resources of this
+ * TestNetworkAgent
+ */
+ @Override
+ public void binderDied() {
+ teardown();
+ }
+
+ @Override
+ protected void unwanted() {
+ teardown();
+ }
+
+ private void teardown() {
+ mNi.setDetailedState(DetailedState.DISCONNECTED, null, null);
+ mNi.setIsAvailable(false);
+ sendNetworkInfo(mNi);
+
+ // Synchronize on mBinderLock to ensure that unlinkToDeath is never called more than
+ // once (otherwise it could throw an exception)
+ synchronized (mBinderLock) {
+ // If mBinder is null, this Test Network has already been cleaned up.
+ if (mBinder == null) return;
+ mBinder.unlinkToDeath(this, 0);
+ mBinder = null;
+ }
+
+ // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up
+ // resources, even for binder death or unwanted calls.
+ synchronized (mTestNetworkTracker) {
+ mTestNetworkTracker.remove(netId);
+ }
+ }
+ }
+
+ private TestNetworkAgent registerTestNetworkAgent(
+ @NonNull Looper looper,
+ @NonNull Context context,
+ @NonNull String iface,
+ int callingUid,
+ @NonNull IBinder binder)
+ throws RemoteException, SocketException {
+ checkNotNull(looper, "missing Looper");
+ checkNotNull(context, "missing Context");
+ // iface and binder validity checked by caller
+
+ // Build network info with special testing type
+ NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_TEST, 0, TEST_NETWORK_TYPE, "");
+ ni.setDetailedState(DetailedState.CONNECTED, null, null);
+ ni.setIsAvailable(true);
+
+ // Build narrow set of NetworkCapabilities, useful only for testing
+ NetworkCapabilities nc = new NetworkCapabilities();
+ nc.clearAll(); // Remove default capabilities.
+ nc.addTransportType(NetworkCapabilities.TRANSPORT_TEST);
+ nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
+ nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ nc.setNetworkSpecifier(new StringNetworkSpecifier(iface));
+
+ // Build LinkProperties
+ LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(iface);
+
+ // Find the currently assigned addresses, and add them to LinkProperties
+ boolean allowIPv4 = false, allowIPv6 = false;
+ NetworkInterface netIntf = NetworkInterface.getByName(iface);
+ checkNotNull(netIntf, "No such network interface found: " + netIntf);
+
+ for (InterfaceAddress intfAddr : netIntf.getInterfaceAddresses()) {
+ lp.addLinkAddress(
+ new LinkAddress(intfAddr.getAddress(), intfAddr.getNetworkPrefixLength()));
+
+ if (intfAddr.getAddress() instanceof Inet6Address) {
+ allowIPv6 |= !intfAddr.getAddress().isLinkLocalAddress();
+ } else if (intfAddr.getAddress() instanceof Inet4Address) {
+ allowIPv4 = true;
+ }
+ }
+
+ // Add global routes (but as non-default, non-internet providing network)
+ if (allowIPv4) {
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null, iface));
+ }
+ if (allowIPv6) {
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface));
+ }
+
+ return new TestNetworkAgent(looper, context, ni, nc, lp, callingUid, binder);
+ }
+
+ /**
+ * Sets up a Network with extremely limited privileges, guarded by the MANAGE_TEST_NETWORKS
+ * permission.
+ *
+ * <p>This method provides a Network that is useful only for testing.
+ */
+ @Override
+ public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
+ enforceTestNetworkPermissions(mContext);
+
+ checkNotNull(iface, "missing Iface");
+ checkNotNull(binder, "missing IBinder");
+
+ if (!(iface.startsWith(INetd.IPSEC_INTERFACE_PREFIX)
+ || iface.startsWith(TEST_TUN_PREFIX))) {
+ throw new IllegalArgumentException(
+ "Cannot create network for non ipsec, non-testtun interface");
+ }
+
+ // Setup needs to be done with NETWORK_STACK privileges.
+ int callingUid = Binder.getCallingUid();
+ Binder.withCleanCallingIdentity(
+ () -> {
+ try {
+ mNMS.setInterfaceUp(iface);
+
+ // Synchronize all accesses to mTestNetworkTracker to prevent the case
+ // where:
+ // 1. TestNetworkAgent successfully binds to death of binder
+ // 2. Before it is added to the mTestNetworkTracker, binder dies,
+ // binderDied() is called (on a different thread)
+ // 3. This thread is pre-empted, put() is called after remove()
+ synchronized (mTestNetworkTracker) {
+ TestNetworkAgent agent =
+ registerTestNetworkAgent(
+ mHandler.getLooper(),
+ mContext,
+ iface,
+ callingUid,
+ binder);
+
+ mTestNetworkTracker.put(agent.netId, agent);
+ }
+ } catch (SocketException e) {
+ throw new UncheckedIOException(e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ });
+ }
+
+ /** Teardown a test network */
+ @Override
+ public void teardownTestNetwork(int netId) {
+ enforceTestNetworkPermissions(mContext);
+
+ TestNetworkAgent agent;
+ synchronized (mTestNetworkTracker) {
+ agent = mTestNetworkTracker.get(netId);
+ }
+
+ if (agent == null) {
+ return; // Already torn down
+ } else if (agent.mUid != Binder.getCallingUid()) {
+ throw new SecurityException("Attempted to modify other user's test networks");
+ }
+
+ // Safe to be called multiple times.
+ agent.teardown();
+ }
+
+ // STOPSHIP: Change this back to android.Manifest.permission.MANAGE_TEST_NETWORKS
+ private static final String PERMISSION_NAME = "dummy";
+
+ public static void enforceTestNetworkPermissions(@NonNull Context context) {
+ // STOPSHIP: Re-enable these checks. Disabled until adoptShellPermissionIdentity() can be
+ // called from CTS test code.
+ if (false) {
+ context.enforceCallingOrSelfPermission(PERMISSION_NAME, "TestNetworkService");
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 5cca159..5d0fa26 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -111,6 +111,8 @@
// intensity level. It's important that we apply the scaling on the delta between the two so
// that the default intensity level applies no scaling to application provided effects.
private final SparseArray<ScaleLevel> mScaleLevels;
+ private final LinkedList<VibrationInfo> mPreviousRingVibrations;
+ private final LinkedList<VibrationInfo> mPreviousNotificationVibrations;
private final LinkedList<VibrationInfo> mPreviousVibrations;
private final int mPreviousVibrationsLimit;
private final boolean mAllowPriorityVibrationsInLowPowerMode;
@@ -354,6 +356,8 @@
mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode);
+ mPreviousRingVibrations = new LinkedList<>();
+ mPreviousNotificationVibrations = new LinkedList<>();
mPreviousVibrations = new LinkedList<>();
IntentFilter filter = new IntentFilter();
@@ -620,10 +624,19 @@
}
private void addToPreviousVibrationsLocked(Vibration vib) {
- if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
- mPreviousVibrations.removeFirst();
+ final LinkedList<VibrationInfo> previousVibrations;
+ if (vib.isRingtone()) {
+ previousVibrations = mPreviousRingVibrations;
+ } else if (vib.isNotification()) {
+ previousVibrations = mPreviousNotificationVibrations;
+ } else {
+ previousVibrations = mPreviousVibrations;
}
- mPreviousVibrations.addLast(vib.toInfo());
+
+ if (previousVibrations.size() > mPreviousVibrationsLimit) {
+ previousVibrations.removeFirst();
+ }
+ previousVibrations.addLast(vib.toInfo());
}
@Override // Binder call
@@ -1355,6 +1368,18 @@
pw.println(" mNotificationIntensity=" + mNotificationIntensity);
pw.println(" mRingIntensity=" + mRingIntensity);
pw.println("");
+ pw.println(" Previous ring vibrations:");
+ for (VibrationInfo info : mPreviousRingVibrations) {
+ pw.print(" ");
+ pw.println(info.toString());
+ }
+
+ pw.println(" Previous notification vibrations:");
+ for (VibrationInfo info : mPreviousNotificationVibrations) {
+ pw.print(" ");
+ pw.println(info.toString());
+ }
+
pw.println(" Previous vibrations:");
for (VibrationInfo info : mPreviousVibrations) {
pw.print(" ");
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 85322d6..57ce98c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1674,8 +1674,9 @@
int runSwitchUser(PrintWriter pw) throws RemoteException {
UserManager userManager = mInternal.mContext.getSystemService(UserManager.class);
- if (!userManager.canSwitchUsers()) {
- getErrPrintWriter().println("Error: disallowed switching user");
+ final int userSwitchable = userManager.getUserSwitchability();
+ if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
+ getErrPrintWriter().println("Error: " + userSwitchable);
return -1;
}
String user = getNextArgRequired();
diff --git a/services/core/java/com/android/server/am/BroadcastDispatcher.java b/services/core/java/com/android/server/am/BroadcastDispatcher.java
index b0b1840..d029482 100644
--- a/services/core/java/com/android/server/am/BroadcastDispatcher.java
+++ b/services/core/java/com/android/server/am/BroadcastDispatcher.java
@@ -450,6 +450,8 @@
return mCurrentBroadcast;
}
+ final boolean someQueued = !mOrderedBroadcasts.isEmpty();
+
BroadcastRecord next = null;
if (!mAlarmBroadcasts.isEmpty()) {
next = popLocked(mAlarmBroadcasts);
@@ -459,10 +461,18 @@
}
if (next == null && !mDeferredBroadcasts.isEmpty()) {
+ // We're going to deliver either:
+ // 1. the next "overdue" deferral; or
+ // 2. the next ordinary ordered broadcast; *or*
+ // 3. the next not-yet-overdue deferral.
+
for (int i = 0; i < mDeferredBroadcasts.size(); i++) {
Deferrals d = mDeferredBroadcasts.get(i);
- if (now < d.deferUntil) {
- // No more deferrals due
+ if (now < d.deferUntil && someQueued) {
+ // stop looking when we haven't hit the next time-out boundary
+ // but only if we have un-deferred broadcasts waiting,
+ // otherwise we can deliver whatever deferred broadcast
+ // is next available.
break;
}
@@ -483,7 +493,7 @@
}
}
- if (next == null && !mOrderedBroadcasts.isEmpty()) {
+ if (next == null && someQueued) {
next = mOrderedBroadcasts.remove(0);
if (DEBUG_BROADCAST_DEFERRAL) {
Slog.i(TAG, "Next broadcast from main queue: " + next);
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 47c9b86..5965d59 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -127,8 +127,7 @@
}
private boolean isServiceEnabled() {
- final String enabled = DeviceConfig.getProperty(NAMESPACE, SERVICE_ENABLED);
- return enabled == null ? DEFAULT_SERVICE_ENABLED : "true".equals(enabled);
+ return DeviceConfig.getBoolean(NAMESPACE, SERVICE_ENABLED, DEFAULT_SERVICE_ENABLED);
}
/**
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 9789688..1ac09ad 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -70,9 +70,8 @@
private static final long MAX_PAC_SIZE = 20 * 1000 * 1000;
// Return values for #setCurrentProxyScriptUrl
- enum ToSendOrNotToSendBroadcast {
- DONT_SEND_BROADCAST, DO_SEND_BROADCAST
- }
+ public static final boolean DONT_SEND_BROADCAST = false;
+ public static final boolean DO_SEND_BROADCAST = true;
private String mCurrentPac;
@GuardedBy("mProxyLock")
@@ -176,11 +175,11 @@
* @param proxy Proxy information that is about to be broadcast.
* @return Returns whether the broadcast should be sent : either DO_ or DONT_SEND_BROADCAST
*/
- synchronized ToSendOrNotToSendBroadcast setCurrentProxyScriptUrl(ProxyInfo proxy) {
+ synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) {
if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) {
// Allow to send broadcast, nothing to do.
- return ToSendOrNotToSendBroadcast.DO_SEND_BROADCAST;
+ return DO_SEND_BROADCAST;
}
mPacUrl = proxy.getPacFileUrl();
mCurrentDelay = DELAY_1;
@@ -188,7 +187,7 @@
mHasDownloaded = false;
getAlarmManager().cancel(mPacRefreshIntent);
bind();
- return ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST;
+ return DONT_SEND_BROADCAST;
} else {
getAlarmManager().cancel(mPacRefreshIntent);
synchronized (mProxyLock) {
@@ -204,7 +203,7 @@
}
}
}
- return ToSendOrNotToSendBroadcast.DO_SEND_BROADCAST;
+ return DO_SEND_BROADCAST;
}
}
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index a671287..e715890 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -208,8 +208,7 @@
public void sendProxyBroadcast() {
final ProxyInfo defaultProxy = getDefaultProxy();
final ProxyInfo proxyInfo = null != defaultProxy ? defaultProxy : new ProxyInfo("", 0, "");
- if (mPacManager.setCurrentProxyScriptUrl(proxyInfo)
- == PacManager.ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST) {
+ if (mPacManager.setCurrentProxyScriptUrl(proxyInfo) == PacManager.DONT_SEND_BROADCAST) {
return;
}
if (DBG) Slog.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 3b4b6f8..35704d40 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -62,6 +62,7 @@
import android.hardware.usb.UsbManager;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -82,6 +83,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
@@ -184,6 +186,9 @@
private final VersionedBroadcastListener mDefaultSubscriptionChange;
private final TetheringDependencies mDeps;
private final EntitlementManager mEntitlementMgr;
+ private final Handler mHandler;
+ private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
+ new RemoteCallbackList<>();
private volatile TetheringConfiguration mConfig;
private InterfaceSet mCurrentUpstreamIfaceSet;
@@ -193,6 +198,7 @@
private boolean mRndisEnabled; // track the RNDIS function enabled state
// True iff. WiFi tethering should be started when soft AP is ready.
private boolean mWifiTetherRequested;
+ private Network mTetherUpstream;
public Tethering(Context context, INetworkManagementService nmService,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
@@ -213,9 +219,9 @@
mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps);
mTetherMasterSM.start();
- final Handler smHandler = mTetherMasterSM.getHandler();
- mOffloadController = new OffloadController(smHandler,
- mDeps.getOffloadHardwareInterface(smHandler, mLog),
+ mHandler = mTetherMasterSM.getHandler();
+ mOffloadController = new OffloadController(mHandler,
+ mDeps.getOffloadHardwareInterface(mHandler, mLog),
mContext.getContentResolver(), mNMService,
mLog);
mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
@@ -227,7 +233,7 @@
mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM,
mLog, systemProperties);
mCarrierConfigChange = new VersionedBroadcastListener(
- "CarrierConfigChangeListener", mContext, smHandler, filter,
+ "CarrierConfigChangeListener", mContext, mHandler, filter,
(Intent ignored) -> {
mLog.log("OBSERVED carrier config change");
updateConfiguration();
@@ -237,7 +243,7 @@
filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mDefaultSubscriptionChange = new VersionedBroadcastListener(
- "DefaultSubscriptionChangeListener", mContext, smHandler, filter,
+ "DefaultSubscriptionChangeListener", mContext, mHandler, filter,
(Intent ignored) -> {
mLog.log("OBSERVED default data subscription change");
updateConfiguration();
@@ -248,14 +254,13 @@
// Load tethering configuration.
updateConfiguration();
- startStateMachineUpdaters();
+ startStateMachineUpdaters(mHandler);
}
- private void startStateMachineUpdaters() {
+ private void startStateMachineUpdaters(Handler handler) {
mCarrierConfigChange.startListening();
mDefaultSubscriptionChange.startListening();
- final Handler handler = mTetherMasterSM.getHandler();
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_STATE);
filter.addAction(CONNECTIVITY_ACTION);
@@ -1229,8 +1234,13 @@
sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
}
}
- mUpstreamNetworkMonitor.setCurrentUpstream((ns != null) ? ns.network : null);
setUpstreamNetwork(ns);
+ final Network newUpstream = (ns != null) ? ns.network : null;
+ if (mTetherUpstream != newUpstream) {
+ mTetherUpstream = newUpstream;
+ mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream);
+ reportUpstreamChanged(mTetherUpstream);
+ }
}
protected void setUpstreamNetwork(NetworkState ns) {
@@ -1413,6 +1423,10 @@
mUpstreamNetworkMonitor.stop();
notifyDownstreamsOfNewUpstreamIface(null);
handleNewUpstreamNetworkState(null);
+ if (mTetherUpstream != null) {
+ mTetherUpstream = null;
+ reportUpstreamChanged(null);
+ }
}
private boolean updateUpstreamWanted() {
@@ -1684,6 +1698,40 @@
}
}
+ /** Register tethering event callback */
+ public void registerTetheringEventCallback(ITetheringEventCallback callback) {
+ mHandler.post(() -> {
+ try {
+ callback.onUpstreamChanged(mTetherUpstream);
+ } catch (RemoteException e) {
+ // Not really very much to do here.
+ }
+ mTetheringEventCallbacks.register(callback);
+ });
+ }
+
+ /** Unregister tethering event callback */
+ public void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
+ mHandler.post(() -> {
+ mTetheringEventCallbacks.unregister(callback);
+ });
+ }
+
+ private void reportUpstreamChanged(Network network) {
+ final int length = mTetheringEventCallbacks.beginBroadcast();
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
+ } catch (RemoteException e) {
+ // Not really very much to do here.
+ }
+ }
+ } finally {
+ mTetheringEventCallbacks.finishBroadcast();
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
// Binder.java closes the resource for us.
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 59fffb4..8005dda 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1842,6 +1842,7 @@
config.interfaze = iface;
config.session = profile.name;
config.isMetered = false;
+ config.proxyInfo = profile.proxy;
config.addLegacyRoutes(profile.routes);
if (!profile.dnsServers.isEmpty()) {
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 1f28a6c..6d7dff5 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -216,7 +216,7 @@
private PackageManager mPackageManager;
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
- SensorManager sensorManager, BrightnessMappingStrategy mapper,
+ SensorManager sensorManager, Sensor lightSensor, BrightnessMappingStrategy mapper,
int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor,
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
@@ -249,7 +249,7 @@
new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);
if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
- mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+ mLightSensor = lightSensor;
}
mActivityTaskManager = ActivityTaskManager.getService();
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index af4db07..b0d8813 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -664,6 +664,12 @@
private void updateDisplayModes(int displayId) {
Display d = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
+ if (d == null) {
+ // We can occasionally get a display added or changed event for a display that was
+ // subsequently removed, which means this returns null. Check this case and bail
+ // out early; if it gets re-attached we'll eventually get another call back for it.
+ return;
+ }
DisplayInfo info = new DisplayInfo();
d.getDisplayInfo(info);
boolean changed = false;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 74cda9d..b79ead0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -44,6 +44,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.MathUtils;
import android.util.Slog;
import android.util.TimeUtils;
@@ -58,6 +59,7 @@
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
+import java.util.List;
/**
* Controls the power state of the display.
@@ -474,10 +476,14 @@
int shortTermModelTimeout = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout);
+ String lightSensorType = resources.getString(
+ com.android.internal.R.string.config_displayLightSensorType);
+ Sensor lightSensor = findDisplayLightSensor(lightSensorType);
+
mBrightnessMapper = BrightnessMappingStrategy.create(resources);
if (mBrightnessMapper != null) {
mAutomaticBrightnessController = new AutomaticBrightnessController(this,
- handler.getLooper(), sensorManager, mBrightnessMapper,
+ handler.getLooper(), sensorManager, lightSensor, mBrightnessMapper,
lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
@@ -530,6 +536,19 @@
mDisplayWhiteBalanceController = displayWhiteBalanceController;
}
+ private Sensor findDisplayLightSensor(String sensorType) {
+ if (!TextUtils.isEmpty(sensorType)) {
+ List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ for (int i = 0; i < sensors.size(); i++) {
+ Sensor sensor = sensors.get(i);
+ if (sensorType.equals(sensor.getStringType())) {
+ return sensor;
+ }
+ }
+ }
+ return mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+ }
+
/**
* Returns true if the proximity sensor screen-off function is available.
*/
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index b1e5510..2311776 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -1276,11 +1276,17 @@
}
boolean isActivatedSetting() {
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ return false;
+ }
return Secure.getIntForUser(getContext().getContentResolver(),
Secure.NIGHT_DISPLAY_ACTIVATED, 0, mCurrentUser) == 1;
}
int getColorTemperatureSetting() {
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ return NOT_SET;
+ }
return clampNightDisplayColorTemperature(Secure.getIntForUser(
getContext().getContentResolver(), Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE,
NOT_SET,
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3052330..150303a 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -949,7 +949,11 @@
}
}
- class ImmsBroadcastReceiver extends BroadcastReceiver {
+ /**
+ * {@link BroadcastReceiver} that is intended to listen to broadcasts sent to the system user
+ * only.
+ */
+ private final class ImmsBroadcastReceiverForSystemUser extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
@@ -977,6 +981,35 @@
}
/**
+ * {@link BroadcastReceiver} that is intended to listen to broadcasts sent to all the users.
+ */
+ private final class ImmsBroadcastReceiverForAllUsers extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
+ final PendingResult pendingResult = getPendingResult();
+ if (pendingResult == null) {
+ return;
+ }
+ // sender userId can be a real user ID or USER_ALL.
+ final int senderUserId = pendingResult.getSendingUserId();
+ if (senderUserId != UserHandle.USER_ALL) {
+ final int resolvedUserId = PER_PROFILE_IME_ENABLED
+ ? senderUserId : mUserManagerInternal.getProfileParentId(senderUserId);
+ if (resolvedUserId != mSettings.getCurrentUserId()) {
+ // A background user is trying to hide the dialog. Ignore.
+ return;
+ }
+ }
+ hideInputMethodMenu();
+ } else {
+ Slog.w(TAG, "Unexpected intent " + intent);
+ }
+ }
+ }
+
+ /**
* Handles {@link Intent#ACTION_LOCALE_CHANGED}.
*
* <p>Note: For historical reasons, {@link Intent#ACTION_LOCALE_CHANGED} has been sent to all
@@ -1544,36 +1577,18 @@
mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
mSettingsObserver.registerContentObserverLocked(currentUserId);
- final IntentFilter broadcastFilter = new IntentFilter();
- broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
- broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
- broadcastFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
- broadcastFilter.addAction(ACTION_SHOW_INPUT_METHOD_PICKER);
- mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
- mContext.registerReceiverAsUser(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // Intent is guaranteed to be ACTION_CLOSE_SYSTEM_DIALOGS here.
- final PendingResult pendingResult = getPendingResult();
- if (pendingResult == null) {
- return;
- }
- // sender userId can be a real user ID or USER_ALL.
- final int senderUserId = pendingResult.getSendingUserId();
- if (senderUserId != UserHandle.USER_ALL) {
- final int resolvedUserId = PER_PROFILE_IME_ENABLED
- ? senderUserId
- : mUserManagerInternal.getProfileParentId(senderUserId);
- if (resolvedUserId != mSettings.getCurrentUserId()) {
- // A background user is trying to hide the dialog. Ignore.
- return;
- }
- }
- hideInputMethodMenu();
- }
- }, UserHandle.ALL, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
- null, null);
+ final IntentFilter broadcastFilterForSystemUser = new IntentFilter();
+ broadcastFilterForSystemUser.addAction(Intent.ACTION_USER_ADDED);
+ broadcastFilterForSystemUser.addAction(Intent.ACTION_USER_REMOVED);
+ broadcastFilterForSystemUser.addAction(Intent.ACTION_LOCALE_CHANGED);
+ broadcastFilterForSystemUser.addAction(ACTION_SHOW_INPUT_METHOD_PICKER);
+ mContext.registerReceiver(new ImmsBroadcastReceiverForSystemUser(),
+ broadcastFilterForSystemUser);
+
+ final IntentFilter broadcastFilterForAllUsers = new IntentFilter();
+ broadcastFilterForAllUsers.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ mContext.registerReceiverAsUser(new ImmsBroadcastReceiverForAllUsers(),
+ UserHandle.ALL, broadcastFilterForAllUsers, null, null);
final String defaultImiId = mSettings.getSelectedInputMethod();
final boolean imeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
@@ -4675,9 +4690,11 @@
private int handleShellCommandEnableDisableInputMethod(
@NonNull ShellCommand shellCommand, boolean enabled) {
final String id = shellCommand.getNextArgRequired();
-
final boolean previouslyEnabled;
synchronized (mMethodMap) {
+ if (!userHasDebugPriv(mSettings.getCurrentUserId(), shellCommand)) {
+ return ShellCommandResult.SUCCESS;
+ }
previouslyEnabled = setInputMethodEnabledLocked(id, enabled);
}
final PrintWriter pr = shellCommand.getOutPrintWriter();
@@ -4699,6 +4716,9 @@
private int handleShellCommandSetInputMethod(@NonNull ShellCommand shellCommand) {
final String id = shellCommand.getNextArgRequired();
synchronized (mMethodMap) {
+ if (!userHasDebugPriv(mSettings.getCurrentUserId(), shellCommand)) {
+ return ShellCommandResult.SUCCESS;
+ }
setInputMethodLocked(id, NOT_A_SUBTYPE_ID);
}
final PrintWriter pr = shellCommand.getOutPrintWriter();
@@ -4717,6 +4737,9 @@
@ShellCommandResult
private int handleShellCommandResetInputMethod(@NonNull ShellCommand shellCommand) {
synchronized (mMethodMap) {
+ if (!userHasDebugPriv(mSettings.getCurrentUserId(), shellCommand)) {
+ return ShellCommandResult.SUCCESS;
+ }
final String nextIme;
final List<InputMethodInfo> nextEnabledImes;
hideCurrentInputLocked(0, null);
@@ -4754,6 +4777,22 @@
}
}
+ /**
+ * @param userId the actual user handle obtained by {@link UserHandle#getIdentifier()}
+ * and *not* pseudo ids like {@link UserHandle#USER_ALL etc}.
+ * @return {@code true} if userId has debugging privileges.
+ * i.e. {@link UserManager#DISALLOW_DEBUGGING_FEATURES} is {@code false}.
+ */
+ private boolean userHasDebugPriv(int userId, final ShellCommand shellCommand) {
+ if (mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.of(userId))) {
+ shellCommand.getErrPrintWriter().println("User #" + userId
+ + " is restricted with DISALLOW_DEBUGGING_FEATURES.");
+ return false;
+ }
+ return true;
+ }
+
private static final class InputMethodPrivilegedOperationsImpl
extends IInputMethodPrivilegedOperations.Stub {
private final InputMethodManagerService mImms;
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 500c388..a2515c8 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -29,6 +29,8 @@
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -44,6 +46,7 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.HandlerThread;
@@ -66,6 +69,7 @@
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSystemProperty;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.IMultiClientInputMethod;
import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations;
@@ -73,6 +77,8 @@
import com.android.internal.inputmethod.StartInputFlags;
import com.android.internal.inputmethod.StartInputReason;
import com.android.internal.inputmethod.UnbindReason;
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -96,8 +102,15 @@
* we can switch the implementation at the boot time.</p>
*/
public final class MultiClientInputMethodManagerService {
- static final String TAG = "MultiClientInputMethodManagerService";
- static final boolean DEBUG = false;
+ private static final String TAG = "MultiClientInputMethodManagerService";
+ private static final boolean DEBUG = false;
+
+ private static final String PER_DISPLAY_FOCUS_DISABLED_WARNING_TITLE =
+ "config_perDisplayFocusEnabled is not true.";
+
+ private static final String PER_DISPLAY_FOCUS_DISABLED_WARNING_MSG =
+ "Consider rebuilding the system image after enabling config_perDisplayFocusEnabled to "
+ + "make IME focus compatible with multi-client IME mode.";
private static final long RECONNECT_DELAY_MSEC = 1000;
@@ -465,8 +478,33 @@
onPackageAdded(intent);
}
}, filter, null, mHandler);
+ break;
}
- break;
+ case SystemService.PHASE_BOOT_COMPLETED: {
+ final boolean perDisplayFocusEnabled = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_perDisplayFocusEnabled);
+ if (!perDisplayFocusEnabled) {
+ final Bundle extras = new Bundle();
+ extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
+ mContext.getSystemService(NotificationManager.class).notifyAsUser(TAG,
+ SystemMessageProto.SystemMessage.NOTE_SELECT_INPUT_METHOD,
+ new Notification.Builder(mContext,
+ SystemNotificationChannels.VIRTUAL_KEYBOARD)
+ .setContentTitle(PER_DISPLAY_FOCUS_DISABLED_WARNING_TITLE)
+ .setStyle(new Notification.BigTextStyle()
+ .bigText(PER_DISPLAY_FOCUS_DISABLED_WARNING_MSG))
+ .setSmallIcon(R.drawable.ic_notification_ime_default)
+ .setWhen(0)
+ .setOngoing(true)
+ .setLocalOnly(true)
+ .addExtras(extras)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setColor(mContext.getColor(
+ R.color.system_notification_accent_color))
+ .build(), UserHandle.ALL);
+ }
+ break;
+ }
}
}
diff --git a/services/core/java/com/android/server/inputmethod/multi-client-ime.md b/services/core/java/com/android/server/inputmethod/multi-client-ime.md
index 3021d2f..ba92cd2 100644
--- a/services/core/java/com/android/server/inputmethod/multi-client-ime.md
+++ b/services/core/java/com/android/server/inputmethod/multi-client-ime.md
@@ -39,7 +39,9 @@
## How to test
-On AOSP-based development devices (e.g. phones) where `android.os.Build.IS_DEBUGGABLE` returns `true` and you can have root access, you can enable multi-client IME feature by setting a valid component name that supports multi-client IME protocol to the system property `persist.debug.multi_client_ime`. Reboot is required for this to take effect.
+For multi-client IME to properly work, an internal boolean resource `com.android.internal.R.bool.config_perDisplayFocusEnabled` needs to be `true`. Since this value cannot be overridden at the run time, you may need to rebuild the system image to enable per-display focus mode.
+
+As for multi-client IME mode itself, you can enable multi-client IME mode just by setting a valid component name that supports multi-client IME protocol to the system property `persist.debug.multi_client_ime`, as long as `android.os.Build.IS_DEBUGGABLE` returns `true` and you can have root access. Reboot is required for this to take effect.
```shell
# Build and install a sample multi-client IME
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 4f8b1dc..6255306 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -174,6 +174,7 @@
public void getRtcCorrectedJobsLocked(final ArrayList<JobStatus> toAdd,
final ArrayList<JobStatus> toRemove) {
final long elapsedNow = sElapsedRealtimeClock.millis();
+ final IActivityManager am = ActivityManager.getService();
// Find the jobs that need to be fixed up, collecting them for post-iteration
// replacement with their new versions
@@ -182,9 +183,11 @@
if (utcTimes != null) {
Pair<Long, Long> elapsedRuntimes =
convertRtcBoundsToElapsed(utcTimes, elapsedNow);
- toAdd.add(new JobStatus(job, job.getBaseHeartbeat(),
+ JobStatus newJob = new JobStatus(job, job.getBaseHeartbeat(),
elapsedRuntimes.first, elapsedRuntimes.second,
- 0, job.getLastSuccessfulRunTime(), job.getLastFailedRunTime()));
+ 0, job.getLastSuccessfulRunTime(), job.getLastFailedRunTime());
+ newJob.prepareLocked(am);
+ toAdd.add(newJob);
toRemove.add(job);
}
});
diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java
index 91b5234..0e9ee40 100644
--- a/services/core/java/com/android/server/location/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/GnssConfiguration.java
@@ -52,7 +52,6 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
// config.xml properties
@@ -191,8 +190,6 @@
return Collections.EMPTY_LIST;
}
- // TODO(b/122856486): Validate proxy app names so that a system app or some popular app
- // with location permission is not specified as a proxy app.
ArrayList proxyApps = new ArrayList(proxyAppsArray.length);
for (String proxyApp : proxyAppsArray) {
proxyApps.add(proxyApp);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 29030fa..c173d66 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -67,6 +67,7 @@
import android.util.Log;
import android.util.StatsLog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
@@ -890,12 +891,14 @@
return GPS_POSITION_MODE_STANDALONE;
}
- private boolean handleEnable() {
- if (DEBUG) Log.d(TAG, "handleEnable");
+ @GuardedBy("mLock")
+ private void handleEnableLocked() {
+ if (DEBUG) Log.d(TAG, "handleEnableLocked");
boolean inited = native_init();
if (inited) {
+ mEnabled = true;
mSupportsXtra = native_supports_xtra();
// TODO: remove the following native calls if we can make sure they are redundant.
@@ -912,15 +915,16 @@
mGnssNavigationMessageProvider.onGpsEnabledChanged();
mGnssBatchingProvider.enable();
} else {
+ mEnabled = false;
Log.w(TAG, "Failed to enable location provider");
}
-
- return inited;
}
- private void handleDisable() {
- if (DEBUG) Log.d(TAG, "handleDisable");
+ @GuardedBy("mLock")
+ private void handleDisableLocked() {
+ if (DEBUG) Log.d(TAG, "handleDisableLocked");
+ mEnabled = false;
updateClientUids(new WorkSource());
stopNavigating();
mAlarmManager.cancel(mWakeupIntent);
@@ -946,10 +950,9 @@
}
if (enabled) {
- mEnabled = handleEnable();
+ handleEnableLocked();
} else {
- mEnabled = false;
- handleDisable();
+ handleDisableLocked();
}
}
}
diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
index 90d16cb..c06b03b 100644
--- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
@@ -373,8 +373,8 @@
networkAttributes = new NetworkAttributes();
networkAttributes.mCapabilities = capabilities;
- // TODO(b/119278134): The synchronous method ConnectivityManager.getNetworkInfo() must
- // not be called inside the asynchronous ConnectivityManager.NetworkCallback methods.
+ // TODO: The synchronous method ConnectivityManager.getNetworkInfo() should not be called
+ // inside the asynchronous ConnectivityManager.NetworkCallback methods.
NetworkInfo info = mConnMgr.getNetworkInfo(network);
if (info != null) {
networkAttributes.mApn = info.getExtraInfo();
@@ -387,8 +387,8 @@
}
private void handleSuplConnectionAvailable(Network network) {
- // TODO(b/119278134): The synchronous method ConnectivityManager.getNetworkInfo() must
- // not be called inside the asynchronous ConnectivityManager.NetworkCallback methods.
+ // TODO: The synchronous method ConnectivityManager.getNetworkInfo() should not be called
+ // inside the asynchronous ConnectivityManager.NetworkCallback methods.
NetworkInfo info = mConnMgr.getNetworkInfo(network);
String apn = null;
if (info != null) {
@@ -509,8 +509,8 @@
}
}
- // TODO(25876485): Delete this method when all devices upgrade to HAL @2.0::IAGnssCallback
- // interface which does not require setting route to host.
+ // TODO: Delete this method when all devices upgrade to HAL @2.0::IAGnssCallback
+ // interface which does not require setting route to host.
private void setRouting() {
boolean result = mConnMgr.requestRouteToHostAddress(
ConnectivityManager.TYPE_MOBILE_SUPL,
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index 20f872a..24ee389 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -18,7 +18,6 @@
import android.annotation.SuppressLint;
import android.app.AppOpsManager;
-import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -32,11 +31,11 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.StatsLog;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -76,9 +75,9 @@
private boolean mIsDeviceLocationSettingsEnabled;
// Number of non-framework location access proxy apps is expected to be small (< 5).
- private static final int HASH_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
- private HashMap<String, Boolean> mProxyAppToLocationPermissions = new HashMap<>(
- HASH_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS);
+ private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
+ private ArrayMap<String, Boolean> mProxyAppToLocationPermissions = new ArrayMap<>(
+ ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS);
private PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
uid -> runOnHandler(() -> handlePermissionsChanged(uid));
@@ -97,10 +96,6 @@
}
void updateProxyApps(List<String> nfwLocationAccessProxyApps) {
- // NOTE: This class doesn't explicitly register and listen for SIM_STATE_CHANGED event
- // but rather piggy backs on the GnssLocationProvider SIM_STATE_CHANGED handling
- // so that the order of processing is preserved. GnssLocationProvider should
- // first load the new config parameters for the new SIM and then call this method.
runOnHandler(() -> handleUpdateProxyApps(nfwLocationAccessProxyApps));
}
@@ -246,15 +241,7 @@
// Represents NfwNotification structure in IGnssVisibilityControlCallback.hal
private static class NfwNotification {
- private static final String KEY_PROTOCOL_STACK = "ProtocolStack";
- private static final String KEY_OTHER_PROTOCOL_STACK_NAME = "OtherProtocolStackName";
- private static final String KEY_REQUESTOR = "Requestor";
- private static final String KEY_REQUESTOR_ID = "RequestorId";
- private static final String KEY_RESPONSE_TYPE = "ResponseType";
- private static final String KEY_IN_EMERGENCY_MODE = "InEmergencyMode";
- private static final String KEY_IS_CACHED_LOCATION = "IsCachedLocation";
-
- // This must match with NfwResponseType enum in IGnssVisibilityControlCallback.hal.
+ // These must match with NfwResponseType enum in IGnssVisibilityControlCallback.hal.
private static final byte NFW_RESPONSE_TYPE_REJECTED = 0;
private static final byte NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1;
private static final byte NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2;
@@ -281,30 +268,14 @@
mIsCachedLocation = isCachedLocation;
}
- private void copyFieldsToIntent(Intent intent) {
- intent.putExtra(KEY_PROTOCOL_STACK, mProtocolStack);
- if (!TextUtils.isEmpty(mOtherProtocolStackName)) {
- intent.putExtra(KEY_OTHER_PROTOCOL_STACK_NAME, mOtherProtocolStackName);
- }
- intent.putExtra(KEY_REQUESTOR, mRequestor);
- if (!TextUtils.isEmpty(mRequestorId)) {
- intent.putExtra(KEY_REQUESTOR_ID, mRequestorId);
- }
- intent.putExtra(KEY_RESPONSE_TYPE, mResponseType);
- intent.putExtra(KEY_IN_EMERGENCY_MODE, mInEmergencyMode);
- if (mResponseType == NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED) {
- intent.putExtra(KEY_IS_CACHED_LOCATION, mIsCachedLocation);
- }
- }
-
@SuppressLint("DefaultLocale")
public String toString() {
return String.format(
- "[Notification] proxyAppPackageName: %s, protocolStack: %d"
- + ", otherProtocolStackName: %s, requestor: %d, requestorId: %s"
- + ", responseType: %d, inEmergencyMode: %b, isCachedLocation: %b",
- mProxyAppPackageName, mProtocolStack, mOtherProtocolStackName,
- mRequestor, mRequestorId, mResponseType, mInEmergencyMode, mIsCachedLocation);
+ "{proxyAppPackageName: %s, protocolStack: %d, otherProtocolStackName: %s, "
+ + "requestor: %d, requestorId: %s, responseType: %s, inEmergencyMode:"
+ + " %b, isCachedLocation: %b}",
+ mProxyAppPackageName, mProtocolStack, mOtherProtocolStackName, mRequestor,
+ mRequestorId, getResponseTypeAsString(), mInEmergencyMode, mIsCachedLocation);
}
private String getResponseTypeAsString() {
@@ -405,7 +376,7 @@
}
private void handleNfwNotification(NfwNotification nfwNotification) {
- if (DEBUG) Log.d(TAG, nfwNotification.toString());
+ if (DEBUG) Log.d(TAG, "Non-framework location access notification: " + nfwNotification);
final String proxyAppPackageName = nfwNotification.mProxyAppPackageName;
Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
@@ -421,39 +392,27 @@
logEvent(nfwNotification, isPermissionMismatched);
if (TextUtils.isEmpty(proxyAppPackageName)) {
- Log.e(TAG, "ProxyAppPackageName field is not set. Not sending intent to proxy app for "
- + nfwNotification);
+ Log.e(TAG, "ProxyAppPackageName field is not set. AppOps service not notified "
+ + "for non-framework location access notification: " + nfwNotification);
return;
}
if (isLocationPermissionEnabled == null) {
- // App is not in the configured list.
- Log.e(TAG, "Could not find proxy app with name: " + proxyAppPackageName + " in the "
+ Log.w(TAG, "Could not find proxy app with name: " + proxyAppPackageName + " in the "
+ "value specified for config parameter: "
- + GnssConfiguration.CONFIG_NFW_PROXY_APPS + ". Not sending intent to proxy app"
- + " for " + nfwNotification);
- return;
- }
-
- // Send intent to non-framework location proxy app with notification information.
- final Intent intent = new Intent(
- proxyAppPackageName + NFW_INTENT_ACTION_NFW_LOCATION_ACCESS_SUFFIX);
- final String proxAppActivityName =
- proxyAppPackageName + NFW_PROXY_APP_PKG_ACTIVITY_NAME_SUFFIX;
- intent.setClassName(proxyAppPackageName, proxAppActivityName);
- intent.setType(NFW_INTENT_TYPE);
- nfwNotification.copyFieldsToIntent(intent);
-
- // Check if the proxy app is still installed.
- final Integer clsAppUid = getApplicationUid(proxyAppPackageName);
- if (clsAppUid == null || intent.resolveActivity(mPackageManager) == null) {
- Log.i(TAG, "Proxy application " + proxyAppPackageName + " and/or activity "
- + proxAppActivityName + " is not found. Not sending"
- + " intent to proxy app for " + nfwNotification);
+ + GnssConfiguration.CONFIG_NFW_PROXY_APPS + ". AppOps service not notified "
+ + "for non-framework location access notification: " + nfwNotification);
return;
}
// Display location icon attributed to this proxy app.
+ final Integer clsAppUid = getApplicationUid(proxyAppPackageName);
+ if (clsAppUid == null) {
+ Log.e(TAG, "Proxy app " + proxyAppPackageName + " is not found. AppOps service not "
+ + "notified for non-framework location access notification: "
+ + nfwNotification);
+ return;
+ }
mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, clsAppUid, proxyAppPackageName);
// Log proxy app permission mismatch between framework and GNSS HAL.
@@ -461,18 +420,8 @@
Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPackageName
+ " location permission is set to " + isLocationPermissionEnabled
+ " but GNSS non-framework location access response type is "
- + nfwNotification.getResponseTypeAsString() + " for " + nfwNotification);
- }
-
- // Notify proxy app.
- try {
- if (DEBUG) {
- Log.d(TAG, "Sending non-framework location access notification intent: " + intent);
- }
- mContext.startActivityAsUser(intent, UserHandle.getUserHandleForUid(clsAppUid));
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "Activity not found. Failed to send non-framework location access"
- + " notification intent to proxy app activity: " + proxAppActivityName);
+ + nfwNotification.getResponseTypeAsString() + " for notification: "
+ + nfwNotification);
}
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index b6995db..a53ab84 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -21,6 +21,7 @@
import static android.content.Context.KEYGUARD_SERVICE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
@@ -2648,7 +2649,8 @@
}
}
- private long addEscrowToken(byte[] token, int userId) throws RemoteException {
+ private long addEscrowToken(byte[] token, int userId, EscrowTokenStateChangeCallback callback)
+ throws RemoteException {
if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
synchronized (mSpManager) {
enableSyntheticPasswordLocked();
@@ -2672,7 +2674,7 @@
throw new SecurityException("Escrow token is disabled on the current user");
}
}
- long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId);
+ long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId, callback);
if (auth != null) {
mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
}
@@ -2943,9 +2945,10 @@
private final class LocalService extends LockSettingsInternal {
@Override
- public long addEscrowToken(byte[] token, int userId) {
+ public long addEscrowToken(byte[] token, int userId,
+ EscrowTokenStateChangeCallback callback) {
try {
- return LockSettingsService.this.addEscrowToken(token, userId);
+ return LockSettingsService.this.addEscrowToken(token, userId, callback);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index dbcfbcd..142ad53 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -16,6 +16,8 @@
package com.android.server.locksettings;
+import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
@@ -281,6 +283,7 @@
byte[] secdiscardableOnDisk;
byte[] weaverSecret;
byte[] aggregatedSecret;
+ EscrowTokenStateChangeCallback mCallback;
}
private final Context mContext;
@@ -746,7 +749,12 @@
private ArrayMap<Integer, ArrayMap<Long, TokenData>> tokenMap = new ArrayMap<>();
- public long createTokenBasedSyntheticPassword(byte[] token, int userId) {
+ /**
+ * Create a token based Synthetic password for the given user.
+ * @return
+ */
+ public long createTokenBasedSyntheticPassword(byte[] token, int userId,
+ @Nullable EscrowTokenStateChangeCallback changeCallback) {
long handle = generateHandle();
if (!tokenMap.containsKey(userId)) {
tokenMap.put(userId, new ArrayMap<>());
@@ -762,6 +770,7 @@
tokenData.weaverSecret = null;
}
tokenData.aggregatedSecret = transformUnderSecdiscardable(token, secdiscardable);
+ tokenData.mCallback = changeCallback;
tokenMap.get(userId).put(handle, tokenData);
return handle;
@@ -810,6 +819,9 @@
createSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_TOKEN_BASED, authToken,
tokenData.aggregatedSecret, 0L, userId);
tokenMap.get(userId).remove(handle);
+ if (tokenData.mCallback != null) {
+ tokenData.mCallback.onEscrowTokenActivated(handle, userId);
+ }
return true;
}
diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS
index 2e91f99..28ae6a4 100644
--- a/services/core/java/com/android/server/net/OWNERS
+++ b/services/core/java/com/android/server/net/OWNERS
@@ -1,12 +1,11 @@
set noparent
codewiz@google.com
-ek@google.com
jchalard@google.com
jsharkey@android.com
+junyulai@google.com
lorenzo@google.com
reminv@google.com
satk@google.com
-silberst@google.com
sudheersai@google.com
yamasani@google.com
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 7a87a57..0c0c23a 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -1112,7 +1112,7 @@
binder.linkToDeath(info, 0);
added = mServices.add(info);
} catch (RemoteException e) {
- // already dead
+ Slog.e(TAG, "Failed to linkToDeath, already dead", e);
}
}
if (added) {
@@ -1144,6 +1144,11 @@
}
}
}
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ Slog.v(TAG, "onNullBinding() called with: name = [" + name + "]");
+ }
};
if (!mContext.bindServiceAsUser(intent,
serviceConnection,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9281bf8..88e697c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -251,7 +251,6 @@
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
-import java.util.function.Predicate;
/** {@hide} */
public class NotificationManagerService extends SystemService {
@@ -759,7 +758,7 @@
synchronized (mNotificationLock) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r == null) {
- Log.w(TAG, "No notification with key: " + key);
+ Slog.w(TAG, "No notification with key: " + key);
return;
}
final long now = System.currentTimeMillis();
@@ -789,7 +788,7 @@
synchronized (mNotificationLock) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r == null) {
- Log.w(TAG, "No notification with key: " + key);
+ Slog.w(TAG, "No notification with key: " + key);
return;
}
final long now = System.currentTimeMillis();
@@ -2477,29 +2476,27 @@
checkCallerIsSameApp(callingPkg);
final int callingUid = Binder.getCallingUid();
UserHandle user = UserHandle.getUserHandleForUid(callingUid);
- try {
- ApplicationInfo info =
- mPackageManager.getApplicationInfo(delegate,
- MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
- if (info != null) {
- mPreferencesHelper.setNotificationDelegate(
- callingPkg, callingUid, delegate, info.uid);
- handleSavePolicyFile();
+ if (delegate == null) {
+ mPreferencesHelper.revokeNotificationDelegate(callingPkg, Binder.getCallingUid());
+ handleSavePolicyFile();
+ } else {
+ try {
+ ApplicationInfo info =
+ mPackageManager.getApplicationInfo(delegate,
+ MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+ user.getIdentifier());
+ if (info != null) {
+ mPreferencesHelper.setNotificationDelegate(
+ callingPkg, callingUid, delegate, info.uid);
+ handleSavePolicyFile();
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
}
- } catch (RemoteException e) {
- // :(
}
}
@Override
- public void revokeNotificationDelegate(String callingPkg) {
- checkCallerIsSameApp(callingPkg);
- mPreferencesHelper.revokeNotificationDelegate(callingPkg, Binder.getCallingUid());
- handleSavePolicyFile();
- }
-
- @Override
public String getNotificationDelegate(String callingPkg) {
// callable by Settings also
checkCallerIsSystemOrSameApp(callingPkg);
@@ -3135,7 +3132,7 @@
synchronized (mNotificationLock) {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
if (info.supportsProfiles()) {
- Log.e(TAG, "Ignoring deprecated cancelNotification(pkg, tag, id) "
+ Slog.e(TAG, "Ignoring deprecated cancelNotification(pkg, tag, id) "
+ "from " + info.component
+ " use cancelNotification(key) instead.");
} else {
@@ -4555,7 +4552,7 @@
+ ", incomingUserId=" + incomingUserId
+ ", notificationUid=" + notificationUid
+ ", notification=" + notification;
- Log.e(TAG, noChannelStr);
+ Slog.e(TAG, noChannelStr);
boolean appNotificationsOff = mPreferencesHelper.getImportance(pkg, notificationUid)
== NotificationManager.IMPORTANCE_NONE;
@@ -4652,7 +4649,7 @@
android.Manifest.permission.USE_FULL_SCREEN_INTENT, pkg);
if (fullscreenIntentPermission != PERMISSION_GRANTED) {
notification.fullScreenIntent = null;
- Log.w(TAG, "Package " + pkg +
+ Slog.w(TAG, "Package " + pkg +
": Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission");
}
}
@@ -5181,7 +5178,7 @@
// Ignore summary updates because we don't display most of the information.
if (r.sbn.isGroup() && r.sbn.getNotification().isGroupSummary()) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is not interruptive: summary");
}
return false;
@@ -5189,7 +5186,7 @@
if (old == null) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is interruptive: new notification");
}
return true;
@@ -5197,7 +5194,7 @@
if (r == null) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is not interruptive: null");
}
return false;
@@ -5208,7 +5205,7 @@
if (oldN.extras == null || newN.extras == null) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is not interruptive: no extras");
}
return false;
@@ -5218,7 +5215,7 @@
// consider them one 'session'. Count them for everything else.
if ((r.sbn.getNotification().flags & FLAG_FOREGROUND_SERVICE) != 0) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is not interruptive: foreground service");
}
return false;
@@ -5228,11 +5225,11 @@
final String newTitle = String.valueOf(newN.extras.get(Notification.EXTRA_TITLE));
if (!Objects.equals(oldTitle, newTitle)) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is interruptive: changed title");
- Log.v(TAG, "INTERRUPTIVENESS: " + String.format(" old title: %s (%s@0x%08x)",
+ Slog.v(TAG, "INTERRUPTIVENESS: " + String.format(" old title: %s (%s@0x%08x)",
oldTitle, oldTitle.getClass(), oldTitle.hashCode()));
- Log.v(TAG, "INTERRUPTIVENESS: " + String.format(" new title: %s (%s@0x%08x)",
+ Slog.v(TAG, "INTERRUPTIVENESS: " + String.format(" new title: %s (%s@0x%08x)",
newTitle, newTitle.getClass(), newTitle.hashCode()));
}
return true;
@@ -5242,18 +5239,18 @@
final String newText = String.valueOf(newN.extras.get(Notification.EXTRA_TEXT));
if (!Objects.equals(oldText, newText)) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is interruptive: changed text");
- Log.v(TAG, "INTERRUPTIVENESS: " + String.format(" old text: %s (%s@0x%08x)",
+ Slog.v(TAG, "INTERRUPTIVENESS: " + String.format(" old text: %s (%s@0x%08x)",
oldText, oldText.getClass(), oldText.hashCode()));
- Log.v(TAG, "INTERRUPTIVENESS: " + String.format(" new text: %s (%s@0x%08x)",
+ Slog.v(TAG, "INTERRUPTIVENESS: " + String.format(" new text: %s (%s@0x%08x)",
newText, newText.getClass(), newText.hashCode()));
}
return true;
}
if (oldN.hasCompletedProgress() != newN.hasCompletedProgress()) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is interruptive: completed progress");
}
return true;
@@ -5261,7 +5258,7 @@
// Actions
if (Notification.areActionsVisiblyDifferent(oldN, newN)) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is interruptive: changed actions");
}
return true;
@@ -5274,7 +5271,7 @@
// Style based comparisons
if (Notification.areStyledNotificationsVisiblyDifferent(oldB, newB)) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is interruptive: styles differ");
}
return true;
@@ -5283,7 +5280,7 @@
// Remote views
if (Notification.areRemoteViewsChanged(oldB, newB)) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ r.getKey() + " is interruptive: remoteviews differ");
}
return true;
@@ -5512,12 +5509,12 @@
// Ignore summary updates because we don't display most of the information.
if (record.sbn.isGroup() && record.sbn.getNotification().isGroupSummary()) {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ record.getKey() + " is not interruptive: summary");
}
} else {
if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
+ Slog.v(TAG, "INTERRUPTIVENESS: "
+ record.getKey() + " is interruptive: alerted");
}
record.setInterruptive(true);
@@ -6605,7 +6602,7 @@
String pkg = r.sbn.getPackageName();
if (pkg == null) {
- if (DBG) Log.e(TAG, "No package for group summary: " + r.getKey());
+ if (DBG) Slog.e(TAG, "No package for group summary: " + r.getKey());
return;
}
@@ -6864,7 +6861,7 @@
return;
}
} catch (RemoteException re) {
- if (DBG) Log.e(TAG, "Unable to confirm if it's safe to skip category "
+ if (DBG) Slog.e(TAG, "Unable to confirm if it's safe to skip category "
+ "restrictions check thus the check will be done anyway");
}
if (Notification.CATEGORY_CAR_EMERGENCY.equals(notification.category)
@@ -7106,7 +7103,7 @@
canUseManagedServices = false;
}
} catch (RemoteException e) {
- Log.e(TAG, "can't talk to pm", e);
+ Slog.e(TAG, "can't talk to pm", e);
}
}
@@ -7196,7 +7193,7 @@
@Override
protected String getRequiredPermission() {
- // only signature/privileged apps can be bound
+ // only signature/privileged apps can be bound.
return android.Manifest.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE;
}
@@ -7249,21 +7246,29 @@
try {
assistant.onNotificationsSeen(keys);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify assistant (seen): " + assistant, ex);
+ Slog.e(TAG, "unable to notify assistant (seen): " + assistant, ex);
}
}
@GuardedBy("mNotificationLock")
private void onNotificationEnqueuedLocked(final NotificationRecord r) {
+ final boolean debug = isVerboseLogEnabled();
+ if (debug) {
+ Slog.v(TAG, "onNotificationEnqueuedLocked() called with: r = [" + r + "]");
+ }
final StatusBarNotification sbn = r.sbn;
notifyAssistantLocked(
sbn,
true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
+ if (debug) {
+ Slog.v(TAG,
+ "calling onNotificationEnqueuedWithChannel " + sbnHolder);
+ }
assistant.onNotificationEnqueuedWithChannel(sbnHolder, r.getChannel());
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
+ Slog.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
}
});
}
@@ -7281,7 +7286,7 @@
try {
assistant.onNotificationExpansionChanged(key, isUserAction, isExpanded);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify assistant (expanded): " + assistant, ex);
+ Slog.e(TAG, "unable to notify assistant (expanded): " + assistant, ex);
}
});
}
@@ -7297,7 +7302,7 @@
try {
assistant.onNotificationDirectReply(key);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify assistant (expanded): " + assistant, ex);
+ Slog.e(TAG, "unable to notify assistant (expanded): " + assistant, ex);
}
});
}
@@ -7318,7 +7323,7 @@
? NotificationAssistantService.SOURCE_FROM_ASSISTANT
: NotificationAssistantService.SOURCE_FROM_APP);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify assistant (snoozed): " + assistant, ex);
+ Slog.e(TAG, "unable to notify assistant (snoozed): " + assistant, ex);
}
});
}
@@ -7340,7 +7345,7 @@
? NotificationAssistantService.SOURCE_FROM_ASSISTANT
: NotificationAssistantService.SOURCE_FROM_APP);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify assistant (snoozed): " + assistant, ex);
+ Slog.e(TAG, "unable to notify assistant (snoozed): " + assistant, ex);
}
});
}
@@ -7360,7 +7365,7 @@
assistant.onNotificationSnoozedUntilContext(
sbnHolder, snoozeCriterionId);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify assistant (snoozed): " + assistant, ex);
+ Slog.e(TAG, "unable to notify assistant (snoozed): " + assistant, ex);
}
});
}
@@ -7382,9 +7387,19 @@
TrimCache trimCache = new TrimCache(sbn);
// There should be only one, but it's a list, so while we enforce
// singularity elsewhere, we keep it general here, to avoid surprises.
+
+ final boolean debug = isVerboseLogEnabled();
+ if (debug) {
+ Slog.v(TAG,
+ "notifyAssistantLocked() called with: sbn = [" + sbn + "], sameUserOnly = ["
+ + sameUserOnly + "], callback = [" + callback + "]");
+ }
for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
boolean sbnVisible = isVisibleToListener(sbn, info)
&& (!sameUserOnly || info.isSameUser(sbn.getUserId()));
+ if (debug) {
+ Slog.v(TAG, "notifyAssistantLocked info=" + info + " snbVisible=" + sbnVisible);
+ }
if (!sbnVisible) {
continue;
}
@@ -7438,6 +7453,10 @@
}
}
}
+
+ private boolean isVerboseLogEnabled() {
+ return Log.isLoggable("notification_assistant", Log.VERBOSE);
+ }
}
public class NotificationListeners extends ManagedServices {
@@ -7532,7 +7551,7 @@
try {
listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify listener "
+ Slog.e(TAG, "unable to notify listener "
+ "(hideSilentStatusIcons): " + listener, ex);
}
});
@@ -7826,7 +7845,7 @@
try {
listener.onNotificationPosted(sbnHolder, rankingUpdate);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
+ Slog.e(TAG, "unable to notify listener (posted): " + listener, ex);
}
}
@@ -7840,7 +7859,7 @@
try {
listener.onNotificationRemoved(sbnHolder, rankingUpdate, stats, reason);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
+ Slog.e(TAG, "unable to notify listener (removed): " + listener, ex);
}
}
@@ -7850,7 +7869,7 @@
try {
listener.onNotificationRankingUpdate(rankingUpdate);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify listener (ranking update): " + listener, ex);
+ Slog.e(TAG, "unable to notify listener (ranking update): " + listener, ex);
}
}
@@ -7859,7 +7878,7 @@
try {
listener.onListenerHintsChanged(hints);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify listener (listener hints): " + listener, ex);
+ Slog.e(TAG, "unable to notify listener (listener hints): " + listener, ex);
}
}
@@ -7869,7 +7888,7 @@
try {
listener.onInterruptionFilterChanged(interruptionFilter);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify listener (interruption filter): " + listener, ex);
+ Slog.e(TAG, "unable to notify listener (interruption filter): " + listener, ex);
}
}
@@ -7880,7 +7899,7 @@
try {
listener.onNotificationChannelModification(pkg, user, channel, modificationType);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify listener (channel changed): " + listener, ex);
+ Slog.e(TAG, "unable to notify listener (channel changed): " + listener, ex);
}
}
@@ -7891,7 +7910,7 @@
try {
listener.onNotificationChannelGroupModification(pkg, user, group, modificationType);
} catch (RemoteException ex) {
- Log.e(TAG, "unable to notify listener (channel group changed): " + listener, ex);
+ Slog.e(TAG, "unable to notify listener (channel group changed): " + listener, ex);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 48818f5..46ce4bf 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -637,25 +637,17 @@
final ArrayList<String> people =
adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE);
setPeopleOverride(people);
- MetricsLogger.action(getAdjustmentLogMaker()
- .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_PEOPLE, people.size()));
}
if (signals.containsKey(Adjustment.KEY_SNOOZE_CRITERIA)) {
final ArrayList<SnoozeCriterion> snoozeCriterionList =
adjustment.getSignals().getParcelableArrayList(
Adjustment.KEY_SNOOZE_CRITERIA);
setSnoozeCriteria(snoozeCriterionList);
- MetricsLogger.action(getAdjustmentLogMaker()
- .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SNOOZE_CRITERIA,
- snoozeCriterionList.size()));
}
if (signals.containsKey(Adjustment.KEY_GROUP_KEY)) {
final String groupOverrideKey =
adjustment.getSignals().getString(Adjustment.KEY_GROUP_KEY);
setOverrideGroupKey(groupOverrideKey);
- MetricsLogger.action(getAdjustmentLogMaker()
- .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_GROUP_KEY,
- groupOverrideKey));
}
if (signals.containsKey(Adjustment.KEY_USER_SENTIMENT)) {
// Only allow user sentiment update from assistant if user hasn't already
@@ -664,32 +656,20 @@
&& (getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0) {
setUserSentiment(adjustment.getSignals().getInt(
Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL));
- MetricsLogger.action(getAdjustmentLogMaker()
- .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_USER_SENTIMENT,
- getUserSentiment()));
}
}
if (signals.containsKey(Adjustment.KEY_CONTEXTUAL_ACTIONS)) {
setSystemGeneratedSmartActions(
signals.getParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS));
- MetricsLogger.action(getAdjustmentLogMaker()
- .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_ACTIONS,
- getSystemGeneratedSmartActions().size()));
}
if (signals.containsKey(Adjustment.KEY_TEXT_REPLIES)) {
setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_TEXT_REPLIES));
- MetricsLogger.action(getAdjustmentLogMaker()
- .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_REPLIES,
- getSmartReplies().size()));
}
if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) {
int importance = signals.getInt(Adjustment.KEY_IMPORTANCE);
importance = Math.max(IMPORTANCE_UNSPECIFIED, importance);
importance = Math.min(IMPORTANCE_HIGH, importance);
setAssistantImportance(importance);
- MetricsLogger.action(getAdjustmentLogMaker()
- .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_IMPORTANCE,
- importance));
}
}
// We have now gotten all the information out of the adjustments and can forget them.
@@ -1280,12 +1260,6 @@
return getLogMaker().setCategory(MetricsEvent.NOTIFICATION_ITEM);
}
- public LogMaker getAdjustmentLogMaker() {
- return getLogMaker()
- .setCategory(MetricsEvent.NOTIFICATION_ITEM)
- .setType(MetricsEvent.TYPE_NOTIFICATION_ASSISTANT_ADJUSTMENT);
- }
-
@VisibleForTesting
static final class Light {
public final int color;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a3b72fd..3a4bcca 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -482,9 +482,9 @@
}
if (callingUid == Process.SYSTEM_UID) {
- params.installFlags |= PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE;
+ params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
} else {
- params.installFlags &= ~PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE;
+ params.installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;
}
boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 251b34bc..4dcab5e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -14702,6 +14702,9 @@
DeviceConfig.Rollback.NAMESPACE,
DeviceConfig.Rollback.ENABLE_ROLLBACK_TIMEOUT,
DEFAULT_ENABLE_ROLLBACK_TIMEOUT);
+ if (rollbackTimeout < 0) {
+ rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT;
+ }
final Message msg = mHandler.obtainMessage(
ENABLE_ROLLBACK_TIMEOUT);
msg.arg1 = enableRollbackToken;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index ff81ad5..a12005b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -820,9 +820,9 @@
// platform builds.
//
// In case of user builds, downgrade is permitted only for the system server initiated
- // sessions. This is enforced by INSTALL_RESPECT_ALLOW_DOWNGRADE flag parameter.
+ // sessions. This is enforced by INSTALL_ALLOW_DOWNGRADE flag parameter.
final boolean downgradeRequested =
- (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+ (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
if (!downgradeRequested) {
return false;
}
@@ -832,7 +832,7 @@
if (isDebuggable) {
return true;
}
- return (installFlags & PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE) != 0;
+ return (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 114810d..912a50e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2337,7 +2337,7 @@
sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
break;
case "-d":
- sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
+ sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
break;
case "-g":
sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 59e5d77..aced1a2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -979,7 +979,7 @@
// Try to revoke as an install permission which is for all users.
// The package is gone - no need to keep flags for applying policy.
permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
+ PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
if (permissionsState.revokeInstallPermission(bp) ==
PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
@@ -2165,7 +2165,7 @@
XmlUtils.skipCurrentTag(parser);
} else {
permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS, flags);
+ PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
}
} else {
if (permissionsState.revokeInstallPermission(bp) ==
@@ -2174,7 +2174,7 @@
XmlUtils.skipCurrentTag(parser);
} else {
permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS, flags);
+ PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
}
}
} else {
@@ -5240,7 +5240,7 @@
if (bp != null) {
permissionsState.revokeRuntimePermission(bp, userId);
permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
+ PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
}
}
}
@@ -5354,10 +5354,10 @@
if (granted) {
permissionsState.grantRuntimePermission(bp, userId);
permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS, flags);
+ PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
} else {
permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS, flags);
+ PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
}
} break;
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 22a85eb..4ee6eaf 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -35,6 +35,7 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.Signature;
import android.content.rollback.IRollbackManager;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -117,9 +118,11 @@
final PackageInfo packageInfo = mApexManager.getActivePackage(packageName);
if (packageInfo == null) {
- // TODO: What is the right thing to do here ? This implies there's no active package
- // with the given name. This should never be the case in production (where we only
- // accept updates to existing APEXes) but may be required for testing.
+ // Only allow installing new apexes if on a debuggable build.
+ if (!Build.IS_DEBUGGABLE) {
+ Slog.w(TAG, "Attempted to install new apex " + packageName + " on user build");
+ return false;
+ }
return true;
}
@@ -498,19 +501,21 @@
Slog.w(TAG, "Cannot abort applied session!");
return;
}
- if (isStagedSessionFinalized(session.sessionId)) {
- Slog.w(TAG, "Cannot abort session because it is not active or APEXD is not reachable");
- return;
- }
-
- mApexManager.abortActiveSession();
-
abortSession(session);
+
+ boolean hasApex = sessionContainsApex(session);
+ if (hasApex) {
+ ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(session.sessionId);
+ if (apexSession == null || isApexSessionFinalized(apexSession)) {
+ Slog.w(TAG,
+ "Cannot abort session because it is not active or APEXD is not reachable");
+ return;
+ }
+ mApexManager.abortActiveSession();
+ }
}
- private boolean isStagedSessionFinalized(int sessionId) {
- ApexSessionInfo session = mApexManager.getStagedSessionInfo(sessionId);
-
+ private boolean isApexSessionFinalized(ApexSessionInfo session) {
/* checking if the session is in a final state, i.e., not active anymore */
return session.isUnknown || session.isActivationFailed || session.isSuccess
|| session.isRolledBack;
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 7e4365d..ae4ff03 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -120,6 +120,7 @@
UserManager.DISALLOW_UNMUTE_DEVICE,
UserManager.DISALLOW_AUTOFILL,
UserManager.DISALLOW_CONTENT_CAPTURE,
+ UserManager.DISALLOW_CONTENT_SUGGESTIONS,
UserManager.DISALLOW_USER_SWITCH,
UserManager.DISALLOW_UNIFIED_PASSWORD,
UserManager.DISALLOW_CONFIG_LOCATION,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index ac7338e..f7d8e0e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -32,7 +32,7 @@
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
-import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS;
+import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.UserHandle.getAppId;
import static android.os.UserHandle.getUid;
@@ -980,7 +980,7 @@
// Revoke the runtime permission and clear the flags.
origPermissions.revokeRuntimePermission(bp, userId);
origPermissions.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
+ PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
// If we revoked a permission permission, we have to write.
updatedUserIds = ArrayUtils.appendInt(
updatedUserIds, userId);
@@ -1043,7 +1043,7 @@
}
permissionsState.updatePermissionFlags(bp, userId,
- MASK_PERMISSION_FLAGS, flags);
+ MASK_PERMISSION_FLAGS_ALL, flags);
}
} break;
@@ -1058,7 +1058,7 @@
if (origPermissions.revokeInstallPermission(bp)
!= PERMISSION_OPERATION_FAILURE) {
origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
+ MASK_PERMISSION_FLAGS_ALL, 0);
changedInstallPermission = true;
}
@@ -1094,7 +1094,7 @@
}
permissionsState.updatePermissionFlags(bp, userId,
- MASK_PERMISSION_FLAGS, flags);
+ MASK_PERMISSION_FLAGS_ALL, flags);
}
} break;
@@ -1114,7 +1114,7 @@
PERMISSION_OPERATION_FAILURE) {
// Also drop the permission flags.
permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
+ MASK_PERMISSION_FLAGS_ALL, 0);
changedInstallPermission = true;
Slog.i(TAG, "Un-granting permission " + perm
+ " from package " + pkg.packageName
@@ -2180,7 +2180,7 @@
if (bp != null) {
permissionsState.revokeInstallPermission(bp);
permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
+ MASK_PERMISSION_FLAGS_ALL, 0);
}
}
}
@@ -2199,7 +2199,7 @@
if (bp != null) {
permissionsState.revokeRuntimePermission(bp, userId);
permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
+ MASK_PERMISSION_FLAGS_ALL, 0);
runtimePermissionChangedUserIds = ArrayUtils.appendInt(
runtimePermissionChangedUserIds, userId);
}
@@ -2229,7 +2229,7 @@
return 0;
}
- enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
+ enforceGrantRevokeGetRuntimePermissionPermissions("getPermissionFlags");
enforceCrossUserPermission(callingUid, userId,
true, // requireFullPermission
@@ -2596,6 +2596,20 @@
}
}
+ private void enforceGrantRevokeGetRuntimePermissionPermissions(@NonNull String message) {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
+ != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
+ != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(message + " requires "
+ + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
+ + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS + " or "
+ + Manifest.permission.GET_RUNTIME_PERMISSIONS);
+ }
+ }
+
/**
* Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
* or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 7d03d82..16d11ef 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -89,9 +89,6 @@
@GuardedBy("mLock")
private ArrayMap<String, Temperature> mTemperatureMap = new ArrayMap<>();
- /** Local PMS handle. */
- private final PowerManager mPowerManager;
-
/** HAL wrapper. */
private ThermalHalWrapper mHalWrapper;
@@ -109,7 +106,6 @@
@VisibleForTesting
ThermalManagerService(Context context, @Nullable ThermalHalWrapper halWrapper) {
super(context);
- mPowerManager = context.getSystemService(PowerManager.class);
mHalWrapper = halWrapper;
// Initialize to invalid to send status onActivityManagerReady
mStatus = INVALID_THROTTLING;
@@ -254,10 +250,11 @@
}
}
- private void shutdownIfNeededLocked(Temperature temperature) {
+ private void shutdownIfNeeded(Temperature temperature) {
if (temperature.getStatus() != Temperature.THROTTLING_SHUTDOWN) {
return;
}
+ final PowerManager powerManager = getContext().getSystemService(PowerManager.class);
switch (temperature.getType()) {
case Temperature.TYPE_CPU:
// Fall through
@@ -266,17 +263,17 @@
case Temperature.TYPE_NPU:
// Fall through
case Temperature.TYPE_SKIN:
- mPowerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false);
+ powerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false);
break;
case Temperature.TYPE_BATTERY:
- mPowerManager.shutdown(false, PowerManager.SHUTDOWN_BATTERY_THERMAL_STATE, false);
+ powerManager.shutdown(false, PowerManager.SHUTDOWN_BATTERY_THERMAL_STATE, false);
break;
}
}
private void onTemperatureChanged(Temperature temperature, boolean sendStatus) {
+ shutdownIfNeeded(temperature);
synchronized (mLock) {
- shutdownIfNeededLocked(temperature);
Temperature old = mTemperatureMap.put(temperature.getName(), temperature);
if (old != null) {
if (old.getStatus() != temperature.getStatus()) {
diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
deleted file mode 100644
index 4fb40db..0000000
--- a/services/core/java/com/android/server/role/RemoteRoleControllerService.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2018 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.role;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.annotation.WorkerThread;
-import android.app.role.IRoleManagerCallback;
-import android.app.role.RoleManager;
-import android.app.role.RoleManagerCallback;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.rolecontrollerservice.IRoleControllerService;
-import android.rolecontrollerservice.RoleControllerService;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.server.FgThread;
-
-import java.util.ArrayDeque;
-import java.util.Arrays;
-import java.util.Queue;
-
-/**
- * Handles connection with {@link RoleControllerService}.
- */
-public class RemoteRoleControllerService {
-
- static final boolean DEBUG = false;
- private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName();
-
- @NonNull
- private final Connection mConnection;
-
- public RemoteRoleControllerService(@UserIdInt int userId, @NonNull Context context) {
- mConnection = new Connection(userId, context);
- }
-
- /**
- * Add a specific application to the holders of a role. If the role is exclusive, the previous
- * holder will be replaced.
- *
- * @see RoleControllerService#onAddRoleHolder(String, String, int, RoleManagerCallback)
- */
- public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
- @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
- mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) ->
- service.onAddRoleHolder(roleName, packageName, flags, callbackDelegate), callback));
- }
-
- /**
- * Remove a specific application from the holders of a role.
- *
- * @see RoleControllerService#onRemoveRoleHolder(String, String, int, RoleManagerCallback)
- */
- public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
- @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
- mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) ->
- service.onRemoveRoleHolder(roleName, packageName, flags, callbackDelegate),
- callback));
- }
-
- /**
- * Remove all holders of a role.
- *
- * @see RoleControllerService#onClearRoleHolders(String, int, RoleManagerCallback)
- */
- public void onClearRoleHolders(@NonNull String roleName,
- @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
- mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) ->
- service.onClearRoleHolders(roleName, flags, callbackDelegate), callback));
- }
-
- /**
- * Performs granting of default roles and permissions and appops
- *
- * @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback)
- */
- public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) {
- mConnection.enqueueCall(new Connection.Call(IRoleControllerService::onGrantDefaultRoles,
- callback));
- }
-
- /**
- * @see RoleControllerService#onSmsKillSwitchToggled(boolean)
- */
- public void onSmsKillSwitchToggled(boolean smsRestrictionEnabled) {
- mConnection.enqueueCall(new Connection.Call(
- (s, cb) -> s.onSmsKillSwitchToggled(smsRestrictionEnabled),
- new IRoleManagerCallback.Default() {
- @Override
- public void onFailure() {
- Slog.e(LOG_TAG, "Failed onSmsKillSwitchToggled");
- }
- }));
- }
-
- private static final class Connection implements ServiceConnection {
-
- private static final long UNBIND_DELAY_MILLIS = 15 * 1000;
-
- @UserIdInt
- private final int mUserId;
-
- @NonNull
- private final Context mContext;
-
- @NonNull
- private final Handler mHandler = FgThread.getHandler();
-
- private boolean mBound;
-
- @Nullable
- private IRoleControllerService mService;
-
- @NonNull
- private final Queue<Call> mPendingCalls = new ArrayDeque<>();
-
- @NonNull
- private final Runnable mUnbindRunnable = this::unbind;
-
- Connection(@UserIdInt int userId, @NonNull Context context) {
- mUserId = userId;
- mContext = context;
- }
-
- @Override
- @WorkerThread
- public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) {
- mService = IRoleControllerService.Stub.asInterface(service);
- executePendingCalls();
- }
-
- @WorkerThread
- private void executePendingCalls() {
- while (!mPendingCalls.isEmpty()) {
- Call call = mPendingCalls.poll();
- call.execute(mService);
- }
- scheduleUnbind();
- }
-
- @Override
- @WorkerThread
- public void onServiceDisconnected(@NonNull ComponentName name) {
- mService = null;
- }
-
- @Override
- @WorkerThread
- public void onBindingDied(@NonNull ComponentName name) {
- unbind();
- }
-
- public void enqueueCall(@NonNull Call call) {
- if (DEBUG) {
- Slog.i(LOG_TAG, "Enqueue " + call);
- }
- mHandler.executeOrSendMessage(PooledLambda.obtainMessage(Connection::executeCall, this,
- call));
- }
-
- @WorkerThread
- private void executeCall(@NonNull Call call) {
- ensureBound();
- if (mService == null) {
- if (DEBUG) {
- Slog.i(LOG_TAG, "Delaying until service connected: " + call);
- }
- mPendingCalls.offer(call);
- return;
- }
- call.execute(mService);
- scheduleUnbind();
- }
-
- @WorkerThread
- private void ensureBound() {
- mHandler.removeCallbacks(mUnbindRunnable);
- if (!mBound) {
- Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
- intent.setPackage(mContext.getPackageManager()
- .getPermissionControllerPackageName());
- // Use direct handler to ensure onServiceConnected callback happens in the same
- // call frame, as required by onGrantDefaultRoles
- //
- // Note that as a result, onServiceConnected may happen not on main thread!
- mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
- mHandler, UserHandle.of(mUserId));
- }
- }
-
- private void scheduleUnbind() {
- mHandler.removeCallbacks(mUnbindRunnable);
- mHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
- }
-
- @WorkerThread
- private void unbind() {
- if (mBound) {
- mService = null;
- mContext.unbindService(this);
- mBound = false;
- }
- }
-
- public static class Call {
-
- private static final int TIMEOUT_MILLIS = 15 * 1000;
-
- @NonNull
- private final CallExecutor mCallExecutor;
-
- @NonNull
- private final IRoleManagerCallback mCallback;
-
- @NonNull
- private final Handler mHandler = FgThread.getHandler();
-
- @NonNull
- private final Runnable mTimeoutRunnable = this::notifyTimeout;
-
- private boolean mCallbackNotified;
-
- @Nullable
- private final String mDebugName;
-
- private Call(@NonNull CallExecutor callExecutor,
- @NonNull IRoleManagerCallback callback) {
- mCallExecutor = callExecutor;
- mCallback = callback;
- mDebugName = DEBUG
- ? Arrays.stream(Thread.currentThread().getStackTrace())
- .filter(s -> s.getClassName().equals(
- RemoteRoleControllerService.class.getName()))
- .findFirst()
- .get()
- .getMethodName()
- : null;
- }
-
- @WorkerThread
- public void execute(IRoleControllerService service) {
- if (DEBUG) {
- Slog.i(LOG_TAG, "Executing " + this);
- }
- try {
- mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
- mCallExecutor.execute(service, new CallbackDelegate());
- } catch (RemoteException e) {
- Slog.e(LOG_TAG, "Error calling RoleControllerService", e);
- notifyCallback(false);
- }
- }
-
- @WorkerThread
- private void notifyTimeout() {
- Slog.e(LOG_TAG, "Call timed out, calling onFailure()");
- notifyCallback(false);
- }
-
- @WorkerThread
- private void notifyCallback(boolean success) {
- if (DEBUG) {
- Log.i(LOG_TAG, "notifyCallback(" + this
- + ", success = " + success + ")");
- }
- if (mCallbackNotified) {
- return;
- }
- mCallbackNotified = true;
- mHandler.removeCallbacks(mTimeoutRunnable);
- try {
- if (success) {
- mCallback.onSuccess();
- } else {
- mCallback.onFailure();
- }
- } catch (RemoteException e) {
- Slog.e(LOG_TAG, "Error calling " + (success ? "onSuccess()" : "onFailure()")
- + " callback", e);
- }
- }
-
- @Override
- public String toString() {
- return DEBUG ? mDebugName : "Call with callback: " + mCallback;
- }
-
- @FunctionalInterface
- public interface CallExecutor {
-
- @WorkerThread
- void execute(IRoleControllerService service, IRoleManagerCallback callbackDelegate)
- throws RemoteException;
- }
-
- private class CallbackDelegate extends IRoleManagerCallback.Stub {
-
- @Override
- public void onSuccess() throws RemoteException {
- mHandler.sendMessage(PooledLambda.obtainMessage(Call::notifyCallback, Call.this,
- true));
- }
-
- @Override
- public void onFailure() throws RemoteException {
- mHandler.sendMessage(PooledLambda.obtainMessage(Call::notifyCallback, Call.this,
- false));
- }
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index f533ad1..f4e10ed 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -27,7 +27,7 @@
import android.app.AppOpsManager;
import android.app.role.IOnRoleHoldersChangedListener;
import android.app.role.IRoleManager;
-import android.app.role.IRoleManagerCallback;
+import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -97,6 +97,8 @@
private static final String LOG_TAG = RoleManagerService.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
@NonNull
private final UserManagerInternal mUserManagerInternal;
@NonNull
@@ -123,12 +125,11 @@
private final SparseArray<RoleUserState> mUserStates = new SparseArray<>();
/**
- * Maps user id to its controller service.
+ * Maps user id to its controller.
*/
@GuardedBy("mLock")
@NonNull
- private final SparseArray<RemoteRoleControllerService> mControllerServices =
- new SparseArray<>();
+ private final SparseArray<RoleControllerManager> mControllers = new SparseArray<>();
/**
* Maps user id to its list of listeners.
@@ -190,9 +191,9 @@
@Override
public void onReceive(Context context, Intent intent) {
int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1));
- if (RemoteRoleControllerService.DEBUG) {
- Slog.i(LOG_TAG,
- "Packages changed - re-running initial grants for user " + userId);
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Packages changed - re-running initial grants for user "
+ + userId);
}
performInitialGrantsIfNecessary(userId);
}
@@ -243,24 +244,21 @@
// Run grants again
Slog.i(LOG_TAG, "Granting default permissions...");
CompletableFuture<Void> result = new CompletableFuture<>();
- getOrCreateControllerService(userId).onGrantDefaultRoles(
- new IRoleManagerCallback.Stub() {
- @Override
- public void onSuccess() {
+ getOrCreateControllerService(userId).grantDefaultRoles(FgThread.getExecutor(),
+ successful -> {
+ if (successful) {
result.complete(null);
- }
- @Override
- public void onFailure() {
+ } else {
result.completeExceptionally(new RuntimeException());
}
});
try {
- result.get(5, TimeUnit.SECONDS);
+ result.get(30, TimeUnit.SECONDS);
userState.setPackagesHash(packagesHash);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
}
- } else if (RemoteRoleControllerService.DEBUG) {
+ } else if (DEBUG) {
Slog.i(LOG_TAG, "Already ran grants for package state " + packagesHash);
}
}
@@ -326,14 +324,22 @@
}
@NonNull
- private RemoteRoleControllerService getOrCreateControllerService(@UserIdInt int userId) {
+ private RoleControllerManager getOrCreateControllerService(@UserIdInt int userId) {
synchronized (mLock) {
- RemoteRoleControllerService controllerService = mControllerServices.get(userId);
- if (controllerService == null) {
- controllerService = new RemoteRoleControllerService(userId, getContext());
- mControllerServices.put(userId, controllerService);
+ RoleControllerManager controller = mControllers.get(userId);
+ if (controller == null) {
+ Context systemContext = getContext();
+ Context context;
+ try {
+ context = systemContext.createPackageContextAsUser(
+ systemContext.getPackageName(), 0, UserHandle.of(userId));
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ controller = new RoleControllerManager(context, FgThread.getHandler());
+ mControllers.put(userId, controller);
}
- return controllerService;
+ return controller;
}
}
@@ -362,7 +368,7 @@
RoleUserState userState;
synchronized (mLock) {
listeners = mListeners.removeReturnOld(userId);
- mControllerServices.remove(userId);
+ mControllers.remove(userId);
userState = mUserStates.removeReturnOld(userId);
}
if (listeners != null) {
@@ -424,11 +430,12 @@
@Override
public boolean isRoleHeld(@NonNull String roleName, @NonNull String packageName) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
int callingUid = getCallingUid();
mAppOpsManager.checkPackage(callingUid, packageName);
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+
int userId = UserHandle.getUserId(callingUid);
ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
if (roleHolders == null) {
@@ -440,7 +447,6 @@
@NonNull
@Override
public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return Collections.emptyList();
@@ -449,6 +455,8 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"getRoleHoldersAsUser");
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+
ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
if (roleHolders == null) {
return Collections.emptyList();
@@ -459,10 +467,7 @@
@Override
public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
- @NonNull IRoleManagerCallback callback) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ @NonNull RemoteCallback callback) {
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -471,6 +476,10 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"addRoleHolderAsUser");
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, flags,
callback);
}
@@ -478,10 +487,7 @@
@Override
public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
- @NonNull IRoleManagerCallback callback) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ @NonNull RemoteCallback callback) {
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -490,6 +496,10 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"removeRoleHolderAsUser");
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName, flags,
callback);
}
@@ -497,9 +507,7 @@
@Override
public void clearRoleHoldersAsUser(@NonNull String roleName,
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
- @NonNull IRoleManagerCallback callback) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ @NonNull RemoteCallback callback) {
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -508,13 +516,15 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"clearRoleHoldersAsUser");
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+
getOrCreateControllerService(userId).onClearRoleHolders(roleName, flags, callback);
}
@Override
public void addOnRoleHoldersChangedListenerAsUser(
@NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -523,6 +533,8 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
"addOnRoleHoldersChangedListenerAsUser");
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners(
userId);
listeners.register(listener);
@@ -531,7 +543,6 @@
@Override
public void removeOnRoleHoldersChangedListenerAsUser(
@NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
@@ -540,6 +551,8 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
"removeOnRoleHoldersChangedListenerAsUser");
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
if (listener == null) {
return;
@@ -549,11 +562,12 @@
@Override
public void setRoleNamesFromController(@NonNull List<String> roleNames) {
- Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"setRoleNamesFromController");
+ Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
+
int userId = UserHandle.getCallingUserId();
getOrCreateUserState(userId).setRoleNames(roleNames);
}
@@ -561,12 +575,13 @@
@Override
public boolean addRoleHolderFromController(@NonNull String roleName,
@NonNull String packageName) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"addRoleHolderFromController");
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+
int userId = UserHandle.getCallingUserId();
return getOrCreateUserState(userId).addRoleHolder(roleName, packageName);
}
@@ -574,23 +589,25 @@
@Override
public boolean removeRoleHolderFromController(@NonNull String roleName,
@NonNull String packageName) {
- Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"removeRoleHolderFromController");
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+
int userId = UserHandle.getCallingUserId();
return getOrCreateUserState(userId).removeRoleHolder(roleName, packageName);
}
@Override
public List<String> getHeldRolesFromController(@NonNull String packageName) {
- Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"getRolesHeldFromController");
+ Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+
int userId = UserHandle.getCallingUserId();
return getOrCreateUserState(userId).getHeldRoles(packageName);
}
@@ -718,16 +735,14 @@
@Override
public boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) {
CompletableFuture<Void> future = new CompletableFuture<>();
- IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
- @Override
- public void onSuccess() {
+ RemoteCallback callback = new RemoteCallback(result -> {
+ boolean successful = result != null;
+ if (successful) {
future.complete(null);
- }
- @Override
- public void onFailure() {
+ } else {
future.completeExceptionally(new RuntimeException());
}
- };
+ });
if (packageName != null) {
getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
packageName, 0, callback);
@@ -746,14 +761,12 @@
@Override
public void setDefaultBrowserAsync(@Nullable String packageName, @UserIdInt int userId) {
- IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
- @Override
- public void onSuccess() {}
- @Override
- public void onFailure() {
+ RemoteCallback callback = new RemoteCallback(result -> {
+ boolean successful = result != null;
+ if (!successful) {
Slog.e(LOG_TAG, "Failed to set default browser: " + packageName);
}
- };
+ });
if (packageName != null) {
getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
packageName, 0, callback);
@@ -775,14 +788,12 @@
@Override
public void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId) {
- IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
- @Override
- public void onSuccess() {}
- @Override
- public void onFailure() {
+ RemoteCallback callback = new RemoteCallback(result -> {
+ boolean successful = result != null;
+ if (!successful) {
Slog.e(LOG_TAG, "Failed to set default home: " + packageName);
}
- };
+ });
if (packageName != null) {
getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
packageName, 0, callback);
diff --git a/services/core/java/com/android/server/role/RoleManagerShellCommand.java b/services/core/java/com/android/server/role/RoleManagerShellCommand.java
index 00021d7..b26a070 100644
--- a/services/core/java/com/android/server/role/RoleManagerShellCommand.java
+++ b/services/core/java/com/android/server/role/RoleManagerShellCommand.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.role.IRoleManager;
-import android.app.role.IRoleManagerCallback;
+import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
@@ -38,14 +38,23 @@
mRoleManager = roleManager;
}
- private class Callback extends IRoleManagerCallback.Stub {
+ private class CallbackFuture extends CompletableFuture<Void> {
@NonNull
- private final CompletableFuture<Void> mResult = new CompletableFuture<>();
+ public RemoteCallback createCallback() {
+ return new RemoteCallback(result -> {
+ boolean successful = result != null;
+ if (successful) {
+ complete(null);
+ } else {
+ completeExceptionally(new RuntimeException("Failed"));
+ }
+ });
+ }
public int waitForResult() {
try {
- mResult.get(5, TimeUnit.SECONDS);
+ get(5, TimeUnit.SECONDS);
return 0;
} catch (Exception e) {
getErrPrintWriter().println("Error: see logcat for details.\n"
@@ -53,16 +62,6 @@
return -1;
}
}
-
- @Override
- public void onSuccess() {
- mResult.complete(null);
- }
-
- @Override
- public void onFailure() {
- mResult.completeExceptionally(new RuntimeException("Failed"));
- }
}
@Override
@@ -112,9 +111,10 @@
String packageName = getNextArgRequired();
int flags = getFlagsMaybe();
- Callback callback = new Callback();
- mRoleManager.addRoleHolderAsUser(roleName, packageName, flags, userId, callback);
- return callback.waitForResult();
+ CallbackFuture future = new CallbackFuture();
+ mRoleManager.addRoleHolderAsUser(roleName, packageName, flags, userId,
+ future.createCallback());
+ return future.waitForResult();
}
private int runRemoveRoleHolder() throws RemoteException {
@@ -123,9 +123,10 @@
String packageName = getNextArgRequired();
int flags = getFlagsMaybe();
- Callback callback = new Callback();
- mRoleManager.removeRoleHolderAsUser(roleName, packageName, flags, userId, callback);
- return callback.waitForResult();
+ CallbackFuture future = new CallbackFuture();
+ mRoleManager.removeRoleHolderAsUser(roleName, packageName, flags, userId,
+ future.createCallback());
+ return future.waitForResult();
}
private int runClearRoleHolders() throws RemoteException {
@@ -133,9 +134,9 @@
String roleName = getNextArgRequired();
int flags = getFlagsMaybe();
- Callback callback = new Callback();
- mRoleManager.clearRoleHoldersAsUser(roleName, flags, userId, callback);
- return callback.waitForResult();
+ CallbackFuture future = new CallbackFuture();
+ mRoleManager.clearRoleHoldersAsUser(roleName, flags, userId, future.createCallback());
+ return future.waitForResult();
}
@Override
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index d3e1a05..871f9f8 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -356,7 +356,7 @@
PackageInstaller packageInstaller = pm.getPackageInstaller();
PackageInstaller.SessionParams parentParams = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
- parentParams.setAllowDowngrade(true);
+ parentParams.setRequestDowngrade(true);
parentParams.setMultiPackage();
if (data.isStaged()) {
parentParams.setStaged();
@@ -377,7 +377,7 @@
params.setInstallerPackageName(installerPackageName);
}
}
- params.setAllowDowngrade(true);
+ params.setRequestDowngrade(true);
if (data.isStaged()) {
params.setStaged();
}
@@ -535,6 +535,9 @@
DeviceConfig.Rollback.BOOT_NAMESPACE,
DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS,
DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS);
+ if (mRollbackLifetimeDurationInMillis < 0) {
+ mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS;
+ }
}
void onBootCompleted() {
diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING
index 6be93a0..921b754 100644
--- a/services/core/java/com/android/server/rollback/TEST_MAPPING
+++ b/services/core/java/com/android/server/rollback/TEST_MAPPING
@@ -5,6 +5,14 @@
},
{
"name": "StagedRollbackTest"
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.rollback"
+ }
+ ]
}
]
}
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 28fee4e..4614355 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -43,8 +43,6 @@
import android.util.Log;
import android.util.Slog;
-import com.android.internal.policy.IKeyguardDismissCallback;
-
import java.util.Collections;
import java.util.List;
@@ -495,6 +493,21 @@
}
}
+ /**
+ * @see android.service.trust.TrustAgentService#onTokenStateReceived()
+ *
+ */
+ public void onEscrowTokenActivated(long handle, int userId) {
+ if (DEBUG) Slog.d(TAG, "onEscrowTokenActivated: " + handle + " user: " + userId);
+ if (mTrustAgentService != null) {
+ try {
+ mTrustAgentService.onTokenStateReceived(handle,
+ TrustAgentService.TOKEN_STATE_ACTIVE);
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+ }
private void setCallback(ITrustAgentServiceCallback callback) {
try {
if (mTrustAgentService != null) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index c7044a1..3a39053 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -409,7 +409,10 @@
}
public long addEscrowToken(byte[] token, int userId) {
- return mLockPatternUtils.addEscrowToken(token, userId);
+ return mLockPatternUtils.addEscrowToken(token, userId,
+ (long handle, int userid) -> {
+ dispatchEscrowTokenActivatedLocked(handle, userid);
+ });
}
public boolean removeEscrowToken(long handle, int userId) {
@@ -662,6 +665,15 @@
}
}
+ private void dispatchEscrowTokenActivatedLocked(long handle, int userId) {
+ for (int i = 0; i < mActiveAgents.size(); i++) {
+ AgentInfo agent = mActiveAgents.valueAt(i);
+ if (agent.userId == userId) {
+ agent.agent.onEscrowTokenActivated(handle, userId);
+ }
+ }
+ }
+
void updateDevicePolicyFeatures() {
boolean changed = false;
for (int i = 0; i < mActiveAgents.size(); i++) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 1ae85b8..9a5ec2a 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -450,10 +450,17 @@
}
void onSystemReady() {
- mPersisterQueue.startPersisting();
mLaunchParamsPersister.onSystemReady();
}
+ void onUserUnlocked(int userId) {
+ // Only start persisting when the first user is unlocked. The method call is
+ // idempotent so there is no side effect to call it again when the second user is
+ // unlocked.
+ mPersisterQueue.startPersisting();
+ mLaunchParamsPersister.onUnlockUser(userId);
+ }
+
public ActivityMetricsLogger getActivityMetricsLogger() {
return mActivityMetricsLogger;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 5a746eb..2b23ff0 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1809,7 +1809,7 @@
}
}
- mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
+ mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? sourceRecord : null;
mInTask = inTask;
// In some flows in to this function, we retrieve the task record and hold on to it
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index f100efc..794a4b8 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -954,7 +954,7 @@
@Override
public void onUnlockUser(int userId) {
synchronized (mService.getGlobalLock()) {
- mService.mStackSupervisor.mLaunchParamsPersister.onUnlockUser(userId);
+ mService.mStackSupervisor.onUserUnlocked(userId);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 515ac52..db59030 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -392,7 +392,8 @@
final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
/** Detect user tapping outside of current focused task bounds .*/
- TaskTapPointerEventListener mTapDetector;
+ @VisibleForTesting
+ final TaskTapPointerEventListener mTapDetector;
/** Detect user tapping outside of current focused stack bounds .*/
private Region mTouchExcludeRegion = new Region();
@@ -876,14 +877,17 @@
mBoundsAnimationController = new BoundsAnimationController(service.mContext,
mAppTransition, AnimationThread.getHandler(), animationHandler);
- if (mWmService.mInputManager != null) {
- final InputChannel inputChannel = mWmService.mInputManager.monitorInput("Display "
- + mDisplayId, mDisplayId);
- mPointerEventDispatcher = inputChannel != null
- ? new PointerEventDispatcher(inputChannel) : null;
- } else {
- mPointerEventDispatcher = null;
- }
+ final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
+ "PointerEventDispatcher" + mDisplayId, mDisplayId);
+ mPointerEventDispatcher = new PointerEventDispatcher(inputChannel);
+
+ // Tap Listeners are supported for:
+ // 1. All physical displays (multi-display).
+ // 2. VirtualDisplays on VR, AA (and everything else).
+ mTapDetector = new TaskTapPointerEventListener(mWmService, this);
+ registerPointerEventListener(mTapDetector);
+ registerPointerEventListener(mWmService.mMousePositionTracker);
+
mDisplayPolicy = new DisplayPolicy(service, this);
mDisplayRotation = new DisplayRotation(service, this);
if (isDefaultDisplay) {
@@ -1511,19 +1515,6 @@
mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
-
- // Tap Listeners are supported for:
- // 1. All physical displays (multi-display).
- // 2. VirtualDisplays on VR, AA (and everything else).
- if (mPointerEventDispatcher != null && mTapDetector == null) {
- if (DEBUG_DISPLAY) {
- Slog.d(TAG,
- "Registering PointerEventListener for DisplayId: " + mDisplayId);
- }
- mTapDetector = new TaskTapPointerEventListener(mWmService, this);
- registerPointerEventListener(mTapDetector);
- registerPointerEventListener(mWmService.mMousePositionTracker);
- }
}
/**
@@ -2450,9 +2441,7 @@
mTmpRegion.set(mTmpRect);
mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
}
- if (mTapDetector != null) {
- mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
- }
+ mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
}
/**
@@ -2502,11 +2491,7 @@
mWmService.stopFreezingDisplayLocked();
super.removeImmediately();
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
- if (mPointerEventDispatcher != null && mTapDetector != null) {
- unregisterPointerEventListener(mTapDetector);
- unregisterPointerEventListener(mWmService.mMousePositionTracker);
- mTapDetector = null;
- }
+ mPointerEventDispatcher.dispose();
mWmService.mAnimator.removeDisplayLocked(mDisplayId);
mWindowingLayer.release();
mOverlayLayer.release();
@@ -2516,7 +2501,6 @@
mRemovingDisplay = false;
}
- mDisplayPolicy.onDisplayRemoved();
mWmService.mWindowPlacerLocked.requestTraversal();
}
@@ -4825,15 +4809,11 @@
}
void registerPointerEventListener(@NonNull PointerEventListener listener) {
- if (mPointerEventDispatcher != null) {
- mPointerEventDispatcher.registerInputEventListener(listener);
- }
+ mPointerEventDispatcher.registerInputEventListener(listener);
}
void unregisterPointerEventListener(@NonNull PointerEventListener listener) {
- if (mPointerEventDispatcher != null) {
- mPointerEventDispatcher.unregisterInputEventListener(listener);
- }
+ mPointerEventDispatcher.unregisterInputEventListener(listener);
}
void prepareAppTransition(@WindowManager.TransitionType int transit,
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 5862d43..e48361f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -221,7 +221,6 @@
}
}
- @VisibleForTesting
private final SystemGesturesPointerEventListener mSystemGestures;
private volatile int mLidState = LID_ABSENT;
@@ -548,10 +547,6 @@
return mDisplayContent.getDisplayId();
}
- void onDisplayRemoved() {
- mDisplayContent.unregisterPointerEventListener(mSystemGestures);
- }
-
void configure(int width, int height, int shortSizeDp) {
// Allow the navigation bar to move on non-square small devices (phones).
mNavigationBarCanMove = width != height && shortSizeDp < 600;
diff --git a/services/core/java/com/android/server/wm/PersisterQueue.java b/services/core/java/com/android/server/wm/PersisterQueue.java
index a17ee65..9dc3d6a 100644
--- a/services/core/java/com/android/server/wm/PersisterQueue.java
+++ b/services/core/java/com/android/server/wm/PersisterQueue.java
@@ -131,10 +131,8 @@
}
/**
- *
- * @param item
- * @param flush
- * @param <T>
+ * Updates the last item found in the queue that matches the given item, or adds it to the end
+ * of the queue if no such item is found.
*/
synchronized <T extends WriteQueueItem> void updateLastOrAddItem(T item, boolean flush) {
final T itemToUpdate = findLastItem(item::matches, (Class<T>) item.getClass());
@@ -149,10 +147,6 @@
/**
* Removes all items with which given predicate returns {@code true}.
- *
- * @param predicate the predicate
- * @param clazz
- * @param <T>
*/
synchronized <T extends WriteQueueItem> void removeItems(Predicate<T> predicate,
Class<T> clazz) {
diff --git a/services/core/java/com/android/server/wm/PointerEventDispatcher.java b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
index f815fa0..8d08aa3 100644
--- a/services/core/java/com/android/server/wm/PointerEventDispatcher.java
+++ b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
@@ -28,11 +28,13 @@
import java.util.ArrayList;
public class PointerEventDispatcher extends InputEventReceiver {
- ArrayList<PointerEventListener> mListeners = new ArrayList<PointerEventListener>();
- PointerEventListener[] mListenersArray = new PointerEventListener[0];
+ private final InputChannel mInputChannel;
+ private final ArrayList<PointerEventListener> mListeners = new ArrayList<>();
+ private PointerEventListener[] mListenersArray = new PointerEventListener[0];
public PointerEventDispatcher(InputChannel inputChannel) {
super(inputChannel, UiThread.getHandler().getLooper());
+ mInputChannel = inputChannel;
}
@Override
@@ -87,4 +89,15 @@
mListenersArray = null;
}
}
+
+ /** Dispose the associated input channel and clean up the listeners. */
+ @Override
+ public void dispose() {
+ super.dispose();
+ mInputChannel.dispose();
+ synchronized (mListeners) {
+ mListeners.clear();
+ mListenersArray = null;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java
index d50af38..06bdcc0 100644
--- a/services/core/java/com/android/server/wm/TaskPersister.java
+++ b/services/core/java/com/android/server/wm/TaskPersister.java
@@ -492,16 +492,8 @@
return new File(userTaskIdsDir, PERSISTED_TASK_IDS_FILENAME);
}
- static File getUserTasksDir(int userId) {
- File userTasksDir = new File(Environment.getDataSystemCeDirectory(userId), TASKS_DIRNAME);
-
- if (!userTasksDir.exists()) {
- if (!userTasksDir.mkdir()) {
- Slog.e(TAG, "Failure creating tasks directory for user " + userId + ": "
- + userTasksDir);
- }
- }
- return userTasksDir;
+ private static File getUserTasksDir(int userId) {
+ return new File(Environment.getDataSystemCeDirectory(userId), TASKS_DIRNAME);
}
static File getUserImagesDir(int userId) {
@@ -568,8 +560,13 @@
FileOutputStream file = null;
AtomicFile atomicFile = null;
try {
- atomicFile = new AtomicFile(new File(
- getUserTasksDir(task.userId),
+ File userTasksDir = getUserTasksDir(task.userId);
+ if (!userTasksDir.isDirectory() && !userTasksDir.mkdirs()) {
+ Slog.e(TAG, "Failure creating tasks directory for user " + task.userId
+ + ": " + userTasksDir + " Dropping persistence for task " + task);
+ return;
+ }
+ atomicFile = new AtomicFile(new File(userTasksDir,
String.valueOf(task.taskId) + TASK_FILENAME_SUFFIX));
file = atomicFile.startWrite();
file.write(stringWriter.toString().getBytes());
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 5c7b287..050a079 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -38,6 +38,7 @@
"com_android_server_SerialService.cpp",
"com_android_server_storage_AppFuseBridge.cpp",
"com_android_server_SystemServer.cpp",
+ "com_android_server_TestNetworkService.cpp",
"com_android_server_tv_TvUinputBridge.cpp",
"com_android_server_tv_TvInputHal.cpp",
"com_android_server_vr_VrManagerService.cpp",
diff --git a/services/core/jni/com_android_server_TestNetworkService.cpp b/services/core/jni/com_android_server_TestNetworkService.cpp
new file mode 100644
index 0000000..b90ff23
--- /dev/null
+++ b/services/core/jni/com_android_server_TestNetworkService.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+
+#define LOG_TAG "TestNetworkServiceJni"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/ipv6_route.h>
+#include <linux/route.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+
+#include "netutils/ifc.h"
+
+#include "jni.h"
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+namespace android {
+
+//------------------------------------------------------------------------------
+
+static void throwException(JNIEnv* env, int error, const char* action, const char* iface) {
+ const std::string& msg =
+ android::base::StringPrintf("Error %s %s: %s", action, iface, strerror(error));
+
+ jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
+}
+
+static int createTunInterface(JNIEnv* env, const char* iface) {
+ base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
+ ifreq ifr{};
+
+ // Allocate interface.
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+ strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
+ if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
+ throwException(env, errno, "allocating", ifr.ifr_name);
+ return -1;
+ }
+
+ // Activate interface using an unconnected datagram socket.
+ base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
+ ifr.ifr_flags = IFF_UP;
+
+ if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
+ throwException(env, errno, "activating", ifr.ifr_name);
+ return -1;
+ }
+
+ return tun.release();
+}
+
+//------------------------------------------------------------------------------
+
+static jint create(JNIEnv* env, jobject /* thiz */, jstring jIface) {
+ ScopedUtfChars iface(env, jIface);
+ if (!iface.c_str()) {
+ jniThrowNullPointerException(env, "iface");
+ return -1;
+ }
+
+ int tun = createTunInterface(env, iface.c_str());
+
+ // Any exceptions will be thrown from the createTunInterface call
+ return tun;
+}
+
+//------------------------------------------------------------------------------
+
+static const JNINativeMethod gMethods[] = {
+ {"jniCreateTun", "(Ljava/lang/String;)I", (void*)create},
+};
+
+int register_android_server_TestNetworkService(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/server/TestNetworkService", gMethods,
+ NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 6e31aed..5ffed03 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -41,6 +41,7 @@
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv*);
+int register_android_server_TestNetworkService(JNIEnv* env);
int register_android_server_devicepolicy_CryptoTestHelper(JNIEnv*);
int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
int register_android_server_tv_TvUinputBridge(JNIEnv* env);
@@ -85,6 +86,7 @@
register_android_server_location_GnssLocationProvider(env);
register_android_server_connectivity_Vpn(env);
register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
+ register_android_server_TestNetworkService(env);
register_android_server_devicepolicy_CryptoTestHelper(env);
register_android_server_ConsumerIrService(env);
register_android_server_BatteryStatsService(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 36251f5..d7922b15 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -13352,8 +13352,8 @@
if (policy.mPasswordTokenHandle != 0) {
mLockPatternUtils.removeEscrowToken(policy.mPasswordTokenHandle, userHandle);
}
-
- policy.mPasswordTokenHandle = mLockPatternUtils.addEscrowToken(token, userHandle);
+ policy.mPasswordTokenHandle = mLockPatternUtils.addEscrowToken(token,
+ userHandle, /*EscrowTokenStateChangeCallback*/ null);
saveSettingsLocked(userHandle);
return policy.mPasswordTokenHandle != 0;
} finally {
diff --git a/services/net/OWNERS b/services/net/OWNERS
index 7311eee..d3836d4 100644
--- a/services/net/OWNERS
+++ b/services/net/OWNERS
@@ -1,8 +1,8 @@
set noparent
codewiz@google.com
-ek@google.com
jchalard@google.com
+junyulai@google.com
lorenzo@google.com
reminv@google.com
satk@google.com
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 830dbbe..a8f4a77 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -42,7 +42,6 @@
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
/**
@@ -53,6 +52,7 @@
private static final String TAG = NetworkStackClient.class.getSimpleName();
private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
+ private static final String IN_PROCESS_SUFFIX = ".InProcess";
private static NetworkStackClient sInstance;
@@ -175,42 +175,50 @@
public void start(Context context) {
log("Starting network stack");
mNetworkStackStartRequested = true;
- // Try to bind in-process if the library is available
- IBinder connector = null;
- try {
- final Class service = Class.forName(
- "com.android.server.NetworkStackService",
- true /* initialize */,
- context.getClassLoader());
- connector = (IBinder) service.getMethod("makeConnector", Context.class)
- .invoke(null, context);
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- logWtf("Could not create network stack connector from NetworkStackService", e);
- // TODO: crash/reboot system here ?
- return;
- } catch (ClassNotFoundException e) {
- // Normal behavior if stack is provided by the app: fall through
+
+ final PackageManager pm = context.getPackageManager();
+
+ // Try to bind in-process if the device was shipped with an in-process version
+ Intent intent = getNetworkStackIntent(pm, true /* inSystemProcess */);
+
+ // Otherwise use the updatable module version
+ if (intent == null) {
+ intent = getNetworkStackIntent(pm, false /* inSystemProcess */);
+ log("Starting network stack process");
+ } else {
+ log("Starting network stack in-process");
}
- // In-process network stack. Add the service to the service manager here.
- if (connector != null) {
- log("Registering in-process network stack connector");
- registerNetworkStackService(connector);
- return;
- }
- // Start the network stack process. The service will be added to the service manager in
- // NetworkStackConnection.onServiceConnected().
- log("Starting network stack process");
- final Intent intent = new Intent(INetworkStackConnector.class.getName());
- final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
- intent.setComponent(comp);
-
- if (comp == null) {
- logWtf("Could not resolve the network stack with " + intent, null);
+ if (intent == null) {
+ logWtf("Could not resolve the network stack", null);
// TODO: crash/reboot system server ?
return;
}
- final PackageManager pm = context.getPackageManager();
+
+ // Start the network stack. The service will be added to the service manager in
+ // NetworkStackConnection.onServiceConnected().
+ if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
+ logWtf("Could not bind to network stack with " + intent, null);
+ return;
+ // TODO: crash/reboot system server if no network stack after a timeout ?
+ }
+
+ log("Network stack service start requested");
+ }
+
+ @Nullable
+ private Intent getNetworkStackIntent(@NonNull PackageManager pm, boolean inSystemProcess) {
+ final String baseAction = INetworkStackConnector.class.getName();
+ final Intent intent =
+ new Intent(inSystemProcess ? baseAction + IN_PROCESS_SUFFIX : baseAction);
+ final ComponentName comp = intent.resolveSystemService(pm, 0);
+
+ if (comp == null) {
+ return null;
+ }
+ intent.setComponent(comp);
+
int uid = -1;
try {
uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
@@ -218,25 +226,27 @@
logWtf("Network stack package not found", e);
// Fall through
}
- if (uid != Process.NETWORK_STACK_UID) {
+
+ final int expectedUid = inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
+ if (uid != expectedUid) {
throw new SecurityException("Invalid network stack UID: " + uid);
}
+ if (!inSystemProcess) {
+ checkNetworkStackPermission(pm, comp);
+ }
+
+ return intent;
+ }
+
+ private void checkNetworkStackPermission(
+ @NonNull PackageManager pm, @NonNull ComponentName comp) {
final int hasPermission =
pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
if (hasPermission != PERMISSION_GRANTED) {
throw new SecurityException(
"Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
}
-
- if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
- logWtf("Could not bind to network stack in-process, or in app with " + intent, null);
- return;
- // TODO: crash/reboot system server if no network stack after a timeout ?
- }
-
- log("Network stack service start requested");
}
private void log(@NonNull String message) {
@@ -289,7 +299,8 @@
private void requestConnector(@NonNull NetworkStackCallback request) {
// TODO: PID check.
final int caller = Binder.getCallingUid();
- if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
+ if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)
+ && !UserHandle.isSameApp(caller, Process.PHONE_UID)) {
// Don't even attempt to obtain the connector and give a nice error message
throw new SecurityException(
"Only the system server should try to bind to the network stack.");
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index 34fc735..0e44f88 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -87,7 +87,6 @@
return "UNKNOWN: " + state;
}
- private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
private static final byte DOUG_ADAMS = (byte) 42;
private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
@@ -557,16 +556,6 @@
addedPrefixes.removeAll(mLastRaParams.prefixes);
}
- if (mLastRaParams == null || mLastRaParams.prefixes.isEmpty()) {
- // We need to be able to send unicast RAs, and clients might
- // like to ping the default router's link-local address. Note
- // that we never remove the link-local route from the network
- // until Tethering disables tethering on the interface. We
- // only need to add the link-local prefix once, but in the
- // event we add it more than once netd silently ignores EEXIST.
- addedPrefixes.add(LINK_LOCAL_PREFIX);
- }
-
if (!addedPrefixes.isEmpty()) {
final ArrayList<RouteInfo> toBeAdded =
getLocalRoutesFor(mIfaceName, addedPrefixes);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 4293247..039a4b7 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -29,6 +29,7 @@
import static android.os.UserManagerInternal.CAMERA_DISABLED_LOCALLY;
import static android.os.UserManagerInternal.CAMERA_NOT_DISABLED;
+import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
import static com.android.server.testutils.TestUtils.assertExpectException;
import static org.mockito.Matchers.any;
@@ -4157,8 +4158,9 @@
final byte[] token = new byte[32];
final long handle = 123456;
final String password = "password";
- when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM)))
- .thenReturn(handle);
+ when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
+ nullable(EscrowTokenStateChangeCallback.class)))
+ .thenReturn(handle);
assertTrue(dpm.setResetPasswordToken(admin1, token));
// test password activation
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index d343ac1..77515258 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -338,7 +338,7 @@
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
+ long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
@@ -367,7 +367,7 @@
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
+ long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
@@ -393,7 +393,7 @@
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
+ long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
@@ -417,7 +417,7 @@
throws RemoteException {
final String token = "some-high-entropy-secure-token";
enableSyntheticPassword();
- long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID);
+ long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID, null);
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
@@ -427,7 +427,7 @@
throws RemoteException {
final String token = "some-high-entropy-secure-token";
initializeCredentialUnderSP(null, PRIMARY_USER_ID);
- long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID);
+ long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID, null);
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
@@ -443,7 +443,7 @@
PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
enableSyntheticPassword();
- long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
+ long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
// Token not activated immediately since user password exists
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
// Activate token (password gets migrated to SP at the same time)
@@ -461,7 +461,7 @@
mHasSecureLockScreen = false;
enableSyntheticPassword();
- long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID);
+ long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
try {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 3ebc6ad..e9edba5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -185,6 +185,18 @@
}
@MediumTest
+ public void testRemoveUserByHandle_ThrowsException() {
+ synchronized (mUserRemoveLock) {
+ try {
+ mUserManager.removeUser(null);
+ fail("Expected IllegalArgumentException on passing in a null UserHandle.");
+ } catch (IllegalArgumentException expected) {
+ // Do nothing - exception is expected.
+ }
+ }
+ }
+
+ @MediumTest
public void testAddGuest() throws Exception {
UserInfo userInfo1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
UserInfo userInfo2 = createUser("Guest 2", UserInfo.FLAG_GUEST);
@@ -520,6 +532,12 @@
}
}
+ public void testGetUserSwitchability() {
+ int userSwitchable = mUserManager.getUserSwitchability();
+ assertEquals("Expected users to be switchable", UserManager.SWITCHABILITY_STATUS_OK,
+ userSwitchable);
+ }
+
@LargeTest
public void testSwitchUser() {
ActivityManager am = getContext().getSystemService(ActivityManager.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index d202e16..032eba1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -270,7 +270,7 @@
WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
windowingMode, int activityType) {
return createTestAppWindowToken(dc, windowingMode, activityType,
- true /*skipOnParentChanged */);
+ false /*skipOnParentChanged */);
}
WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 2907021..2fc6efa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -74,7 +74,7 @@
public SurfaceControl.Transaction setLayer(SurfaceControl sc, int layer) {
mRelativeLayersForControl.remove(sc);
mLayersForControl.put(sc, layer);
- return super.setLayer(sc, layer);
+ return this;
}
@Override
@@ -83,7 +83,7 @@
int layer) {
mRelativeLayersForControl.put(sc, relativeTo);
mLayersForControl.put(sc, layer);
- return super.setRelativeLayer(sc, relativeTo, layer);
+ return this;
}
private int getLayer(SurfaceControl sc) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index b9a5676..9498e16 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -17,6 +17,7 @@
package com.android.server.usage;
import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
+import static android.app.usage.UsageEvents.Event.DEVICE_STARTUP;
import static android.app.usage.UsageStatsManager.INTERVAL_BEST;
import static android.app.usage.UsageStatsManager.INTERVAL_COUNT;
import static android.app.usage.UsageStatsManager.INTERVAL_DAILY;
@@ -137,15 +138,18 @@
// During system reboot, add a DEVICE_SHUTDOWN event to the end of event list, the timestamp
// is last time UsageStatsDatabase is persisted to disk.
+ // Also add a DEVICE_STARTUP event with current system timestamp.
final IntervalStats currentDailyStats = mCurrentStats[INTERVAL_DAILY];
if (currentDailyStats != null) {
- final int size = currentDailyStats.events.size();
- if (size == 0 || currentDailyStats.events.get(size - 1).mEventType != DEVICE_SHUTDOWN) {
- // The last event in event list is not DEVICE_SHUTDOWN, then we insert one.
- final Event event = new Event(DEVICE_SHUTDOWN, currentDailyStats.lastTimeSaved);
- event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
- currentDailyStats.addEvent(event);
- }
+ // File system timestamp only has precision of 1 second, add 1000ms to make up
+ // for the loss of round up.
+ final Event shutdownEvent =
+ new Event(DEVICE_SHUTDOWN, currentDailyStats.lastTimeSaved + 1000);
+ shutdownEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
+ currentDailyStats.addEvent(shutdownEvent);
+ final Event startupEvent = new Event(DEVICE_STARTUP, currentTimeMillis);
+ startupEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
+ currentDailyStats.addEvent(startupEvent);
}
if (mDatabase.isNewUpdate()) {
@@ -956,6 +960,8 @@
return "KEYGUARD_HIDDEN";
case Event.DEVICE_SHUTDOWN:
return "DEVICE_SHUTDOWN";
+ case Event.DEVICE_STARTUP:
+ return "DEVICE_STARTUP";
default:
return "UNKNOWN_TYPE_" + eventType;
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index b9440eb..ad1e3ef 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1389,6 +1389,16 @@
resetCurAssistant(userHandle);
initForUser(userHandle);
switchImplementationIfNeededLocked(true);
+
+ Context context = getContext();
+ context.getSystemService(RoleManager.class).clearRoleHoldersAsUser(
+ RoleManager.ROLE_ASSISTANT, 0, UserHandle.of(userHandle),
+ context.getMainExecutor(), successful -> {
+ if (!successful) {
+ Slog.e(TAG,
+ "Failed to clear default assistant for force stop");
+ }
+ });
}
} else if (hitRec && doit) {
// We are just force-stopping the current recognizer, which is not
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index e43b2b7..5b806a6 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -16,7 +16,6 @@
import android.app.ActivityManager;
import android.app.role.RoleManager;
-import android.app.role.RoleManagerCallback;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -34,9 +33,11 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
/**
* Class for managing the default dialer application that will receive incoming calls, and be
@@ -75,11 +76,18 @@
int user) {
long identity = Binder.clearCallingIdentity();
try {
- RoleManagerCallback.Future cb = new RoleManagerCallback.Future();
+ CompletableFuture<Void> future = new CompletableFuture<>();
+ Consumer<Boolean> callback = successful -> {
+ if (successful) {
+ future.complete(null);
+ } else {
+ future.completeExceptionally(new RuntimeException());
+ }
+ };
context.getSystemService(RoleManager.class).addRoleHolderAsUser(
RoleManager.ROLE_DIALER, packageName, 0, UserHandle.of(user),
- AsyncTask.THREAD_POOL_EXECUTOR, cb);
- cb.get(5, TimeUnit.SECONDS);
+ AsyncTask.THREAD_POOL_EXECUTOR, callback);
+ future.get(5, TimeUnit.SECONDS);
return true;
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Slog.e(TAG, "Failed to set default dialer to " + packageName + " for user " + user, e);
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 7688ac6..52c5425 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -25,7 +25,6 @@
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
-import android.app.role.RoleManagerCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -478,12 +477,6 @@
"android.telecom.extra.START_CALL_WITH_RTT";
/**
- * A boolean extra set to indicate whether an app is eligible to be bound to when there are
- * ongoing calls on the device.
- */
- public static final String EXTRA_IS_ENABLED = "android.telecom.extra.IS_ENABLED";
-
- /**
* A boolean meta-data value indicating whether an {@link InCallService} implements an
* in-call user interface. Dialer implementations (see {@link #getDefaultDialerPackage()}) which
* would also like to replace the in-call interface should set this meta-data to {@code true} in
@@ -1221,8 +1214,8 @@
*
* @hide
* @deprecated Use
- * {@link android.app.role.RoleManager#addRoleHolderAsUser(String, String, UserHandle, Executor,
- * RoleManagerCallback)} instead.
+ * {@link android.app.role.RoleManager#addRoleHolderAsUser(String, String, int, UserHandle,
+ * Executor, java.util.function.Consumer)} instead.
*/
@SystemApi
@Deprecated
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 67477cf..3106e40 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -4372,24 +4372,24 @@
}
/**
- * Generates a content {@link Uri} used to receive updates on precise carrier identity
+ * Generates a content {@link Uri} used to receive updates on specific carrier identity
* change on the given subscriptionId returned by
- * {@link TelephonyManager#getSimPreciseCarrierId()}.
- * @see TelephonyManager#ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED
+ * {@link TelephonyManager#getSimSpecificCarrierId()}.
+ * @see TelephonyManager#ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
- * precise carrier identity {@link TelephonyManager#getSimPreciseCarrierId()}
+ * specific carrier identity {@link TelephonyManager#getSimSpecificCarrierId()}
* while your app is running. You can also use a {@link JobService} to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
* Note, however, that using a {@link JobService} does not guarantee timely delivery of
* updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
- * @return the Uri used to observe precise carrier identity changes
+ * @return the Uri used to observe specific carrier identity changes
*/
@NonNull
- public static Uri getPreciseCarrierIdUriForSubscriptionId(int subscriptionId) {
- return Uri.withAppendedPath(Uri.withAppendedPath(CONTENT_URI, "precise"),
+ public static Uri getSpecificCarrierIdUriForSubscriptionId(int subscriptionId) {
+ return Uri.withAppendedPath(Uri.withAppendedPath(CONTENT_URI, "specific"),
String.valueOf(subscriptionId));
}
@@ -4409,26 +4409,30 @@
/**
* A fine-grained carrier id.
- * @see TelephonyManager#getSimPreciseCarrierId()
+ * The specific carrier ID would be used for configuration purposes, but apps wishing to
+ * know about the carrier itself should use the regular carrier ID returned by
+ * {@link TelephonyManager#getSimCarrierId()}.
+ *
+ * @see TelephonyManager#getSimSpecificCarrierId()
* This is not a database column, only used to notify content observers for
- * {@link #getPreciseCarrierIdUriForSubscriptionId(int)}
+ * {@link #getSpecificCarrierIdUriForSubscriptionId(int)}
*/
- public static final String PRECISE_CARRIER_ID = "precise_carrier_id";
+ public static final String SPECIFIC_CARRIER_ID = "specific_carrier_id";
/**
- * A user facing carrier name for precise carrier id {@link #PRECISE_CARRIER_ID}.
- * @see TelephonyManager#getSimPreciseCarrierIdName()
+ * A user facing carrier name for specific carrier id {@link #SPECIFIC_CARRIER_ID}.
+ * @see TelephonyManager#getSimSpecificCarrierIdName()
* This is not a database column, only used to notify content observers for
- * {@link #getPreciseCarrierIdUriForSubscriptionId(int)}
+ * {@link #getSpecificCarrierIdUriForSubscriptionId(int)}
*/
- public static final String PRECISE_CARRIER_ID_NAME = "precise_carrier_id_name";
+ public static final String SPECIFIC_CARRIER_ID_NAME = "specific_carrier_id_name";
/**
* A unique parent carrier id. The parent-child
* relationship can be used to further differentiate a single carrier by different networks,
- * by prepaid v.s. postpaid or even by 4G v.s. 3G plan. It's an optional field.
- * A carrier id with a valid parent_carrier_id is considered fine-grained carrier id, will
- * not be returned as {@link #CARRIER_ID} but {@link #PRECISE_CARRIER_ID}.
+ * by prepaid v.s. postpaid. It's an optional field.
+ * A carrier id with a valid parent_carrier_id is considered fine-grained specific carrier
+ * ID, will not be returned as {@link #CARRIER_ID} but {@link #SPECIFIC_CARRIER_ID}.
* <P>Type: INTEGER </P>
* @hide
*/
diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java
index 8a7153e..a15f959 100644
--- a/telephony/java/android/telephony/AvailableNetworkInfo.java
+++ b/telephony/java/android/telephony/AvailableNetworkInfo.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -62,11 +63,22 @@
/**
* Describes the List of PLMN ids (MCC-MNC) associated with mSubId.
* If this entry is left empty, then the platform software will not scan the network
- * to revalidate the input.
+ * to revalidate the input else platform will scan and verify specified PLMNs are available.
*/
private ArrayList<String> mMccMncs;
/**
+ * Returns the frequency bands associated with the {@link #getMccMncs() MCC/MNCs}.
+ * Opportunistic network service will use these bands to scan.
+ *
+ * When no specific bands are specified (empty array or null) CBRS band (B48) will be
+ * used for network scan.
+ *
+ * See {@link AccessNetworkConstants} for details.
+ */
+ private ArrayList<Integer> mBands;
+
+ /**
* Return subscription Id of the available network.
* This value must be one of the entry retrieved from
* {@link SubscriptionManager#getOpportunisticSubscriptions}
@@ -91,10 +103,20 @@
* to revalidate the input.
* @return list of PLMN ids
*/
- public List<String> getMccMncs() {
+ public @NonNull List<String> getMccMncs() {
return (List<String>) mMccMncs.clone();
}
+ /**
+ * Returns the frequency bands that need to be scanned by opportunistic network service
+ *
+ * The returned value is defined in either of {@link AccessNetworkConstants.GeranBand},
+ * {@link AccessNetworkConstants.UtranBand} and {@link AccessNetworkConstants.EutranBand}
+ */
+ public @NonNull List<Integer> getBands() {
+ return (List<Integer>) mBands.clone();
+ }
+
@Override
public int describeContents() {
return 0;
@@ -105,6 +127,7 @@
dest.writeInt(mSubId);
dest.writeInt(mPriority);
dest.writeStringList(mMccMncs);
+ dest.writeList(mBands);
}
private AvailableNetworkInfo(Parcel in) {
@@ -112,12 +135,16 @@
mPriority = in.readInt();
mMccMncs = new ArrayList<>();
in.readStringList(mMccMncs);
+ mBands = new ArrayList<>();
+ in.readList(mBands, Integer.class.getClassLoader());
}
- public AvailableNetworkInfo(int subId, int priority, List<String> mccMncs) {
+ public AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs,
+ @NonNull List<Integer> bands) {
mSubId = subId;
mPriority = priority;
mMccMncs = new ArrayList<String>(mccMncs);
+ mBands = new ArrayList<Integer>(bands);
}
@Override
@@ -135,14 +162,15 @@
}
return (mSubId == ani.mSubId
- && mPriority == ani.mPriority
- && (((mMccMncs != null)
- && mMccMncs.equals(ani.mMccMncs))));
+ && mPriority == ani.mPriority
+ && (((mMccMncs != null)
+ && mMccMncs.equals(ani.mMccMncs)))
+ && mBands.equals(ani.mBands));
}
@Override
public int hashCode() {
- return Objects.hash(mSubId, mPriority, mMccMncs);
+ return Objects.hash(mSubId, mPriority, mMccMncs, mBands);
}
public static final @android.annotation.NonNull Parcelable.Creator<AvailableNetworkInfo> CREATOR =
@@ -161,9 +189,9 @@
@Override
public String toString() {
return ("AvailableNetworkInfo:"
- + " mSubId: " + mSubId
- + " mPriority: " + mPriority
- + " mMccMncs: " + Arrays.toString(mMccMncs.toArray()));
+ + " mSubId: " + mSubId
+ + " mPriority: " + mPriority
+ + " mMccMncs: " + Arrays.toString(mMccMncs.toArray())
+ + " mBands: " + Arrays.toString(mBands.toArray()));
}
}
-
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
old mode 100644
new mode 100755
index d680b89..d79a168
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -31,6 +31,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.carrier.CarrierService;
+import android.telecom.TelecomManager;
import android.telephony.ims.ImsReasonInfo;
import com.android.internal.telephony.ICarrierConfigLoader;
@@ -71,10 +72,10 @@
* one is available for the slot index. An optional int extra
* {@link TelephonyManager#EXTRA_CARRIER_ID} is included to indicate the carrier id for the
* changed carrier configuration. An optional int extra
- * {@link TelephonyManager#EXTRA_PRECISE_CARRIER_ID} is included to indicate the precise
+ * {@link TelephonyManager#EXTRA_SPECIFIC_CARRIER_ID} is included to indicate the precise
* carrier id for the changed carrier configuration.
* @see TelephonyManager#getSimCarrierId()
- * @see TelephonyManager#getSimPreciseCarrierId()
+ * @see TelephonyManager#getSimSpecificCarrierId()
*/
public static final String
ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
@@ -2114,6 +2115,18 @@
public static final String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
/**
+ * Boolean flag indicating whether the carrier supports TTY.
+ * <p>
+ * Note that {@link #KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL} controls availability of TTY over
+ * VoLTE; if {@link #KEY_TTY_SUPPORTED_BOOL} is disabled, then
+ * {@link #KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL} is also implicitly disabled.
+ * <p>
+ * {@link TelecomManager#isTtySupported()} should be used to determine if a device supports TTY,
+ * and this carrier config key should be used to see if the current carrier supports it.
+ */
+ public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
+
+ /**
* Indicates if the carrier supports auto-upgrading a call to RTT when receiving a call from a
* RTT-supported device.
* @hide
@@ -2633,6 +2646,25 @@
public static final String KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY =
"cdma_enhanced_roaming_indicator_for_home_network_int_array";
+ /**
+ * Indicates use 3GPP application to replace 3GPP2 application even if it's a CDMA/CDMA-LTE
+ * phone, becasue some carriers's CSIM application is present but not supported.
+ * @hide
+ */
+ public static final String KEY_USE_USIM_BOOL = "use_usim_bool";
+
+ /**
+ * Determines whether the carrier wants to cancel the cs reject notification automatically
+ * when the voice registration state changes.
+ * If true, the notification will be automatically removed
+ * when the voice registration state changes.
+ * If false, the notification will persist until the user dismisses it,
+ * the SIM is removed, or the device is rebooted.
+ * @hide
+ */
+ public static final String KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION =
+ "carrier_auto_cancel_cs_notification";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -2952,6 +2984,7 @@
sDefaults.putStringArray(KEY_ROAMING_OPERATOR_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
sDefaults.putBoolean(KEY_RTT_SUPPORTED_BOOL, false);
+ sDefaults.putBoolean(KEY_TTY_SUPPORTED_BOOL, true);
sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true);
sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
@@ -3017,6 +3050,8 @@
1 /* Roaming Indicator Off */
});
sDefaults.putStringArray(KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY, new String[0]);
+ sDefaults.putBoolean(KEY_USE_USIM_BOOL, false);
+ sDefaults.putBoolean(KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION, false);
}
/**
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 223f3ef..1796034 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -22,7 +22,6 @@
import android.hardware.radio.V1_4.CellInfo.Info;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.SystemClock;
import com.android.internal.annotations.VisibleForTesting;
@@ -325,9 +324,9 @@
}
/** @hide */
- protected CellInfo(android.hardware.radio.V1_4.CellInfo ci) {
+ protected CellInfo(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
this.mRegistered = ci.isRegistered;
- this.mTimeStamp = SystemClock.elapsedRealtimeNanos();
+ this.mTimeStamp = timeStamp;
this.mCellConnectionStatus = ci.connectionStatus;
}
@@ -358,14 +357,14 @@
}
/** @hide */
- public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci) {
+ public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
if (ci == null) return null;
switch (ci.info.getDiscriminator()) {
- case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci);
- case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci);
- case Info.hidl_discriminator.lte: return new CellInfoLte(ci);
- case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci);
- case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci);
+ case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci, timeStamp);
+ case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci, timeStamp);
+ case Info.hidl_discriminator.lte: return new CellInfoLte(ci, timeStamp);
+ case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci, timeStamp);
+ case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci, timeStamp);
default: return null;
}
}
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index 9c38506..82bb3961 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -68,8 +68,8 @@
}
/** @hide */
- public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci) {
- super(ci);
+ public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+ super(ci, timeStamp);
final android.hardware.radio.V1_2.CellInfoCdma cic = ci.info.cdma();
mCellIdentityCdma = new CellIdentityCdma(cic.cellIdentityCdma);
mCellSignalStrengthCdma =
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index 0d91f80..59fcd1e 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -64,8 +64,8 @@
}
/** @hide */
- public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci) {
- super(ci);
+ public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+ super(ci, timeStamp);
final android.hardware.radio.V1_2.CellInfoGsm cig = ci.info.gsm();
mCellIdentityGsm = new CellIdentityGsm(cig.cellIdentityGsm);
mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index deae632..08dafe1 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -71,8 +71,8 @@
}
/** @hide */
- public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci) {
- super(ci);
+ public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+ super(ci, timeStamp);
final android.hardware.radio.V1_4.CellInfoLte cil = ci.info.lte();
mCellIdentityLte = new CellIdentityLte(cil.base.cellIdentityLte);
mCellSignalStrengthLte = new CellSignalStrengthLte(cil.base.signalStrengthLte);
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index ae43bb2..93baabf 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -65,8 +65,8 @@
}
/** @hide */
- public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci) {
- super(ci);
+ public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+ super(ci, timeStamp);
final android.hardware.radio.V1_2.CellInfoTdscdma cit = ci.info.tdscdma();
mCellIdentityTdscdma = new CellIdentityTdscdma(cit.cellIdentityTdscdma);
mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index d2287ea..02dbb1a 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -64,8 +64,8 @@
}
/** @hide */
- public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci) {
- super(ci);
+ public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+ super(ci, timeStamp);
final android.hardware.radio.V1_2.CellInfoWcdma ciw = ci.info.wcdma();
mCellIdentityWcdma = new CellIdentityWcdma(ciw.cellIdentityWcdma);
mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 3dea6f4..0aeb0f6 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -151,6 +151,17 @@
}
/**
+ * Return the Received Signal Strength Indicator
+ *
+ * @return the RSSI in dBm (-113, -51) or
+ * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}.
+ * @hide
+ */
+ public int getRssi() {
+ return mRssi;
+ }
+
+ /**
* Return the Bit Error Rate
*
* @return the bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
diff --git a/telephony/java/android/telephony/MbmsGroupCallSession.java b/telephony/java/android/telephony/MbmsGroupCallSession.java
index 269cda1..f1be31f 100644
--- a/telephony/java/android/telephony/MbmsGroupCallSession.java
+++ b/telephony/java/android/telephony/MbmsGroupCallSession.java
@@ -141,7 +141,7 @@
* Create a new {@link MbmsGroupCallSession} using the system default data subscription ID.
* See {@link #create(Context, int, Executor, MbmsGroupCallSessionCallback)}.
*/
- public static MbmsGroupCallSession create(@NonNull Context context,
+ public static @Nullable MbmsGroupCallSession create(@NonNull Context context,
@NonNull Executor executor, @NonNull MbmsGroupCallSessionCallback callback) {
return create(context, SubscriptionManager.getDefaultSubscriptionId(), executor, callback);
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 4dcb410..549c044 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -25,12 +25,11 @@
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Resources;
import android.database.Cursor;
import android.location.CountryDetector;
import android.net.Uri;
-import android.os.SystemProperties;
import android.os.PersistableBundle;
+import android.os.SystemProperties;
import android.provider.Contacts;
import android.provider.ContactsContract;
import android.telecom.PhoneAccount;
@@ -1738,7 +1737,7 @@
* @return true if the number is in the list of emergency numbers
* listed in the RIL / SIM, otherwise return false.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)} instead.
+ * @deprecated Please use {@link TelephonyManager#isEmergencyNumber(String)} instead.
*/
@Deprecated
public static boolean isEmergencyNumber(String number) {
@@ -1754,7 +1753,7 @@
* @return true if the number is in the list of emergency numbers
* listed in the RIL / SIM, otherwise return false.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isEmergencyNumber(String)}
* instead.
*
* @hide
@@ -1785,7 +1784,7 @@
* listed in the RIL / SIM, *or* if the number starts with the
* same digits as any of those emergency numbers.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isPotentialEmergencyNumber(String)}
* instead.
*
* @hide
@@ -1814,7 +1813,7 @@
* listed in the RIL / SIM, *or* if the number starts with the
* same digits as any of those emergency numbers.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isPotentialEmergencyNumber(String)}
* instead.
*
* @hide
@@ -1883,7 +1882,7 @@
* @return if the number is an emergency number for the specific country, then return true,
* otherwise false
*
- * @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isEmergencyNumber(String)}
* instead.
*
* @hide
@@ -1903,7 +1902,7 @@
* @return if the number is an emergency number for the specific country, then return true,
* otherwise false
*
- * @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isEmergencyNumber(String)}
* instead.
*
* @hide
@@ -1934,7 +1933,7 @@
* country, *or* if the number starts with the same digits as
* any of those emergency numbers.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isPotentialEmergencyNumber(String)}
* instead.
*
* @hide
@@ -1964,7 +1963,7 @@
* country, *or* if the number starts with the same digits as
* any of those emergency numbers.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isPotentialEmergencyNumber(String)}
* instead.
*
* @hide
@@ -2017,7 +2016,7 @@
private static boolean isEmergencyNumberInternal(int subId, String number,
String defaultCountryIso,
boolean useExactMatch) {
- return TelephonyManager.getDefault().isCurrentEmergencyNumber(number);
+ return TelephonyManager.getDefault().isEmergencyNumber(number);
}
/**
@@ -2028,7 +2027,7 @@
* @return true if the specified number is an emergency number for the country the user
* is currently in.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isEmergencyNumber(String)}
* instead.
*/
@Deprecated
@@ -2045,7 +2044,7 @@
* @return true if the specified number is an emergency number for the country the user
* is currently in.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isEmergencyNumber(String)}
* instead.
*
* @hide
@@ -2079,7 +2078,7 @@
*
* @see android.location.CountryDetector
*
- * @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isPotentialEmergencyNumber(String)}
* instead.
*
* @hide
@@ -2110,7 +2109,7 @@
* @return true if the specified number is an emergency number for a local country, based on the
* CountryDetector.
*
- * @deprecated Please use {@link TelephonyManager#isCurrentPotentialEmergencyNumber(String)}
+ * @deprecated Please use {@link TelephonyManager#isPotentialEmergencyNumber(String)}
* instead.
*
* @hide
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index fae7920..07ffaac 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -322,6 +322,7 @@
* <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
* <code>RESULT_ERROR_RADIO_OFF</code><br>
* <code>RESULT_ERROR_NULL_PDU</code><br>
+ * <code>RESULT_ERROR_NO_SERVICE</code><br>
* For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.<br>
@@ -371,19 +372,12 @@
if (DBG) {
Log.d(TAG, "for subId: " + subId + ", subscription-info: " + info);
}
- if (info == null) {
- // There is no subscription for the given subId. That can only mean one thing:
- // the caller is using a SmsManager instance with an obsolete subscription id.
- // That is most probably because caller didn't invalidate SmsManager instance
- // for an already deleted subscription id.
- Log.e(TAG, "subId: " + subId + " for this SmsManager instance is obsolete.");
- sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_NO_SERVICE);
- }
/* If the Subscription associated with this SmsManager instance belongs to a remote-sim,
* then send the message thru the remote-sim subscription.
*/
- if (info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) {
+ if (info != null
+ && info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) {
if (DBG) Log.d(TAG, "sending message thru bluetooth");
sendTextMessageBluetooth(destinationAddress, scAddress, text, sentIntent,
deliveryIntent, info);
@@ -391,8 +385,10 @@
}
try {
+ // If the subscription is invalid or default, we will use the default phone to send the
+ // SMS and possibly fail later in the SMS sending process.
ISms iccISms = getISmsServiceOrThrow();
- iccISms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
+ iccISms.sendTextForSubscriber(subId, ActivityThread.currentPackageName(),
destinationAddress,
scAddress, text, sentIntent, deliveryIntent,
persistMessage);
@@ -465,6 +461,9 @@
}
private void sendErrorInPendingIntent(PendingIntent intent, int errorCode) {
+ if (intent == null) {
+ return;
+ }
try {
intent.send(errorCode);
} catch (PendingIntent.CanceledException e) {
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index fb6f39d..245f5b3 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -425,14 +425,14 @@
/**
* @return The MCC, as a string.
*/
- public String getMccString() {
+ public @Nullable String getMccString() {
return this.mMcc;
}
/**
* @return The MNC, as a string.
*/
- public String getMncString() {
+ public @Nullable String getMncString() {
return this.mMnc;
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 8edc5b4..d9a37c6 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2706,7 +2706,8 @@
* 1) Even if it's active, it will be dormant most of the time. The modem will not try
* to scan or camp until it knows an available network is nearby to save power.
* 2) Telephony relies on system app or carrier input to notify nearby available networks.
- * See {@link TelephonyManager#updateAvailableNetworks(List)} for more information.
+ * See {@link TelephonyManager#updateAvailableNetworks(List, Executor, Consumer)}
+ * for more information.
* 3) In multi-SIM devices, when the network is nearby and camped, system may automatically
* switch internet data between it and default data subscription, based on carrier
* recommendation and its signal strength and metered-ness, etc.
@@ -2938,7 +2939,7 @@
}
/**
- * Enabled or disable a subscription. This is currently used in the settings page.
+ * Enables or disables a subscription. This is currently used in the settings page.
*
* <p>
* Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 7954d0e..16dafd6 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -84,6 +84,7 @@
import com.android.internal.telephony.ISetOpportunisticDataCallback;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
import com.android.internal.telephony.OperatorInfo;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
@@ -95,6 +96,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -1248,30 +1250,34 @@
public static final String EXTRA_CARRIER_NAME = "android.telephony.extra.CARRIER_NAME";
/**
- * Broadcast Action: The subscription precise carrier identity has changed.
- * The precise carrier id can be used to further differentiate a carrier by different
- * networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
- * carrier id returned by {@link #getSimCarrierId()} but could have multiple precise carrier id.
- * e.g, {@link #getSimCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM,
- * while {@link #getSimPreciseCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based
- * on the current subscription IMSI. For carriers without any fine-grained ids, precise carrier
- * id is same as carrier id.
+ * Broadcast Action: The subscription specific carrier identity has changed.
+ *
+ * A specific carrier ID returns the fine-grained carrier ID of the current subscription.
+ * It can represent the fact that a carrier may be in effect an aggregation of other carriers
+ * (ie in an MVNO type scenario) where each of these specific carriers which are used to make
+ * up the actual carrier service may have different carrier configurations.
+ * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
+ * different carrier configuration for different service offering such as a prepaid plan.
+ *
+ * the specific carrier ID would be used for configuration purposes, but apps wishing to know
+ * about the carrier itself should use the regular carrier ID returned by
+ * {@link #getSimCarrierId()}.
*
* <p>Similar like {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED}, this intent will be
* sent on the event of {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} while its also
* possible to be sent without {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} when
- * precise carrier id changes with the same carrier id.
+ * specific carrier ID changes while carrier ID remains the same.
* e.g, the same subscription switches to different IMSI could potentially change its
- * precise carrier id while carrier id remains the same.
- * @see #getSimPreciseCarrierId()
+ * specific carrier ID while carrier id remains the same.
+ * @see #getSimSpecificCarrierId()
* @see #getSimCarrierId()
*
* The intent will have the following extra values:
* <ul>
- * <li>{@link #EXTRA_PRECISE_CARRIER_ID} The up-to-date precise carrier id of the
+ * <li>{@link #EXTRA_SPECIFIC_CARRIER_ID} The up-to-date specific carrier id of the
* current subscription.
* </li>
- * <li>{@link #EXTRA_PRECISE_CARRIER_NAME} The up-to-date name of the precise carrier id.
+ * <li>{@link #EXTRA_SPECIFIC_CARRIER_NAME} The up-to-date name of the specific carrier id.
* </li>
* <li>{@link #EXTRA_SUBSCRIPTION_ID} The subscription id associated with the changed carrier
* identity.
@@ -1280,30 +1286,30 @@
* <p class="note">This is a protected intent that can only be sent by the system.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED =
- "android.telephony.action.SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED";
+ public static final String ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED =
+ "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED";
/**
- * An int extra used with {@link #ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED} which
- * indicates the updated precise carrier id returned by
- * {@link TelephonyManager#getSimPreciseCarrierId()}. Note, its possible precise carrier id
+ * An int extra used with {@link #ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED} which
+ * indicates the updated specific carrier id returned by
+ * {@link TelephonyManager#getSimSpecificCarrierId()}. Note, its possible specific carrier id
* changes while {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} remains the same
* e.g, when subscription switch to different IMSIs.
* <p>Will be {@link TelephonyManager#UNKNOWN_CARRIER_ID} if the subscription is unavailable or
* the carrier cannot be identified.
*/
- public static final String EXTRA_PRECISE_CARRIER_ID =
- "android.telephony.extra.PRECISE_CARRIER_ID";
+ public static final String EXTRA_SPECIFIC_CARRIER_ID =
+ "android.telephony.extra.SPECIFIC_CARRIER_ID";
/**
- * An string extra used with {@link #ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED} which
- * indicates the updated precise carrier name returned by
- * {@link TelephonyManager#getSimPreciseCarrierIdName()}.
- * <p>it's a user-facing name of the precise carrier id {@link #EXTRA_PRECISE_CARRIER_ID}, e.g,
- * Tracfone-AT&T.
+ * An string extra used with {@link #ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED}
+ * which indicates the updated specific carrier name returned by
+ * {@link TelephonyManager#getSimSpecificCarrierIdName()}.
+ * <p>it's a user-facing name of the specific carrier id {@link #EXTRA_SPECIFIC_CARRIER_ID}
+ * e.g, Tracfone-AT&T
*/
- public static final String EXTRA_PRECISE_CARRIER_NAME =
- "android.telephony.extra.PRECISE_CARRIER_NAME";
+ public static final String EXTRA_SPECIFIC_CARRIER_NAME =
+ "android.telephony.extra.SPECIFIC_CARRIER_NAME";
/**
* An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} to indicate the
@@ -8940,17 +8946,23 @@
}
/**
- * Returns fine-grained carrier id of the current subscription.
+ * Returns fine-grained carrier ID of the current subscription.
*
- * <p>The precise carrier id can be used to further differentiate a carrier by different
- * networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
- * carrier id returned by {@link #getSimCarrierId()} but could have multiple precise carrier id.
- * e.g, {@link #getSimCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM,
- * while {@link #getSimPreciseCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based
- * on the current subscription IMSI.
+ * A specific carrier ID can represent the fact that a carrier may be in effect an aggregation
+ * of other carriers (ie in an MVNO type scenario) where each of these specific carriers which
+ * are used to make up the actual carrier service may have different carrier configurations.
+ * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
+ * different carrier configuration for different service offering such as a prepaid plan.
*
- * <p>For carriers without any fine-grained carrier ids, return {@link #getSimCarrierId()}
- * <p>Precise carrier ids are defined in the same way as carrier id
+ * the specific carrier ID would be used for configuration purposes, but apps wishing to know
+ * about the carrier itself should use the regular carrier ID returned by
+ * {@link #getSimCarrierId()}.
+ *
+ * e.g, Tracfone SIMs could return different specific carrier ID based on IMSI from current
+ * subscription while carrier ID remains the same.
+ *
+ * <p>For carriers without fine-grained specific carrier ids, return {@link #getSimCarrierId()}
+ * <p>Specific carrier ids are defined in the same way as carrier id
* <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
* except each with a "parent" id linking to its top-level carrier id.
*
@@ -8958,11 +8970,11 @@
* Return {@link #UNKNOWN_CARRIER_ID} if the subscription is unavailable or the carrier cannot
* be identified.
*/
- public int getSimPreciseCarrierId() {
+ public int getSimSpecificCarrierId() {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getSubscriptionPreciseCarrierId(getSubId());
+ return service.getSubscriptionSpecificCarrierId(getSubId());
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -8972,18 +8984,22 @@
/**
* Similar like {@link #getSimCarrierIdName()}, returns user-facing name of the
- * precise carrier id returned by {@link #getSimPreciseCarrierId()}.
+ * specific carrier id returned by {@link #getSimSpecificCarrierId()}.
+ *
+ * The specific carrier ID would be used for configuration purposes, but apps wishing to know
+ * about the carrier itself should use the regular carrier ID returned by
+ * {@link #getSimCarrierIdName()}.
*
* <p>The returned name is unlocalized.
*
- * @return user-facing name of the subscription precise carrier id. Return {@code null} if the
+ * @return user-facing name of the subscription specific carrier id. Return {@code null} if the
* subscription is unavailable or the carrier cannot be identified.
*/
- public @Nullable CharSequence getSimPreciseCarrierIdName() {
+ public @Nullable CharSequence getSimSpecificCarrierIdName() {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getSubscriptionPreciseCarrierName(getSubId());
+ return service.getSubscriptionSpecificCarrierName(getSubId());
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -10015,18 +10031,21 @@
* a SecurityException if the caller does not have the permission.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- @Nullable
- public Map<Integer, List<EmergencyNumber>> getCurrentEmergencyNumberList() {
+ @NonNull
+ public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList() {
+ Map<Integer, List<EmergencyNumber>> emergencyNumberList = new HashMap<>();
try {
ITelephony telephony = getITelephony();
- if (telephony == null) {
- return null;
+ if (telephony != null) {
+ return telephony.getEmergencyNumberList(mContext.getOpPackageName());
+ } else {
+ throw new IllegalStateException("telephony service is null.");
}
- return telephony.getCurrentEmergencyNumberList(mContext.getOpPackageName());
} catch (RemoteException ex) {
- Log.e(TAG, "getCurrentEmergencyNumberList RemoteException", ex);
+ Log.e(TAG, "getEmergencyNumberList RemoteException", ex);
+ ex.rethrowAsRuntimeException();
}
- return null;
+ return emergencyNumberList;
}
/**
@@ -10065,31 +10084,34 @@
* a SecurityException if the caller does not have the permission.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- @Nullable
- public Map<Integer, List<EmergencyNumber>> getCurrentEmergencyNumberList(
+ @NonNull
+ public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList(
@EmergencyServiceCategories int categories) {
+ Map<Integer, List<EmergencyNumber>> emergencyNumberList = new HashMap<>();
try {
ITelephony telephony = getITelephony();
- if (telephony == null) {
- return null;
- }
- Map<Integer, List<EmergencyNumber>> numberMap = telephony
- .getCurrentEmergencyNumberList(mContext.getOpPackageName());
- if (numberMap != null) {
- for (Integer subscriptionId : numberMap.keySet()) {
- List<EmergencyNumber> numberList = numberMap.get(subscriptionId);
- for (EmergencyNumber number : numberList) {
- if (!number.isInEmergencyServiceCategories(categories)) {
- numberList.remove(number);
+ if (telephony != null) {
+ emergencyNumberList = telephony.getEmergencyNumberList(
+ mContext.getOpPackageName());
+ if (emergencyNumberList != null) {
+ for (Integer subscriptionId : emergencyNumberList.keySet()) {
+ List<EmergencyNumber> numberList = emergencyNumberList.get(subscriptionId);
+ for (EmergencyNumber number : numberList) {
+ if (!number.isInEmergencyServiceCategories(categories)) {
+ numberList.remove(number);
+ }
}
}
}
+ return emergencyNumberList;
+ } else {
+ throw new IllegalStateException("telephony service is null.");
}
- return numberMap;
} catch (RemoteException ex) {
- Log.e(TAG, "getCurrentEmergencyNumberList with Categories RemoteException", ex);
+ Log.e(TAG, "getEmergencyNumberList with Categories RemoteException", ex);
+ ex.rethrowAsRuntimeException();
}
- return null;
+ return emergencyNumberList;
}
/**
@@ -10103,15 +10125,17 @@
* @return {@code true} if the given number is an emergency number based on current locale,
* sim, modem and network; {@code false} otherwise.
*/
- public boolean isCurrentEmergencyNumber(@NonNull String number) {
+ public boolean isEmergencyNumber(@NonNull String number) {
try {
ITelephony telephony = getITelephony();
- if (telephony == null) {
- return false;
+ if (telephony != null) {
+ return telephony.isEmergencyNumber(number, true);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
}
- return telephony.isCurrentEmergencyNumber(number, true);
} catch (RemoteException ex) {
- Log.e(TAG, "isCurrentEmergencyNumber RemoteException", ex);
+ Log.e(TAG, "isEmergencyNumber RemoteException", ex);
+ ex.rethrowAsRuntimeException();
}
return false;
}
@@ -10140,15 +10164,17 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isCurrentPotentialEmergencyNumber(@NonNull String number) {
+ public boolean isPotentialEmergencyNumber(@NonNull String number) {
try {
ITelephony telephony = getITelephony();
- if (telephony == null) {
- return false;
+ if (telephony != null) {
+ return telephony.isEmergencyNumber(number, false);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
}
- return telephony.isCurrentEmergencyNumber(number, false);
} catch (RemoteException ex) {
- Log.e(TAG, "isCurrentEmergencyNumber RemoteException", ex);
+ Log.e(TAG, "isEmergencyNumber RemoteException", ex);
+ ex.rethrowAsRuntimeException();
}
return false;
}
@@ -10176,6 +10202,41 @@
*/
public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"UPDATE_AVAILABLE_NETWORKS"}, value = {
+ UPDATE_AVAILABLE_NETWORKS_SUCCESS,
+ UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE,
+ UPDATE_AVAILABLE_NETWORKS_ABORTED,
+ UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS,
+ UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE})
+ public @interface UpdateAvailableNetworksResult {}
+
+ /**
+ * No error. Operation succeeded.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0;
+
+ /**
+ * There is a unknown failure happened.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1;
+
+ /**
+ * The request is aborted.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2;
+
+ /**
+ * The parameter passed in is invalid.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3;
+
+ /**
+ * No carrier privilege.
+ */
+ public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4;
+
/**
* Set preferred opportunistic data subscription id.
*
@@ -10258,28 +10319,46 @@
* This api should be called to inform OpportunisticNetwork Service about the availability
* of a network at the current location. This information will be used by OpportunisticNetwork
* service to decide to attach to the network opportunistically. If an empty list is passed,
- * it is assumed that no network is available.
+ * it is assumed that no network is available and will result in disabling the modem stack
+ * to save power.
* Requires that the calling app has carrier privileges on both primary and
* secondary subscriptions (see {@link #hasCarrierPrivileges}), or has permission
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
* @param availableNetworks is a list of available network information.
- * @return true if request is accepted
+ * @param executor The executor of where the callback will execute.
+ * @param callback Callback will be triggered once it succeeds or failed.
*
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
- public boolean updateAvailableNetworks(List<AvailableNetworkInfo> availableNetworks) {
+ public void updateAvailableNetworks(@NonNull List<AvailableNetworkInfo> availableNetworks,
+ @Nullable @CallbackExecutor Executor executor,
+ @UpdateAvailableNetworksResult @Nullable Consumer<Integer> callback) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
- boolean ret = false;
try {
IOns iOpportunisticNetworkService = getIOns();
- if (iOpportunisticNetworkService != null && availableNetworks != null) {
- ret = iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks,
- pkgForDebug);
+ if (iOpportunisticNetworkService == null || availableNetworks == null) {
+ Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+ callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
+ }));
+ return;
}
+ IUpdateAvailableNetworksCallback callbackStub =
+ new IUpdateAvailableNetworksCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ if (executor == null || callback == null) {
+ return;
+ }
+ Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+ callback.accept(result);
+ }));
+ }
+ };
+ iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks, callbackStub,
+ pkgForDebug);
} catch (RemoteException ex) {
Rlog.e(TAG, "updateAvailableNetworks RemoteException", ex);
}
- return ret;
}
/**
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index 332aae1..bcb47f7 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -243,7 +243,6 @@
*/
public boolean isPreferred() { return mPreferred; }
- /** @hide */
@Override
public int describeContents() {
return 0;
@@ -266,7 +265,6 @@
return (o == this || toString().equals(o.toString()));
}
- /** @hide */
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mProfileId);
@@ -288,7 +286,6 @@
dest.writeBoolean(mPreferred);
}
- /** @hide */
public static final @android.annotation.NonNull Parcelable.Creator<DataProfile> CREATOR =
new Parcelable.Creator<DataProfile>() {
@Override
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 5373c38..173f4ed 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -302,7 +302,7 @@
*
* @return the dialing number.
*/
- public String getNumber() {
+ public @NonNull String getNumber() {
return mNumber;
}
@@ -311,7 +311,7 @@
*
* @return the country code string (lowercase character) in ISO 3166 format.
*/
- public String getCountryIso() {
+ public @NonNull String getCountryIso() {
return mCountryIso;
}
@@ -320,7 +320,7 @@
*
* @return the Mobile Network Code of the emergency number.
*/
- public String getMnc() {
+ public @NonNull String getMnc() {
return mMnc;
}
@@ -328,6 +328,8 @@
* Returns the bitmask of emergency service categories of the emergency number.
*
* @return bitmask of the emergency service categories
+ *
+ * @hide
*/
public @EmergencyServiceCategories int getEmergencyServiceCategoryBitmask() {
return mEmergencyServiceCategoryBitmask;
@@ -357,7 +359,7 @@
*
* @return a list of the emergency service categories
*/
- public List<Integer> getEmergencyServiceCategories() {
+ public @NonNull List<Integer> getEmergencyServiceCategories() {
List<Integer> categories = new ArrayList<>();
if (serviceUnspecified()) {
categories.add(EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED);
@@ -384,7 +386,7 @@
* number does not have a specified emergency Uniform Resource Name.
*/
public @NonNull List<String> getEmergencyUrns() {
- return mEmergencyUrns;
+ return Collections.unmodifiableList(mEmergencyUrns);
}
/**
@@ -421,6 +423,8 @@
* Returns the bitmask of the sources of the emergency number.
*
* @return bitmask of the emergency number sources
+ *
+ * @hide
*/
public @EmergencyNumberSources int getEmergencyNumberSourceBitmask() {
return mEmergencyNumberSourceBitmask;
@@ -431,7 +435,7 @@
*
* @return a list of emergency number sources
*/
- public List<Integer> getEmergencyNumberSources() {
+ public @NonNull List<Integer> getEmergencyNumberSources() {
List<Integer> sources = new ArrayList<>();
for (Integer source : EMERGENCY_NUMBER_SOURCE_SET) {
if ((mEmergencyNumberSourceBitmask & source) == source) {
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 793ac3c..751ce9d 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Bundle;
@@ -842,7 +843,7 @@
* 3gpp 22.101, Section 10 - Emergency Calls.
*/
@VisibleForTesting
- public void setEmergencyUrns(List<String> emergencyUrns) {
+ public void setEmergencyUrns(@NonNull List<String> emergencyUrns) {
mEmergencyUrns = emergencyUrns;
}
@@ -916,7 +917,7 @@
* Reference: 3gpp 24.503, Section 5.1.6.8.1 - General;
* 3gpp 22.101, Section 10 - Emergency Calls.
*/
- public List<String> getEmergencyUrns() {
+ public @NonNull List<String> getEmergencyUrns() {
return mEmergencyUrns;
}
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 9104d9f..d12cda8 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -154,7 +154,7 @@
* @param item the IMS provisioning key constant, as defined by the OEM.
* @param value the new String value of the IMS configuration constant.
*/
- public void onProvisioningStringChanged(int item, String value) {
+ public void onProvisioningStringChanged(int item, @NonNull String value) {
// Base Implementation
}
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index 0364477..2c48b65 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -19,6 +19,7 @@
import android.telephony.AvailableNetworkInfo;
import com.android.internal.telephony.ISetOpportunisticDataCallback;
+import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
interface IOns {
@@ -97,9 +98,9 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
* @param availableNetworks is a list of available network information.
* @param callingPackage caller's package name
- * @return true if request is accepted
+ * @param callback callback upon request completion.
*
*/
- boolean updateAvailableNetworks(in List<AvailableNetworkInfo> availableNetworks,
- String callingPackage);
+ void updateAvailableNetworks(in List<AvailableNetworkInfo> availableNetworks,
+ IUpdateAvailableNetworksCallback callbackStub, String callingPackage);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index b90194a..122747a65 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1369,7 +1369,7 @@
/**
* Returns fine-grained carrier id of the current subscription.
*
- * <p>The precise carrier id can be used to further differentiate a carrier by different
+ * <p>The specific carrier id can be used to further differentiate a carrier by different
* networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
* carrier id {@link #getSimCarrierId()} but can have multiple precise carrier id. e.g,
* {@link #getSimCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM, while
@@ -1383,19 +1383,19 @@
* be identified.
* @hide
*/
- int getSubscriptionPreciseCarrierId(int subId);
+ int getSubscriptionSpecificCarrierId(int subId);
/**
* Similar like {@link #getSimCarrierIdName()}, returns user-facing name of the
- * precise carrier id {@link #getSimPreciseCarrierId()}
+ * specific carrier id {@link #getSimSpecificCarrierId()}
*
* <p>The returned name is unlocalized.
*
- * @return user-facing name of the subscription precise carrier id. Return {@code null} if the
+ * @return user-facing name of the subscription specific carrier id. Return {@code null} if the
* subscription is unavailable or the carrier cannot be identified.
* @hide
*/
- String getSubscriptionPreciseCarrierName(int subId);
+ String getSubscriptionSpecificCarrierName(int subId);
/**
* Returns carrier id based on MCCMNC only. This will return a MNO carrier id used for fallback
@@ -1773,12 +1773,12 @@
/**
* Return the emergency number list from all the active subscriptions.
*/
- Map getCurrentEmergencyNumberList(String callingPackage);
+ Map getEmergencyNumberList(String callingPackage);
/**
* Identify if the number is emergency number, based on all the active subscriptions.
*/
- boolean isCurrentEmergencyNumber(String number, boolean exactMatch);
+ boolean isEmergencyNumber(String number, boolean exactMatch);
/**
* Return a list of certs in hex string from loaded carrier privileges access rules.
diff --git a/core/java/android/app/role/IRoleManagerCallback.aidl b/telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl
similarity index 69%
copy from core/java/android/app/role/IRoleManagerCallback.aidl
copy to telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl
index c0f8eea..8fe086ce 100644
--- a/core/java/android/app/role/IRoleManagerCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package android.app.role;
+package com.android.internal.telephony;
/**
+ * Callback to provide asynchronous result of updateAvailableNetworks.
* @hide
*/
-oneway interface IRoleManagerCallback {
-
- void onSuccess();
-
- void onFailure();
+oneway interface IUpdateAvailableNetworksCallback {
+ void onComplete(int result);
}
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/java/com/android/internal/telephony/SmsApplication.java
index 7478a00..ef7c605 100644
--- a/telephony/java/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/java/com/android/internal/telephony/SmsApplication.java
@@ -19,7 +19,6 @@
import android.Manifest.permission;
import android.app.AppOpsManager;
import android.app.role.RoleManager;
-import android.app.role.RoleManagerCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -51,9 +50,11 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
/**
* Class for managing the primary application that we will deliver SMS/MMS messages to
@@ -634,12 +635,19 @@
}
// Update the setting.
- RoleManagerCallback.Future res = new RoleManagerCallback.Future();
+ CompletableFuture<Void> future = new CompletableFuture<>();
+ Consumer<Boolean> callback = successful -> {
+ if (successful) {
+ future.complete(null);
+ } else {
+ future.completeExceptionally(new RuntimeException());
+ }
+ };
context.getSystemService(RoleManager.class).addRoleHolderAsUser(
RoleManager.ROLE_SMS, applicationData.mPackageName, 0, UserHandle.of(userId),
- AsyncTask.THREAD_POOL_EXECUTOR, res);
+ AsyncTask.THREAD_POOL_EXECUTOR, callback);
try {
- res.get(5, TimeUnit.SECONDS);
+ future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Log.e(LOG_TAG, "Exception while adding sms role holder " + applicationData, e);
return;
diff --git a/tests/AccessibilityEventsLogger/Android.bp b/tests/AccessibilityEventsLogger/Android.bp
new file mode 100644
index 0000000..ead1656
--- /dev/null
+++ b/tests/AccessibilityEventsLogger/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+ name: "AccessibilityEventsLogger",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/AccessibilityEventsLogger/Android.mk b/tests/AccessibilityEventsLogger/Android.mk
deleted file mode 100644
index 4224017..0000000
--- a/tests/AccessibilityEventsLogger/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AccessibilityEventsLogger
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AccessoryDisplay/Android.mk b/tests/AccessoryDisplay/Android.mk
deleted file mode 100644
index 85cb309..0000000
--- a/tests/AccessoryDisplay/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/AccessoryDisplay/common/Android.bp b/tests/AccessoryDisplay/common/Android.bp
new file mode 100644
index 0000000..3ce4c57
--- /dev/null
+++ b/tests/AccessoryDisplay/common/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+java_library_static {
+ name: "AccessoryDisplayCommon",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+}
diff --git a/tests/AccessoryDisplay/common/Android.mk b/tests/AccessoryDisplay/common/Android.mk
deleted file mode 100644
index 2d4de15..0000000
--- a/tests/AccessoryDisplay/common/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_MODULE := AccessoryDisplayCommon
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/AccessoryDisplay/sink/Android.bp b/tests/AccessoryDisplay/sink/Android.bp
new file mode 100644
index 0000000..4e50a81
--- /dev/null
+++ b/tests/AccessoryDisplay/sink/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+ name: "AccessoryDisplaySink",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ static_libs: ["AccessoryDisplayCommon"],
+}
diff --git a/tests/AccessoryDisplay/sink/Android.mk b/tests/AccessoryDisplay/sink/Android.mk
deleted file mode 100644
index 772ce0c..0000000
--- a/tests/AccessoryDisplay/sink/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := AccessoryDisplaySink
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_STATIC_JAVA_LIBRARIES := AccessoryDisplayCommon
-include $(BUILD_PACKAGE)
diff --git a/tests/AccessoryDisplay/source/Android.bp b/tests/AccessoryDisplay/source/Android.bp
new file mode 100644
index 0000000..6d8087f
--- /dev/null
+++ b/tests/AccessoryDisplay/source/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+ name: "AccessoryDisplaySource",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ static_libs: ["AccessoryDisplayCommon"],
+}
diff --git a/tests/AccessoryDisplay/source/Android.mk b/tests/AccessoryDisplay/source/Android.mk
deleted file mode 100644
index 5d1085d..0000000
--- a/tests/AccessoryDisplay/source/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := AccessoryDisplaySource
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_STATIC_JAVA_LIBRARIES := AccessoryDisplayCommon
-include $(BUILD_PACKAGE)
diff --git a/tests/ActivityTests/Android.bp b/tests/ActivityTests/Android.bp
new file mode 100644
index 0000000..0182862
--- /dev/null
+++ b/tests/ActivityTests/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+ name: "ActivityTest",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/tests/ActivityTests/Android.mk b/tests/ActivityTests/Android.mk
deleted file mode 100644
index 94294f6..0000000
--- a/tests/ActivityTests/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := ActivityTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_USE_AAPT2 := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AmSlam/Android.bp b/tests/AmSlam/Android.bp
new file mode 100644
index 0000000..a8e575a
--- /dev/null
+++ b/tests/AmSlam/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "AmSlam",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ min_sdk_version: "21",
+ java_version: "1.8",
+}
diff --git a/tests/AmSlam/Android.mk b/tests/AmSlam/Android.mk
deleted file mode 100644
index 934bae0..0000000
--- a/tests/AmSlam/Android.mk
+++ /dev/null
@@ -1,30 +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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AmSlam
-
-LOCAL_SDK_VERSION := current
-LOCAL_MIN_SDK_VERSION := 21
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Assist/Android.bp b/tests/Assist/Android.bp
new file mode 100644
index 0000000..216e751
--- /dev/null
+++ b/tests/Assist/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "Assist",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+}
diff --git a/tests/Assist/Android.mk b/tests/Assist/Android.mk
deleted file mode 100644
index d0d3eca..0000000
--- a/tests/Assist/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := Assist
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BandwidthTests/Android.bp b/tests/BandwidthTests/Android.bp
new file mode 100644
index 0000000..523f522
--- /dev/null
+++ b/tests/BandwidthTests/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "BandwidthEnforcementTest",
+ platform_apis: true,
+ srcs: ["src/**/*.java"],
+}
diff --git a/tests/BandwidthTests/Android.mk b/tests/BandwidthTests/Android.mk
deleted file mode 100644
index d00fdc6..0000000
--- a/tests/BandwidthTests/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := BandwidthEnforcementTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BatteryWaster/Android.bp b/tests/BatteryWaster/Android.bp
new file mode 100644
index 0000000..4698910
--- /dev/null
+++ b/tests/BatteryWaster/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+ name: "BatteryWaster",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+}
diff --git a/tests/BatteryWaster/Android.mk b/tests/BatteryWaster/Android.mk
deleted file mode 100644
index fb244a8..0000000
--- a/tests/BatteryWaster/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := BatteryWaster
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BiDiTests/Android.bp b/tests/BiDiTests/Android.bp
new file mode 100644
index 0000000..c659e8c
--- /dev/null
+++ b/tests/BiDiTests/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "BiDiTests",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+}
diff --git a/tests/BiDiTests/Android.mk b/tests/BiDiTests/Android.mk
deleted file mode 100644
index 78cf4be..0000000
--- a/tests/BiDiTests/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := BiDiTests
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/BrowserPowerTest/Android.bp b/tests/BrowserPowerTest/Android.bp
new file mode 100644
index 0000000..1d358cb
--- /dev/null
+++ b/tests/BrowserPowerTest/Android.bp
@@ -0,0 +1,26 @@
+// Copyright 2008, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "BrowserPowerTests",
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ //LOCAL_INSTRUMENTATION_FOR := browserpowertest
+}
diff --git a/tests/BrowserPowerTest/Android.mk b/tests/BrowserPowerTest/Android.mk
deleted file mode 100644
index 0934889..0000000
--- a/tests/BrowserPowerTest/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2008, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := BrowserPowerTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-#LOCAL_INSTRUMENTATION_FOR := browserpowertest
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Camera2Tests/Android.mk b/tests/Camera2Tests/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/tests/Camera2Tests/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/tests/Camera2Tests/SmartCamera/Android.mk b/tests/Camera2Tests/SmartCamera/Android.mk
deleted file mode 100644
index 3fa8f54..0000000
--- a/tests/Camera2Tests/SmartCamera/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-include $(call all-subdir-makefiles)
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
index 0b16b0e..a23ac38 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
@@ -15,9 +15,7 @@
cc_test_library {
name: "libsmartcamera_jni",
-
sdk_version: "14",
-
srcs: [
"contrast.cpp",
"brightness.cpp",
@@ -29,13 +27,11 @@
"sobeloperator.cpp",
"stats_scorer.cpp",
],
-
cflags: [
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
],
-
stl: "c++_static",
}
diff --git a/tests/CameraPrewarmTest/Android.bp b/tests/CameraPrewarmTest/Android.bp
new file mode 100644
index 0000000..eaf453b
--- /dev/null
+++ b/tests/CameraPrewarmTest/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+ name: "CameraPrewarmTest",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+}
diff --git a/tests/CameraPrewarmTest/Android.mk b/tests/CameraPrewarmTest/Android.mk
deleted file mode 100644
index e128504..0000000
--- a/tests/CameraPrewarmTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CameraPrewarmTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CoreTests/Android.mk b/tests/CoreTests/Android.mk
deleted file mode 100644
index 8338432..0000000
--- a/tests/CoreTests/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-include $(call all-subdir-makefiles)
-
diff --git a/tests/CoreTests/android/Android.bp b/tests/CoreTests/android/Android.bp
new file mode 100644
index 0000000..24134e8
--- /dev/null
+++ b/tests/CoreTests/android/Android.bp
@@ -0,0 +1,11 @@
+android_test {
+ name: "LegacyCoreTests",
+ srcs: ["**/*.java"],
+ libs: [
+ "android.test.runner.stubs",
+ "org.apache.http.legacy",
+ "android.test.base.stubs",
+ ],
+ sdk_version: "current",
+ static_libs: ["junit"],
+}
diff --git a/tests/CoreTests/android/Android.mk b/tests/CoreTests/android/Android.mk
deleted file mode 100644
index 04f6739..0000000
--- a/tests/CoreTests/android/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- $(call all-subdir-java-files)
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner.stubs \
- org.apache.http.legacy \
- android.test.base.stubs \
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_PACKAGE_NAME := LegacyCoreTests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/DataIdleTest/Android.bp b/tests/DataIdleTest/Android.bp
new file mode 100644
index 0000000..19656ce
--- /dev/null
+++ b/tests/DataIdleTest/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "DataIdleTest",
+ platform_apis: true,
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+ srcs: ["src/**/*.java"],
+ // We need to sign it to get access to the network usage history.
+ certificate: "platform",
+}
diff --git a/tests/DataIdleTest/Android.mk b/tests/DataIdleTest/Android.mk
deleted file mode 100644
index bcf3599..0000000
--- a/tests/DataIdleTest/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := DataIdleTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# We need to sign it to get access to the network usage history.
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/DozeTest/Android.bp b/tests/DozeTest/Android.bp
new file mode 100644
index 0000000..f1be029
--- /dev/null
+++ b/tests/DozeTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "DozeTest",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+}
diff --git a/tests/DozeTest/Android.mk b/tests/DozeTest/Android.mk
deleted file mode 100644
index ec250ff..0000000
--- a/tests/DozeTest/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := DozeTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/DpiTest/Android.bp b/tests/DpiTest/Android.bp
new file mode 100644
index 0000000..7d6a78b
--- /dev/null
+++ b/tests/DpiTest/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+ name: "DensityTest",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ aaptflags: [
+ "-c",
+ "120dpi,240dpi,160dpi,nodpi",
+ ],
+}
diff --git a/tests/DpiTest/Android.mk b/tests/DpiTest/Android.mk
deleted file mode 100644
index e69d082..0000000
--- a/tests/DpiTest/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := DensityTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,nodpi
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/base/Android.bp b/tests/FeatureSplit/base/Android.bp
new file mode 100644
index 0000000..ab25464
--- /dev/null
+++ b/tests/FeatureSplit/base/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test_helper_app {
+ name: "FeatureSplitBase",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ export_package_resources: true,
+}
diff --git a/tests/FeatureSplit/base/Android.mk b/tests/FeatureSplit/base/Android.mk
deleted file mode 100644
index 8646460..0000000
--- a/tests/FeatureSplit/base/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplitBase
-LOCAL_SDK_VERSION := current
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/feature1/Android.bp b/tests/FeatureSplit/feature1/Android.bp
new file mode 100644
index 0000000..1a93e84
--- /dev/null
+++ b/tests/FeatureSplit/feature1/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "FeatureSplit1",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ libs: ["FeatureSplitBase"],
+ aaptflags: [
+ "--package-id",
+ "0x80",
+ ] + [
+ "--custom-package",
+ "com.android.test.split.feature.one",
+ ],
+}
diff --git a/tests/FeatureSplit/feature1/Android.mk b/tests/FeatureSplit/feature1/Android.mk
deleted file mode 100644
index d4d2589..0000000
--- a/tests/FeatureSplit/feature1/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplit1
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_APK_LIBRARIES := FeatureSplitBase
-LOCAL_RES_LIBRARIES := FeatureSplitBase
-
-LOCAL_AAPT_FLAGS += --package-id 0x80
-LOCAL_AAPT_FLAGS += --custom-package com.android.test.split.feature.one
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/feature2/Android.bp b/tests/FeatureSplit/feature2/Android.bp
new file mode 100644
index 0000000..a363482
--- /dev/null
+++ b/tests/FeatureSplit/feature2/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "FeatureSplit2",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ libs: ["FeatureSplitBase"],
+ aaptflags: [
+ "--package-id",
+ "0x81",
+ "--custom-package",
+ "com.android.test.split.feature.two",
+ ],
+}
diff --git a/tests/FeatureSplit/feature2/Android.mk b/tests/FeatureSplit/feature2/Android.mk
deleted file mode 100644
index 5e5e78b..0000000
--- a/tests/FeatureSplit/feature2/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplit2
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_APK_LIBRARIES := FeatureSplitBase
-LOCAL_RES_LIBRARIES := FeatureSplitBase
-
-LOCAL_AAPT_FLAGS += --package-id 0x81
-LOCAL_AAPT_FLAGS += --custom-package com.android.test.split.feature.two
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FixVibrateSetting/Android.bp b/tests/FixVibrateSetting/Android.bp
new file mode 100644
index 0000000..5608a2b
--- /dev/null
+++ b/tests/FixVibrateSetting/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "FixVibrateSetting",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+}
diff --git a/tests/FixVibrateSetting/Android.mk b/tests/FixVibrateSetting/Android.mk
deleted file mode 100644
index 86db09e..0000000
--- a/tests/FixVibrateSetting/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := FixVibrateSetting
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FrameworkPerf/Android.bp b/tests/FrameworkPerf/Android.bp
new file mode 100644
index 0000000..a259ebd
--- /dev/null
+++ b/tests/FrameworkPerf/Android.bp
@@ -0,0 +1,14 @@
+android_test {
+ name: "FrameworkPerf",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+ aaptflags: [
+ "-c",
+ "120dpi,240dpi,160dpi,161dpi,320dpi,nodpi",
+ ],
+}
diff --git a/tests/FrameworkPerf/Android.mk b/tests/FrameworkPerf/Android.mk
deleted file mode 100644
index 0664d4d..0000000
--- a/tests/FrameworkPerf/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := FrameworkPerf
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,161dpi,320dpi,nodpi
-
-include $(BUILD_PACKAGE)
diff --git a/tests/GridLayoutTest/Android.bp b/tests/GridLayoutTest/Android.bp
new file mode 100644
index 0000000..b4b5ba5
--- /dev/null
+++ b/tests/GridLayoutTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "GridLayoutTest",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/GridLayoutTest/Android.mk b/tests/GridLayoutTest/Android.mk
deleted file mode 100644
index e7e3ccd..0000000
--- a/tests/GridLayoutTest/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := GridLayoutTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/HierarchyViewerTest/Android.bp b/tests/HierarchyViewerTest/Android.bp
new file mode 100644
index 0000000..814c883
--- /dev/null
+++ b/tests/HierarchyViewerTest/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+ name: "HierarchyViewerTest",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ static_libs: ["junit"],
+}
diff --git a/tests/HierarchyViewerTest/Android.mk b/tests/HierarchyViewerTest/Android.mk
deleted file mode 100644
index cf1a512..0000000
--- a/tests/HierarchyViewerTest/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := HierarchyViewerTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-include $(BUILD_PACKAGE)
diff --git a/tests/HugeBackup/Android.bp b/tests/HugeBackup/Android.bp
new file mode 100644
index 0000000..b44c457
--- /dev/null
+++ b/tests/HugeBackup/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+ name: "HugeBackup",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+}
diff --git a/tests/HugeBackup/Android.mk b/tests/HugeBackup/Android.mk
deleted file mode 100644
index 4789bc8..0000000
--- a/tests/HugeBackup/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := HugeBackup
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java
index fece8ba..5ad7fb9 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java
@@ -16,6 +16,7 @@
package com.android.test.hwui;
+import android.animation.ObjectAnimator;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.HardwareRenderer;
@@ -23,12 +24,15 @@
import android.graphics.RecordingCanvas;
import android.graphics.RenderNode;
import android.os.Bundle;
-import android.util.Log;
+import android.os.Handler;
import android.view.SurfaceHolder;
public class CustomRenderer extends Activity {
- private RenderNode mContent = new RenderNode("CustomRenderer");
+ private RenderNode mRootNode = new RenderNode("CustomRenderer");
+ private RenderNode mChildNode = new RenderNode("RedBox");
private HardwareRenderer mRenderer = new HardwareRenderer();
+ private ObjectAnimator mAnimator;
+ private Handler mRedrawHandler = new Handler(true);
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -36,6 +40,64 @@
getWindow().takeSurface(mSurfaceCallbacks);
}
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mAnimator = ObjectAnimator.ofFloat(mChildNode, "translationY", 0, 300);
+ mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
+ mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
+ final Runnable redraw = this::draw;
+ mAnimator.addUpdateListener(animation -> {
+ mRedrawHandler.post(redraw);
+ });
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mAnimator.end();
+ mAnimator = null;
+ }
+
+ private void setupRoot(int width, int height) {
+ mRootNode.setPosition(0, 0, width, height);
+
+ RecordingCanvas canvas = mRootNode.beginRecording();
+ canvas.drawColor(Color.WHITE);
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setColor(Color.BLACK);
+ paint.setTextAlign(Paint.Align.CENTER);
+ float textSize = Math.min(width, height) * .05f;
+ paint.setTextSize(textSize);
+ canvas.drawText("Hello custom renderer!", width / 2, textSize * 2, paint);
+
+ canvas.translate(0, height / 4);
+ canvas.drawRenderNode(mChildNode);
+ canvas.translate(width / 2, 0);
+ canvas.drawRenderNode(mChildNode);
+ mRootNode.endRecording();
+
+ setupChild(width / 2, height / 2);
+ }
+
+ private void setupChild(int width, int height) {
+ mChildNode.setPosition(0, 0, width, height);
+ mChildNode.setScaleX(.5f);
+ mChildNode.setScaleY(.5f);
+
+ RecordingCanvas canvas = mChildNode.beginRecording();
+ canvas.drawColor(Color.RED);
+ mChildNode.endRecording();
+ }
+
+ private void draw() {
+ // Since we are constantly pumping frames between onStart & onStop we don't really
+ // care about any errors that may happen. They will self-correct.
+ mRenderer.createRenderRequest()
+ .setVsyncTime(System.nanoTime())
+ .syncAndDraw();
+ }
+
private SurfaceHolder.Callback2 mSurfaceCallbacks = new SurfaceHolder.Callback2() {
@Override
@@ -48,24 +110,14 @@
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- mContent.setLeftTopRightBottom(0, 0, width, height);
- RecordingCanvas canvas = mContent.beginRecording();
- canvas.drawColor(Color.WHITE);
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(Color.BLACK);
- paint.setTextAlign(Paint.Align.CENTER);
- paint.setTextSize(Math.min(width, height) * .05f);
- canvas.drawText("Hello custom renderer!", width / 2, height / 2, paint);
- mContent.endRecording();
+ setupRoot(width, height);
- mRenderer.setContentRoot(mContent);
+ mRenderer.setContentRoot(mRootNode);
mRenderer.setSurface(holder.getSurface());
- mRenderer.createRenderRequest()
- .setVsyncTime(System.nanoTime())
- .setFrameCommitCallback(Runnable::run, () -> {
- Log.d("CustomRenderer", "Frame committed!");
- })
- .syncAndDraw();
+ draw();
+ if (!mAnimator.isStarted()) {
+ mAnimator.start();
+ }
}
@Override
diff --git a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
index d92cfce..300182d 100644
--- a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
+++ b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
@@ -27,7 +27,6 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
-import com.android.internal.graphics.ColorUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -96,7 +95,6 @@
Tonal.ConfigParser config = new Tonal.ConfigParser(InstrumentationRegistry.getContext());
// 1 to avoid regression where only first item would be parsed.
assertTrue("Tonal palettes are empty", config.getTonalPalettes().size() > 1);
- assertTrue("Blacklisted colors are empty", config.getBlacklistedColors().size() > 1);
}
@Test
@@ -113,41 +111,4 @@
assertTrue("L should be <= to 1.", palette.l[1] <= 1);
}
}
-
- @Test
- public void tonal_blacklistTest() {
- // Make sure that palette generation will fail.
- final Tonal tonal = new Tonal(InstrumentationRegistry.getContext());
-
- // Creating a WallpaperColors object that contains *only* blacklisted colors.
- final float[] hsl = tonal.getBlacklistedColors().get(0).getCenter();
- final int blacklistedColor = ColorUtils.HSLToColor(hsl);
- WallpaperColors colorsFromBitmap = new WallpaperColors(Color.valueOf(blacklistedColor),
- null, null, WallpaperColors.HINT_FROM_BITMAP);
-
- // Make sure that palette generation will fail
- final GradientColors normal = new GradientColors();
- tonal.extractInto(colorsFromBitmap, normal, new GradientColors(),
- new GradientColors());
- assertTrue("Cannot generate a tonal palette from blacklisted colors.",
- normal.getMainColor() == Tonal.MAIN_COLOR_DARK);
- }
-
- @Test
- public void tonal_ignoreBlacklistTest() {
- final Tonal tonal = new Tonal(InstrumentationRegistry.getContext());
-
- // Creating a WallpaperColors object that contains *only* blacklisted colors.
- final float[] hsl = tonal.getBlacklistedColors().get(0).getCenter();
- final int blacklistedColor = ColorUtils.HSLToColor(hsl);
- WallpaperColors colors = new WallpaperColors(Color.valueOf(blacklistedColor),
- null, null);
-
- // Blacklist should be ignored when HINT_FROM_BITMAP isn't present.
- final GradientColors normal = new GradientColors();
- tonal.extractInto(colors, normal, new GradientColors(),
- new GradientColors());
- assertTrue("Blacklist should never be used on WallpaperColors generated using "
- + "default constructor.", normal.getMainColor() == blacklistedColor);
- }
}
diff --git a/tests/JobSchedulerTestApp/Android.bp b/tests/JobSchedulerTestApp/Android.bp
new file mode 100644
index 0000000..bac0220
--- /dev/null
+++ b/tests/JobSchedulerTestApp/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+ name: "JobSchedulerTestApp",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ sdk_version: "current",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/JobSchedulerTestApp/Android.mk b/tests/JobSchedulerTestApp/Android.mk
deleted file mode 100644
index 48ee1f6..0000000
--- a/tests/JobSchedulerTestApp/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := JobSchedulerTestApp
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/LargeAssetTest/Android.bp b/tests/LargeAssetTest/Android.bp
new file mode 100644
index 0000000..499e6a0
--- /dev/null
+++ b/tests/LargeAssetTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "LargeAssetTest",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+}
diff --git a/tests/LargeAssetTest/Android.mk b/tests/LargeAssetTest/Android.mk
deleted file mode 100644
index f6d98bf..0000000
--- a/tests/LargeAssetTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LargeAssetTest
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LegacyAssistant/Android.bp b/tests/LegacyAssistant/Android.bp
new file mode 100644
index 0000000..fef924d
--- /dev/null
+++ b/tests/LegacyAssistant/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+ name: "LegacyAssistant",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+}
diff --git a/tests/LegacyAssistant/Android.mk b/tests/LegacyAssistant/Android.mk
deleted file mode 100644
index a583369..0000000
--- a/tests/LegacyAssistant/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LegacyAssistant
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LocationTracker/Android.bp b/tests/LocationTracker/Android.bp
new file mode 100644
index 0000000..f0075a9
--- /dev/null
+++ b/tests/LocationTracker/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "LocationTracker",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/LocationTracker/Android.mk b/tests/LocationTracker/Android.mk
deleted file mode 100644
index 0d51b3b..0000000
--- a/tests/LocationTracker/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LocationTracker
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LotsOfApps/Android.bp b/tests/LotsOfApps/Android.bp
new file mode 100644
index 0000000..68b9f88
--- /dev/null
+++ b/tests/LotsOfApps/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+ name: "LotsOfApps",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/LotsOfApps/Android.mk b/tests/LotsOfApps/Android.mk
deleted file mode 100644
index bee3bcc..0000000
--- a/tests/LotsOfApps/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LotsOfApps
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LowStorageTest/Android.bp b/tests/LowStorageTest/Android.bp
new file mode 100644
index 0000000..e72e4a5
--- /dev/null
+++ b/tests/LowStorageTest/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "lowstoragetest",
+ certificate: "platform",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/LowStorageTest/Android.mk b/tests/LowStorageTest/Android.mk
deleted file mode 100644
index bdde6bd..0000000
--- a/tests/LowStorageTest/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := lowstoragetest
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/MemoryUsage/Android.bp b/tests/MemoryUsage/Android.bp
new file mode 100644
index 0000000..aeb5338
--- /dev/null
+++ b/tests/MemoryUsage/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+ name: "MemoryUsage",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+}
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
deleted file mode 100644
index 5040d5a..0000000
--- a/tests/MemoryUsage/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := MemoryUsage
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/NetworkSecurityConfigTest/Android.bp b/tests/NetworkSecurityConfigTest/Android.bp
new file mode 100644
index 0000000..cf8ca57
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+ name: "NetworkSecurityConfigTests",
+ certificate: "platform",
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+}
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
deleted file mode 100644
index a6c21db..0000000
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner \
- android.test.base \
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := NetworkSecurityConfigTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/OdmApps/Android.bp b/tests/OdmApps/Android.bp
new file mode 100644
index 0000000..d86f9cc
--- /dev/null
+++ b/tests/OdmApps/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2018 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.
+
+java_test_host {
+ name: "OdmAppsTest",
+ srcs: ["src/**/*.java"],
+ libs: ["tradefed"],
+ test_suites: ["device-tests"],
+}
diff --git a/tests/OdmApps/Android.mk b/tests/OdmApps/Android.mk
deleted file mode 100644
index 64fa653..0000000
--- a/tests/OdmApps/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := OdmAppsTest
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := tradefed
-LOCAL_COMPATIBILITY_SUITE := device-tests
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/OdmApps/app/Android.bp b/tests/OdmApps/app/Android.bp
new file mode 100644
index 0000000..5eb8590
--- /dev/null
+++ b/tests/OdmApps/app/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "TestOdmApp",
+ test_suites: ["device-tests"],
+ sdk_version: "current",
+}
diff --git a/tests/OdmApps/app/Android.mk b/tests/OdmApps/app/Android.mk
deleted file mode 100644
index 9eec0cc..0000000
--- a/tests/OdmApps/app/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := TestOdmApp
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_SDK_VERSION := current
-include $(BUILD_PACKAGE)
diff --git a/tests/OdmApps/priv-app/Android.bp b/tests/OdmApps/priv-app/Android.bp
new file mode 100644
index 0000000..9dd477cf
--- /dev/null
+++ b/tests/OdmApps/priv-app/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "TestOdmPrivApp",
+ test_suites: ["device-tests"],
+ sdk_version: "current",
+}
diff --git a/tests/OdmApps/priv-app/Android.mk b/tests/OdmApps/priv-app/Android.mk
deleted file mode 100644
index d423133..0000000
--- a/tests/OdmApps/priv-app/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := TestOdmPrivApp
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_SDK_VERSION := current
-include $(BUILD_PACKAGE)
diff --git a/tests/OneMedia/Android.bp b/tests/OneMedia/Android.bp
new file mode 100644
index 0000000..11e12f35
--- /dev/null
+++ b/tests/OneMedia/Android.bp
@@ -0,0 +1,13 @@
+android_app {
+ name: "OneMedia",
+ srcs: [
+ "**/*.java",
+ "src/**/I*.aidl",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+ libs: ["org.apache.http.legacy"],
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk
deleted file mode 100644
index 41f3f64..0000000
--- a/tests/OneMedia/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files) \
- $(call all-Iaidl-files-under, src)
-
-LOCAL_PACKAGE_NAME := OneMedia
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/RemoteDisplayProvider/Android.bp b/tests/RemoteDisplayProvider/Android.bp
new file mode 100644
index 0000000..6c7798f
--- /dev/null
+++ b/tests/RemoteDisplayProvider/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+ name: "RemoteDisplayProviderTest",
+ sdk_version: "system_current",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ libs: ["com.android.media.remotedisplay"],
+ certificate: "platform",
+}
diff --git a/tests/RemoteDisplayProvider/Android.mk b/tests/RemoteDisplayProvider/Android.mk
deleted file mode 100644
index 43bf024..0000000
--- a/tests/RemoteDisplayProvider/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := RemoteDisplayProviderTest
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := system_current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_JAVA_LIBRARIES := com.android.media.remotedisplay
-LOCAL_CERTIFICATE := platform
-include $(BUILD_PACKAGE)
diff --git a/tests/RenderThreadTest/Android.bp b/tests/RenderThreadTest/Android.bp
new file mode 100644
index 0000000..1659776
--- /dev/null
+++ b/tests/RenderThreadTest/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+ name: "RenderThreadTest",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ static_libs: ["android-common"],
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/RenderThreadTest/Android.mk b/tests/RenderThreadTest/Android.mk
deleted file mode 100644
index 4e5f35b..0000000
--- a/tests/RenderThreadTest/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := RenderThreadTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES += android-common
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index ed8a533..a03fae0 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -165,9 +165,7 @@
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
- if (enableRollback) {
- params.setEnableRollback();
- }
+ params.setEnableRollback(enableRollback);
int sessionId = packageInstaller.createSession(params);
session = packageInstaller.openSession(sessionId);
@@ -224,11 +222,9 @@
if (staged) {
multiPackageParams.setStaged();
}
- if (enableRollback) {
- // TODO: Do we set this on the parent params, the child params, or
- // both?
- multiPackageParams.setEnableRollback();
- }
+ // TODO: Do we set this on the parent params, the child params, or
+ // both?
+ multiPackageParams.setEnableRollback(enableRollback);
int multiPackageId = packageInstaller.createSession(multiPackageParams);
PackageInstaller.Session multiPackage = packageInstaller.openSession(multiPackageId);
@@ -242,9 +238,7 @@
if (resourceName.endsWith(".apex")) {
params.setInstallAsApex();
}
- if (enableRollback) {
- params.setEnableRollback();
- }
+ params.setEnableRollback(enableRollback);
int sessionId = packageInstaller.createSession(params);
session = packageInstaller.openSession(sessionId);
diff --git a/tests/SerialChat/Android.bp b/tests/SerialChat/Android.bp
new file mode 100644
index 0000000..3c18035
--- /dev/null
+++ b/tests/SerialChat/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "SerialChat",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+}
diff --git a/tests/SerialChat/Android.mk b/tests/SerialChat/Android.mk
deleted file mode 100644
index ed6ca999..0000000
--- a/tests/SerialChat/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := SerialChat
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SharedLibrary/client/Android.bp b/tests/SharedLibrary/client/Android.bp
new file mode 100644
index 0000000..dbf6dc9
--- /dev/null
+++ b/tests/SharedLibrary/client/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+ name: "SharedLibraryClient",
+ srcs: ["**/*.java"],
+ libs: ["SharedLibrary"],
+ sdk_version: "current",
+}
diff --git a/tests/SharedLibrary/client/Android.mk b/tests/SharedLibrary/client/Android.mk
deleted file mode 100644
index 9e76c40..0000000
--- a/tests/SharedLibrary/client/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RES_LIBRARIES := SharedLibrary
-
-LOCAL_PACKAGE_NAME := SharedLibraryClient
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SharedLibrary/lib/Android.bp b/tests/SharedLibrary/lib/Android.bp
new file mode 100644
index 0000000..f69d388
--- /dev/null
+++ b/tests/SharedLibrary/lib/Android.bp
@@ -0,0 +1,11 @@
+android_app {
+ name: "SharedLibrary",
+ srcs: ["**/*.java"],
+ aaptflags: ["--shared-lib"],
+ sdk_version: "current",
+ export_package_resources: true,
+ privileged: true,
+ optimize: {
+ proguard_flags_files: ["proguard.proguard"],
+ },
+}
diff --git a/tests/SharedLibrary/lib/Android.mk b/tests/SharedLibrary/lib/Android.mk
deleted file mode 100644
index 3c1ca87..0000000
--- a/tests/SharedLibrary/lib/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_AAPT_FLAGS := --shared-lib
-LOCAL_PACKAGE_NAME := SharedLibrary
-LOCAL_SDK_VERSION := current
-
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.proguard
-
-include $(BUILD_PACKAGE)
diff --git a/tests/ShowWhenLockedApp/Android.bp b/tests/ShowWhenLockedApp/Android.bp
new file mode 100644
index 0000000..dba564c
--- /dev/null
+++ b/tests/ShowWhenLockedApp/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "ShowWhenLocked",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/ShowWhenLockedApp/Android.mk b/tests/ShowWhenLockedApp/Android.mk
deleted file mode 100644
index 41e0ac4..0000000
--- a/tests/ShowWhenLockedApp/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := ShowWhenLocked
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/SmokeTest/Android.bp b/tests/SmokeTest/Android.bp
new file mode 100644
index 0000000..bc45ee6
--- /dev/null
+++ b/tests/SmokeTest/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+ name: "SmokeTestApp",
+ // This builds "SmokeTestApp"
+ srcs: ["src/**/*.java"],
+ sdk_version: "8",
+}
diff --git a/tests/SmokeTest/Android.mk b/tests/SmokeTest/Android.mk
deleted file mode 100644
index 591a84e..0000000
--- a/tests/SmokeTest/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# This builds "SmokeTestApp"
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SmokeTestApp
-
-LOCAL_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
-# This builds "SmokeTest"
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SmokeTest/tests/Android.bp b/tests/SmokeTest/tests/Android.bp
new file mode 100644
index 0000000..ceb2d19
--- /dev/null
+++ b/tests/SmokeTest/tests/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+ name: "SmokeTest",
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+ // Notice that we don't have to include the src files of SmokeTestApp because, by
+ // running the tests using an instrumentation targeting SmokeTestApp, we
+ // automatically get all of its classes loaded into our environment.
+ instrumentation_for: "SmokeTestApp",
+ sdk_version: "8",
+}
diff --git a/tests/SmokeTest/tests/Android.mk b/tests/SmokeTest/tests/Android.mk
deleted file mode 100644
index 18e682e..0000000
--- a/tests/SmokeTest/tests/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Notice that we don't have to include the src files of SmokeTestApp because, by
-# running the tests using an instrumentation targeting SmokeTestApp, we
-# automatically get all of its classes loaded into our environment.
-
-LOCAL_PACKAGE_NAME := SmokeTest
-
-LOCAL_INSTRUMENTATION_FOR := SmokeTestApp
-
-LOCAL_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/SmokeTestApps/Android.bp b/tests/SmokeTestApps/Android.bp
new file mode 100644
index 0000000..0feb0004
--- /dev/null
+++ b/tests/SmokeTestApps/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "SmokeTestTriggerApps",
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/SmokeTestApps/Android.mk b/tests/SmokeTestApps/Android.mk
deleted file mode 100644
index 1f564e0..0000000
--- a/tests/SmokeTestApps/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SmokeTestTriggerApps
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SoundTriggerTestApp/Android.bp b/tests/SoundTriggerTestApp/Android.bp
new file mode 100644
index 0000000..d3a1300
--- /dev/null
+++ b/tests/SoundTriggerTestApp/Android.bp
@@ -0,0 +1,7 @@
+android_app {
+ name: "SoundTriggerTestApp",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ privileged: true,
+ certificate: "platform",
+}
diff --git a/tests/SoundTriggerTestApp/Android.mk b/tests/SoundTriggerTestApp/Android.mk
deleted file mode 100644
index 73fb5e8..0000000
--- a/tests/SoundTriggerTestApp/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := SoundTriggerTestApp
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Split/Android.bp b/tests/Split/Android.bp
new file mode 100644
index 0000000..d8c89ba
--- /dev/null
+++ b/tests/Split/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "Split",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ package_splits: [
+ "mdpi-v4",
+ "hdpi-v4",
+ "xhdpi-v4",
+ "xxhdpi-v4",
+ ],
+}
diff --git a/tests/Split/Android.mk b/tests/Split/Android.mk
deleted file mode 100644
index 4d15b2d..0000000
--- a/tests/Split/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := Split
-LOCAL_SDK_VERSION := current
-
-LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/StatusBar/Android.bp b/tests/StatusBar/Android.bp
new file mode 100644
index 0000000..0b650ed
--- /dev/null
+++ b/tests/StatusBar/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+ name: "StatusBarTest",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/StatusBar/Android.mk b/tests/StatusBar/Android.mk
deleted file mode 100644
index e845335..0000000
--- a/tests/StatusBar/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := StatusBarTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SystemUIDemoModeController/Android.bp b/tests/SystemUIDemoModeController/Android.bp
new file mode 100644
index 0000000..1e4c437
--- /dev/null
+++ b/tests/SystemUIDemoModeController/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "DemoModeController",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/SystemUIDemoModeController/Android.mk b/tests/SystemUIDemoModeController/Android.mk
deleted file mode 100644
index cc6fa8d..0000000
--- a/tests/SystemUIDemoModeController/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := DemoModeController
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TouchLatency/Android.bp b/tests/TouchLatency/Android.bp
new file mode 100644
index 0000000..1174bcb0
--- /dev/null
+++ b/tests/TouchLatency/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+ name: "TouchLatency",
+ manifest: "app/src/main/AndroidManifest.xml",
+ // omit gradle 'build' dir
+ srcs: ["app/src/main/java/**/*.java"],
+ resource_dirs: ["app/src/main/res"],
+ aaptflags: ["--auto-add-overlay"],
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+}
diff --git a/tests/TouchLatency/Android.mk b/tests/TouchLatency/Android.mk
deleted file mode 100644
index 2334bd8..0000000
--- a/tests/TouchLatency/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml
-
-# omit gradle 'build' dir
-LOCAL_SRC_FILES := $(call all-java-files-under,app/src/main/java)
-
-LOCAL_RESOURCE_DIR := \
- $(LOCAL_PATH)/app/src/main/res
-
-LOCAL_AAPT_FLAGS := \
- --auto-add-overlay
-
-LOCAL_PACKAGE_NAME := TouchLatency
-LOCAL_SDK_VERSION := current
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TransformTest/Android.bp b/tests/TransformTest/Android.bp
new file mode 100644
index 0000000..fd7aaeb
--- /dev/null
+++ b/tests/TransformTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "TransformTest",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/TransformTest/Android.mk b/tests/TransformTest/Android.mk
deleted file mode 100644
index 5340cdd..0000000
--- a/tests/TransformTest/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := TransformTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TransitionTests/Android.bp b/tests/TransitionTests/Android.bp
new file mode 100644
index 0000000..57f19e3
--- /dev/null
+++ b/tests/TransitionTests/Android.bp
@@ -0,0 +1,10 @@
+android_app {
+ name: "TransitionTests",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ static_libs: ["android-common"],
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/TransitionTests/Android.mk b/tests/TransitionTests/Android.mk
deleted file mode 100644
index a696156..0000000
--- a/tests/TransitionTests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := TransitionTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES += android-common
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/TtsTests/Android.bp b/tests/TtsTests/Android.bp
new file mode 100644
index 0000000..b137523
--- /dev/null
+++ b/tests/TtsTests/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "TtsTests",
+ srcs: ["**/*.java"],
+ static_libs: ["mockito-target"],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ platform_apis: true,
+}
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
deleted file mode 100644
index 116cc0a..0000000
--- a/tests/TtsTests/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-
-LOCAL_PACKAGE_NAME := TtsTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/UsesFeature2Test/Android.bp b/tests/UsesFeature2Test/Android.bp
new file mode 100644
index 0000000..a1b77d0
--- /dev/null
+++ b/tests/UsesFeature2Test/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "UsesFeature2Test",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/UsesFeature2Test/Android.mk b/tests/UsesFeature2Test/Android.mk
deleted file mode 100644
index 4cba4ff..0000000
--- a/tests/UsesFeature2Test/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := UsesFeature2Test
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VectorDrawableTest/Android.bp b/tests/VectorDrawableTest/Android.bp
new file mode 100644
index 0000000..13f318e
--- /dev/null
+++ b/tests/VectorDrawableTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "VectorDrawableTest",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+}
diff --git a/tests/VectorDrawableTest/Android.mk b/tests/VectorDrawableTest/Android.mk
deleted file mode 100644
index 155b2bc..0000000
--- a/tests/VectorDrawableTest/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VectorDrawableTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VoiceEnrollment/Android.bp b/tests/VoiceEnrollment/Android.bp
new file mode 100644
index 0000000..e43b38c
--- /dev/null
+++ b/tests/VoiceEnrollment/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "VoiceEnrollment",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ privileged: true,
+}
diff --git a/tests/VoiceEnrollment/Android.mk b/tests/VoiceEnrollment/Android.mk
deleted file mode 100644
index 725e2bd..0000000
--- a/tests/VoiceEnrollment/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VoiceEnrollment
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VoiceInteraction/Android.bp b/tests/VoiceInteraction/Android.bp
new file mode 100644
index 0000000..7059473
--- /dev/null
+++ b/tests/VoiceInteraction/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "VoiceInteraction",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+}
diff --git a/tests/VoiceInteraction/Android.mk b/tests/VoiceInteraction/Android.mk
deleted file mode 100644
index aa48b42..0000000
--- a/tests/VoiceInteraction/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VoiceInteraction
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/WallpaperTest/Android.bp b/tests/WallpaperTest/Android.bp
new file mode 100644
index 0000000..f68b6ec
--- /dev/null
+++ b/tests/WallpaperTest/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+ name: "WallpaperTest",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ platform_apis: true,
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/WallpaperTest/Android.mk b/tests/WallpaperTest/Android.mk
deleted file mode 100644
index 4815500..0000000
--- a/tests/WallpaperTest/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := WallpaperTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/WindowManagerStressTest/Android.bp b/tests/WindowManagerStressTest/Android.bp
new file mode 100644
index 0000000..98749a7
--- /dev/null
+++ b/tests/WindowManagerStressTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "WindowManagerStressTest",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+}
diff --git a/tests/WindowManagerStressTest/Android.mk b/tests/WindowManagerStressTest/Android.mk
deleted file mode 100644
index 6f4403f..0000000
--- a/tests/WindowManagerStressTest/Android.mk
+++ /dev/null
@@ -1,27 +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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := WindowManagerStressTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/appwidgets/AppWidgetHostTest/Android.bp b/tests/appwidgets/AppWidgetHostTest/Android.bp
new file mode 100644
index 0000000..24b7613
--- /dev/null
+++ b/tests/appwidgets/AppWidgetHostTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "AppWidgetHostTest",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+}
diff --git a/tests/appwidgets/AppWidgetHostTest/Android.mk b/tests/appwidgets/AppWidgetHostTest/Android.mk
deleted file mode 100644
index c9e6c6b..0000000
--- a/tests/appwidgets/AppWidgetHostTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AppWidgetHostTest
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.bp b/tests/appwidgets/AppWidgetProviderTest/Android.bp
new file mode 100644
index 0000000..a1a5991
--- /dev/null
+++ b/tests/appwidgets/AppWidgetProviderTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "AppWidgetProvider",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ certificate: "platform",
+}
diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.mk b/tests/appwidgets/AppWidgetProviderTest/Android.mk
deleted file mode 100644
index b26c60b..0000000
--- a/tests/appwidgets/AppWidgetProviderTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AppWidgetProvider
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
new file mode 100644
index 0000000..2539c0f
--- /dev/null
+++ b/tests/net/Android.bp
@@ -0,0 +1,27 @@
+//########################################################################
+// Build FrameworksNetTests package
+//########################################################################
+
+android_test {
+ name: "FrameworksNetTests",
+ // Include all test java files.
+ srcs: ["java/**/*.java"],
+ static_libs: [
+ "frameworks-base-testutils",
+ "framework-protos",
+ "androidx.test.rules",
+ "mockito-target-minus-junit4",
+ "platform-test-annotations",
+ "services.core",
+ "services.ipmemorystore",
+ "services.net",
+ ],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ "android.test.mock",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ certificate: "platform",
+}
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
deleted file mode 100644
index 2ef141f..0000000
--- a/tests/net/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#########################################################################
-# Build FrameworksNetTests package
-#########################################################################
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, java)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- frameworks-base-testutils \
- framework-protos \
- androidx.test.rules \
- mockito-target-minus-junit4 \
- platform-test-annotations \
- services.core \
- services.ipmemorystore \
- services.net
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner \
- android.test.base \
- android.test.mock
-
-LOCAL_PACKAGE_NAME := FrameworksNetTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-include $(BUILD_PACKAGE)
diff --git a/tests/net/OWNERS b/tests/net/OWNERS
index 7311eee..d3836d4 100644
--- a/tests/net/OWNERS
+++ b/tests/net/OWNERS
@@ -1,8 +1,8 @@
set noparent
codewiz@google.com
-ek@google.com
jchalard@google.com
+junyulai@google.com
lorenzo@google.com
reminv@google.com
satk@google.com
diff --git a/tests/net/java/android/net/DnsPacketTest.java b/tests/net/java/android/net/DnsPacketTest.java
index 91ff6b3..9ede2b8 100644
--- a/tests/net/java/android/net/DnsPacketTest.java
+++ b/tests/net/java/android/net/DnsPacketTest.java
@@ -36,19 +36,19 @@
int qCount, int aCount, int nsCount, int arCount) {
assertEquals(header.id, id);
assertEquals(header.flags, flag);
- assertEquals(header.getSectionCount(DnsPacket.QDSECTION), qCount);
- assertEquals(header.getSectionCount(DnsPacket.ANSECTION), aCount);
- assertEquals(header.getSectionCount(DnsPacket.NSSECTION), nsCount);
- assertEquals(header.getSectionCount(DnsPacket.ARSECTION), arCount);
+ assertEquals(header.getRecordCount(DnsPacket.QDSECTION), qCount);
+ assertEquals(header.getRecordCount(DnsPacket.ANSECTION), aCount);
+ assertEquals(header.getRecordCount(DnsPacket.NSSECTION), nsCount);
+ assertEquals(header.getRecordCount(DnsPacket.ARSECTION), arCount);
}
- private void assertSectionParses(DnsPacket.DnsSection section, String dname,
+ private void assertRecordParses(DnsPacket.DnsRecord record, String dname,
int dtype, int dclass, int ttl, byte[] rr) {
- assertEquals(section.dName, dname);
- assertEquals(section.nsType, dtype);
- assertEquals(section.nsClass, dclass);
- assertEquals(section.ttl, ttl);
- assertTrue(Arrays.equals(section.getRR(), rr));
+ assertEquals(record.dName, dname);
+ assertEquals(record.nsType, dtype);
+ assertEquals(record.nsClass, dclass);
+ assertEquals(record.ttl, ttl);
+ assertTrue(Arrays.equals(record.getRR(), rr));
}
class TestDnsPacket extends DnsPacket {
@@ -59,8 +59,8 @@
public DnsHeader getHeader() {
return mHeader;
}
- public List<DnsSection> getSectionList(int secType) {
- return mSections[secType];
+ public List<DnsRecord> getRecordList(int secType) {
+ return mRecords[secType];
}
}
@@ -101,16 +101,16 @@
// Header part
assertHeaderParses(packet.getHeader(), 0x5566, 0x8180, 1, 1, 0, 0);
- // Section part
- List<DnsPacket.DnsSection> qdSectionList =
- packet.getSectionList(DnsPacket.QDSECTION);
- assertEquals(qdSectionList.size(), 1);
- assertSectionParses(qdSectionList.get(0), "www.google.com", 1, 1, 0, null);
+ // Record part
+ List<DnsPacket.DnsRecord> qdRecordList =
+ packet.getRecordList(DnsPacket.QDSECTION);
+ assertEquals(qdRecordList.size(), 1);
+ assertRecordParses(qdRecordList.get(0), "www.google.com", 1, 1, 0, null);
- List<DnsPacket.DnsSection> anSectionList =
- packet.getSectionList(DnsPacket.ANSECTION);
- assertEquals(anSectionList.size(), 1);
- assertSectionParses(anSectionList.get(0), "www.google.com", 1, 1, 0x12b,
+ List<DnsPacket.DnsRecord> anRecordList =
+ packet.getRecordList(DnsPacket.ANSECTION);
+ assertEquals(anRecordList.size(), 1);
+ assertRecordParses(anRecordList.get(0), "www.google.com", 1, 1, 0x12b,
new byte[]{ (byte) 0xac, (byte) 0xd9, (byte) 0xa1, (byte) 0x84 });
}
@@ -143,16 +143,16 @@
// Header part
assertHeaderParses(packet.getHeader(), 0x7722, 0x8180, 1, 1, 0, 0);
- // Section part
- List<DnsPacket.DnsSection> qdSectionList =
- packet.getSectionList(DnsPacket.QDSECTION);
- assertEquals(qdSectionList.size(), 1);
- assertSectionParses(qdSectionList.get(0), "www.google.com", 28, 1, 0, null);
+ // Record part
+ List<DnsPacket.DnsRecord> qdRecordList =
+ packet.getRecordList(DnsPacket.QDSECTION);
+ assertEquals(qdRecordList.size(), 1);
+ assertRecordParses(qdRecordList.get(0), "www.google.com", 28, 1, 0, null);
- List<DnsPacket.DnsSection> anSectionList =
- packet.getSectionList(DnsPacket.ANSECTION);
- assertEquals(anSectionList.size(), 1);
- assertSectionParses(anSectionList.get(0), "www.google.com", 28, 1, 0x37,
+ List<DnsPacket.DnsRecord> anRecordList =
+ packet.getRecordList(DnsPacket.ANSECTION);
+ assertEquals(anRecordList.size(), 1);
+ assertRecordParses(anRecordList.get(0), "www.google.com", 28, 1, 0x37,
new byte[]{ 0x24, 0x04, 0x68, 0x00, 0x40, 0x05, 0x08, 0x0d,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04 });
}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index a12b0a0..fdba723 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -68,6 +68,7 @@
import android.net.INetd;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -123,6 +124,7 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Vector;
@RunWith(AndroidJUnit4.class)
@@ -918,6 +920,67 @@
expectedInteractionsWithShowNotification);
}
+ private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
+ private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
+
+ public void expectUpstreamChanged(Network... networks) {
+ final ArrayList<Network> expectedUpstreams =
+ new ArrayList<Network>(Arrays.asList(networks));
+ for (Network upstream : expectedUpstreams) {
+ // throws OOB if no expectations
+ assertEquals(mActualUpstreams.remove(0), upstream);
+ }
+ assertNoCallback();
+ }
+
+ @Override
+ public void onUpstreamChanged(Network network) {
+ mActualUpstreams.add(network);
+ }
+
+ public void assertNoCallback() {
+ assertTrue(mActualUpstreams.isEmpty());
+ }
+ }
+
+ @Test
+ public void testRegisterTetheringEventCallback() throws Exception {
+ TestTetheringEventCallback callback1 = new TestTetheringEventCallback();
+ TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
+
+ // 1. Register one callback and run usb tethering.
+ mTethering.registerTetheringEventCallback(callback1);
+ mLooper.dispatchAll();
+ callback1.expectUpstreamChanged(new Network[] {null});
+ NetworkState upstreamState = buildMobileDualStackUpstreamState();
+ runUsbTethering(upstreamState);
+ callback1.expectUpstreamChanged(upstreamState.network);
+ // 2. Register second callback.
+ mTethering.registerTetheringEventCallback(callback2);
+ mLooper.dispatchAll();
+ callback2.expectUpstreamChanged(upstreamState.network);
+ // 3. Disable usb tethering.
+ mTethering.stopTethering(TETHERING_USB);
+ mLooper.dispatchAll();
+ sendUsbBroadcast(false, false, false);
+ mLooper.dispatchAll();
+ callback1.expectUpstreamChanged(new Network[] {null});
+ callback2.expectUpstreamChanged(new Network[] {null});
+ // 4. Unregister first callback and run hotspot.
+ mTethering.unregisterTetheringEventCallback(callback1);
+ mLooper.dispatchAll();
+ when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
+ when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
+ .thenReturn(upstreamState);
+ when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+ mTethering.startTethering(TETHERING_WIFI, null, false);
+ mLooper.dispatchAll();
+ mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
+ sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
+ mLooper.dispatchAll();
+ callback1.assertNoCallback();
+ callback2.expectUpstreamChanged(upstreamState.network);
+ }
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
diff --git a/tests/notification/Android.bp b/tests/notification/Android.bp
new file mode 100644
index 0000000..f05edaf
--- /dev/null
+++ b/tests/notification/Android.bp
@@ -0,0 +1,7 @@
+android_test {
+ name: "NotificationTests",
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+ libs: ["android.test.runner.stubs"],
+ sdk_version: "21",
+}
diff --git a/tests/notification/Android.mk b/tests/notification/Android.mk
deleted file mode 100644
index 255e6e7..0000000
--- a/tests/notification/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
-LOCAL_PACKAGE_NAME := NotificationTests
-
-LOCAL_SDK_VERSION := 21
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/permission/Android.bp b/tests/permission/Android.bp
new file mode 100644
index 0000000..bd07009
--- /dev/null
+++ b/tests/permission/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+ name: "FrameworkPermissionTests",
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+ libs: [
+ "android.test.runner",
+ "telephony-common",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+ platform_apis: true,
+}
diff --git a/tests/permission/Android.mk b/tests/permission/Android.mk
deleted file mode 100644
index dd2f3ec..0000000
--- a/tests/permission/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-LOCAL_PACKAGE_NAME := FrameworkPermissionTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/testables/Android.bp b/tests/testables/Android.bp
index 0bad7a4..eb6811c 100644
--- a/tests/testables/Android.bp
+++ b/tests/testables/Android.bp
@@ -15,18 +15,12 @@
//
java_library {
-
name: "testables",
- // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_MODULE_TAG
- // LOCAL_MODULE_TAG := tests
-
srcs: ["src/**/*.java"],
-
libs: [
"android.test.runner",
"android.test.mock",
"androidx.test.rules",
"mockito-target-inline-minus-junit4",
],
-
}
diff --git a/tests/testables/tests/Android.bp b/tests/testables/tests/Android.bp
new file mode 100644
index 0000000..e1a58be
--- /dev/null
+++ b/tests/testables/tests/Android.bp
@@ -0,0 +1,41 @@
+// 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.
+
+android_test {
+ name: "TestablesTests",
+ platform_apis: true,
+ srcs: [
+ "src/**/*.java",
+ "src/**/I*.aidl",
+ ],
+ resource_dirs: ["res"],
+ static_libs: [
+ "androidx.test.rules",
+ "hamcrest-library",
+ "mockito-target-inline-minus-junit4",
+ "testables",
+ ],
+ compile_multilib: "both",
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libmultiplejvmtiagentsinterferenceagent",
+ ],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ "android.test.mock",
+ ],
+ certificate: "platform",
+ test_suites: ["device-tests"],
+}
diff --git a/tests/testables/tests/Android.mk b/tests/testables/tests/Android.mk
deleted file mode 100644
index 16fbb18..0000000
--- a/tests/testables/tests/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := TestablesTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
- $(call all-Iaidl-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules hamcrest-library \
- mockito-target-inline-minus-junit4 \
- testables
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
- libdexmakerjvmtiagent \
- libmultiplejvmtiagentsinterferenceagent
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/touchlag/Android.bp b/tests/touchlag/Android.bp
index 2610cb3..092eea9 100644
--- a/tests/touchlag/Android.bp
+++ b/tests/touchlag/Android.bp
@@ -1,14 +1,11 @@
cc_test {
name: "test-touchlag",
gtest: false,
-
srcs: ["touchlag.cpp"],
-
shared_libs: [
"libcutils",
"libutils",
],
-
cflags: [
"-Wall",
"-Wextra",
diff --git a/tests/utils/Android.mk b/tests/utils/Android.mk
deleted file mode 100644
index c141484..0000000
--- a/tests/utils/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2012 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include $(call all-subdir-makefiles)
diff --git a/tests/utils/DummyIME/Android.bp b/tests/utils/DummyIME/Android.bp
new file mode 100644
index 0000000..4a44b3b
--- /dev/null
+++ b/tests/utils/DummyIME/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "DummyIME",
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+}
diff --git a/tests/utils/DummyIME/Android.mk b/tests/utils/DummyIME/Android.mk
deleted file mode 100644
index 0f6c988..0000000
--- a/tests/utils/DummyIME/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2012 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := DummyIME
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 251ca0c..5336141 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -183,11 +183,11 @@
EXPECT_THAT(str->untranslatable_sections, IsEmpty());
// Preserve non-ASCII whitespace including extended ASCII characters
- EXPECT_TRUE(TestParse(R"(<string name="foo3"> Hello </string>)"));
+ EXPECT_TRUE(TestParse(R"(<string name="foo3"> Hello World </string>)"));
str = test::GetValue<String>(&table_, "string/foo3");
ASSERT_THAT(str, NotNull());
- EXPECT_THAT(*str->value, StrEq("\xC2\xA0Hello\xC2\xA0"));
+ EXPECT_THAT(*str->value, StrEq("\xC2\xA0Hello\xE2\x80\xAFWorld\xC2\xA0"));
EXPECT_THAT(str->untranslatable_sections, IsEmpty());
EXPECT_TRUE(TestParse(R"(<string name="foo4">2005年6月1日</string>)"));
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index f0e4d9e..a571aee 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -40,8 +40,6 @@
namespace aapt {
namespace ResourceUtils {
-constexpr int32_t kNonBreakingSpace = 0xa0;
-
Maybe<ResourceName> ToResourceName(
const android::ResTable::resource_name& name_in) {
// TODO: Remove this when ResTable and AssetManager(1) are removed from AAPT2
@@ -854,7 +852,8 @@
Utf8Iterator iter(text);
while (iter.HasNext()) {
char32_t codepoint = iter.Next();
- if (!preserve_spaces_ && !quote_ && codepoint != kNonBreakingSpace && iswspace(codepoint)) {
+ if (!preserve_spaces_ && !quote_ && (codepoint <= std::numeric_limits<char>::max())
+ && isspace(static_cast<char>(codepoint))) {
if (!last_codepoint_was_space_) {
// Emit a space if it's the first.
xml_string_.text += ' ';
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index 2a8f695..6781eba 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -29,6 +29,9 @@
FLAG_GREYLIST_MAX_O = "greylist-max-o"
FLAG_GREYLIST_MAX_P = "greylist-max-p"
FLAG_CORE_PLATFORM_API = "core-platform-api"
+FLAG_PUBLIC_API = "public-api"
+FLAG_SYSTEM_API = "system-api"
+FLAG_TEST_API = "test-api"
# List of all known flags.
FLAGS_API_LIST = [
@@ -38,7 +41,12 @@
FLAG_GREYLIST_MAX_O,
FLAG_GREYLIST_MAX_P,
]
-ALL_FLAGS = FLAGS_API_LIST + [ FLAG_CORE_PLATFORM_API ]
+ALL_FLAGS = FLAGS_API_LIST + [
+ FLAG_CORE_PLATFORM_API,
+ FLAG_PUBLIC_API,
+ FLAG_SYSTEM_API,
+ FLAG_TEST_API,
+ ]
FLAGS_API_LIST_SET = set(FLAGS_API_LIST)
ALL_FLAGS_SET = set(ALL_FLAGS)
@@ -203,14 +211,19 @@
# Iterate over all CSV lines, find entry in dict and append flags to it.
for csv in csv_values:
- self._dict[csv[0]].update(csv[1:])
+ flags = csv[1:]
+ if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags):
+ flags.append(FLAG_WHITELIST)
+ elif FLAG_TEST_API in flags:
+ flags.append(FLAG_GREYLIST)
+ self._dict[csv[0]].update(flags)
def assign_flag(self, flag, apis, source="<unknown>"):
"""Assigns a flag to given subset of entries.
Args:
flag (string): One of ALL_FLAGS.
- apis (set): Subset of APIs to recieve the flag.
+ apis (set): Subset of APIs to receive the flag.
source (string): Origin of `entries_subset`. Will be printed in error messages.
Throws:
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
index 44d88bb..6f6c1aa 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
@@ -97,7 +97,7 @@
/**
* The suffix of the generated class name after the class's binary name.
*/
- private static final String GENERATED_CLASS_SUFFIX = "$$InspectionCompanion";
+ private static final String GENERATED_CLASS_SUFFIX = "$InspectionCompanion";
/**
* The null resource ID, copied to avoid a host dependency on platform code.
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
index 01d9430..fd142c6 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java
@@ -34,6 +34,7 @@
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
/**
@@ -127,13 +128,38 @@
final InspectableClassModel model = modelMap.computeIfAbsent(
classElement.get().getQualifiedName().toString(),
- k -> new InspectableClassModel(ClassName.get(classElement.get())));
+ k -> {
+ if (hasNestedInspectionCompanion(classElement.get())) {
+ fail(
+ String.format(
+ "Class %s already has an inspection companion.",
+ classElement.get().getQualifiedName().toString()),
+ element);
+ }
+ return new InspectableClassModel(ClassName.get(classElement.get()));
+ });
processor.process(element, model);
}
}
/**
+ * Determine if a class has a nested class named {@code InspectionCompanion}.
+ *
+ * @param typeElement A type element representing the class to check
+ * @return f the class contains a class named {@code InspectionCompanion}
+ */
+ private static boolean hasNestedInspectionCompanion(TypeElement typeElement) {
+ for (TypeElement nestedClass : ElementFilter.typesIn(typeElement.getEnclosedElements())) {
+ if (nestedClass.getSimpleName().toString().equals("InspectionCompanion")) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Get the nearest enclosing class if there is one.
*
* If {@param element} represents a class, it will be returned wrapped in an optional.
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt
index a44c43e..9a0fe5b 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt
@@ -12,7 +12,7 @@
* Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
* on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
*/
-public final class TestNode$$InspectionCompanion implements InspectionCompanion<TestNode> {
+public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
/**
* Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
*/
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt
index 764aa8b..b491de1 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt
@@ -13,7 +13,7 @@
* Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
* on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
*/
-public final class TestNode$$InspectionCompanion implements InspectionCompanion<TestNode> {
+public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
/**
* Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
*/
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt
index 75f2813..7d18058 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt
@@ -12,7 +12,7 @@
* Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
* on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
*/
-public final class TestNode$$InspectionCompanion implements InspectionCompanion<TestNode> {
+public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
/**
* Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
*/
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt
index 0cac462..dc27abb 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt
@@ -11,7 +11,7 @@
* Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
* on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
*/
-public final class Outer$Inner$$InspectionCompanion implements InspectionCompanion<Outer.Inner> {
+public final class Outer$Inner$InspectionCompanion implements InspectionCompanion<Outer.Inner> {
/**
* Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
*/
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt
index ce0f867..738bcd3 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt
@@ -11,7 +11,7 @@
* Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
* on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
*/
-public final class TestNode$$InspectionCompanion implements InspectionCompanion<TestNode> {
+public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
/**
* Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
*/
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt
index f7357fe..82dd66e 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt
@@ -12,7 +12,7 @@
* Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
* on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
*/
-public final class TestNode$$InspectionCompanion implements InspectionCompanion<TestNode> {
+public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
/**
* Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
*/
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
index 556d8dd..08ea696 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
@@ -12,7 +12,7 @@
* Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
* on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
*/
-public final class TestNode$$InspectionCompanion implements InspectionCompanion<TestNode> {
+public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
/**
* Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
*/
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt
index d72cdd5..3bfa78a 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt
@@ -11,7 +11,7 @@
* Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
* on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
*/
-public final class TestNode$$InspectionCompanion implements InspectionCompanion<TestNode> {
+public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> {
/**
* Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
*/
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index ee60408..0b55794 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -539,9 +539,10 @@
mFqdn = fqdn;
}
- /** {@hide} */
- @SystemApi
- public @Nullable String getFqdn() {
+ /**
+ * Returns the Fully Qualified Domain Name of the network if it is a Passpoint network.
+ */
+ public @Nullable String getPasspointFqdn() {
return mFqdn;
}
@@ -550,9 +551,10 @@
mProviderFriendlyName = providerFriendlyName;
}
- /** {@hide} */
- @SystemApi
- public @Nullable String getProviderFriendlyName() {
+ /**
+ * Returns the Provider Friendly Name of the network if it is a Passpoint network.
+ */
+ public @Nullable String getPasspointProviderFriendlyName() {
return mProviderFriendlyName;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6dd838c..4fd00f7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -3604,7 +3604,7 @@
android.Manifest.permission.NETWORK_SETUP_WIZARD,
android.Manifest.permission.NETWORK_STACK
})
- public void connect(WifiConfiguration config, ActionListener listener) {
+ public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
// Use INVALID_NETWORK_ID for arg1 when passing a config object
// arg1 is used to pass network id when the network already exists
@@ -3630,7 +3630,7 @@
android.Manifest.permission.NETWORK_SETUP_WIZARD,
android.Manifest.permission.NETWORK_STACK
})
- public void connect(int networkId, ActionListener listener) {
+ public void connect(int networkId, @Nullable ActionListener listener) {
if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
}
@@ -3661,7 +3661,7 @@
android.Manifest.permission.NETWORK_SETUP_WIZARD,
android.Manifest.permission.NETWORK_STACK
})
- public void save(WifiConfiguration config, ActionListener listener) {
+ public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
}
@@ -3685,7 +3685,7 @@
android.Manifest.permission.NETWORK_SETUP_WIZARD,
android.Manifest.permission.NETWORK_STACK
})
- public void forget(int netId, ActionListener listener) {
+ public void forget(int netId, @Nullable ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener));
}
@@ -3705,7 +3705,7 @@
android.Manifest.permission.NETWORK_SETUP_WIZARD,
android.Manifest.permission.NETWORK_STACK
})
- public void disable(int netId, ActionListener listener) {
+ public void disable(int netId, @Nullable ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener));
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 358bf31..8b56b3f 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -408,7 +408,7 @@
* @return Instance of {@link NetworkSpecifier}.
* @throws IllegalStateException on invalid params set.
*/
- public @NonNull NetworkSpecifier build() {
+ public @NonNull WifiNetworkSpecifier build() {
if (!hasSetAnyPattern()) {
throw new IllegalStateException("one of setSsidPattern/setSsid/setBssidPattern/"
+ "setBssid should be invoked for specifier");
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index a47e70b..d97f6fb 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -36,7 +36,7 @@
* <ul>
* <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} method.
* <li>Creating a network-specifier when requesting a Aware connection using
- * {@link WifiAwareManager.NetworkSpecifierBuilder}.
+ * {@link WifiAwareNetworkSpecifier.Builder}.
* </ul>
* <p>
* The {@link #close()} method must be called to destroy discovery sessions once they are
@@ -270,7 +270,7 @@
* <p>
* To set up an encrypted link use the
* {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} API.
- * @deprecated Use the replacement {@link WifiAwareManager.NetworkSpecifierBuilder}.
+ * @deprecated Use the replacement {@link WifiAwareNetworkSpecifier.Builder}.
*
* @param peerHandle The peer's handle obtained through
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
@@ -320,7 +320,7 @@
* <p>
* Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
* and a Publisher is a RESPONDER.
- * @deprecated Use the replacement {@link WifiAwareManager.NetworkSpecifierBuilder}.
+ * @deprecated Use the replacement {@link WifiAwareNetworkSpecifier.Builder}.
*
* @param peerHandle The peer's handle obtained through
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
@@ -380,7 +380,7 @@
* <p>
* Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
* and a Publisher is a RESPONDER.
- * @deprecated Use the replacement {@link WifiAwareManager.NetworkSpecifierBuilder}.
+ * @deprecated Use the replacement {@link WifiAwareNetworkSpecifier.Builder}.
*
* @param peerHandle The peer's handle obtained through
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
diff --git a/wifi/java/android/net/wifi/aware/ParcelablePeerHandle.java b/wifi/java/android/net/wifi/aware/ParcelablePeerHandle.java
index ce67abf..ca473db 100644
--- a/wifi/java/android/net/wifi/aware/ParcelablePeerHandle.java
+++ b/wifi/java/android/net/wifi/aware/ParcelablePeerHandle.java
@@ -16,6 +16,7 @@
package android.net.wifi.aware;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,7 +30,7 @@
*
* @param peerHandle The {@link PeerHandle} to be made parcelable.
*/
- public ParcelablePeerHandle(PeerHandle peerHandle) {
+ public ParcelablePeerHandle(@NonNull PeerHandle peerHandle) {
super(peerHandle.peerId);
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 1a5cd5a..c9b0b12 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -21,7 +21,6 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -35,7 +34,6 @@
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
-import android.text.TextUtils;
import android.util.Log;
import libcore.util.HexEncoding;
@@ -59,7 +57,7 @@
* {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}.
* <li>Create a Aware network specifier to be used with
* {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
- * to set-up a Aware connection with a peer. Refer to {@link NetworkSpecifierBuilder}.
+ * to set-up a Aware connection with a peer. Refer to {@link WifiAwareNetworkSpecifier.Builder}.
* </ul>
* <p>
* Aware may not be usable when Wi-Fi is disabled (and other conditions). To validate that
@@ -108,7 +106,7 @@
* <li>{@link NetworkRequest.Builder#addTransportType(int)} of
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
- * {@link NetworkSpecifierBuilder}.
+ * {@link WifiAwareNetworkSpecifier.Builder}.
* </ul>
*/
@SystemService(Context.WIFI_AWARE_SERVICE)
@@ -408,7 +406,7 @@
if (!WifiAwareUtils.isLegacyVersion(mContext, Build.VERSION_CODES.Q)) {
throw new UnsupportedOperationException(
- "API not deprecated - use WifiAwareManager.NetworkSpecifierBuilder");
+ "API not deprecated - use WifiAwareNetworkSpecifier.Builder");
}
if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
@@ -813,198 +811,4 @@
mOriginalCallback.onSessionTerminated();
}
}
-
- /**
- * A builder class for a Wi-Fi Aware network specifier to set up an Aware connection with a
- * peer.
- * <p>
- * Note that all Wi-Fi Aware connection specifier objects must call the
- * {@link NetworkSpecifierBuilder#setDiscoverySession(DiscoverySession)} to specify the context
- * within which the connection is created, and
- * {@link NetworkSpecifierBuilder#setPeerHandle(PeerHandle)} to specify the peer to which the
- * connection is created.
- */
- public static final class NetworkSpecifierBuilder {
- private DiscoverySession mDiscoverySession;
- private PeerHandle mPeerHandle;
- private String mPskPassphrase;
- private byte[] mPmk;
- private int mPort = 0; // invalid value
- private int mTransportProtocol = -1; // invalid value
-
- /**
- * Configure the {@link PublishDiscoverySession} or {@link SubscribeDiscoverySession}
- * discovery session in whose context the connection is created.
- * <p>
- * Note: this method must be called for any connection request!
- *
- * @param discoverySession A Wi-Fi Aware discovery session.
- * @return the current {@link NetworkSpecifierBuilder} builder, enabling chaining of builder
- * methods.
- */
- public @NonNull NetworkSpecifierBuilder setDiscoverySession(
- @NonNull DiscoverySession discoverySession) {
- if (discoverySession == null) {
- throw new IllegalArgumentException("Non-null discoverySession required");
- }
- mDiscoverySession = discoverySession;
- return this;
- }
-
- /**
- * Configure the {@link PeerHandle} of the peer to which the Wi-Fi Aware connection is
- * requested. The peer is discovered through Wi-Fi Aware discovery,
- * <p>
- * Note: this method must be called for any connection request!
- *
- * @param peerHandle The peer's handle obtained through
- * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
- * or
- * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
- * @return the current {@link NetworkSpecifierBuilder} builder, enabling chaining of builder
- * methods.
- */
- public @NonNull NetworkSpecifierBuilder setPeerHandle(@NonNull PeerHandle peerHandle) {
- if (peerHandle == null) {
- throw new IllegalArgumentException("Non-null peerHandle required");
- }
- mPeerHandle = peerHandle;
- return this;
- }
-
- /**
- * Configure the PSK Passphrase for the Wi-Fi Aware connection being requested. This method
- * is optional - if not called, then an Open (unencrypted) connection will be created.
- *
- * @param pskPassphrase The (optional) passphrase to be used to encrypt the link.
- * @return the current {@link NetworkSpecifierBuilder} builder, enabling chaining of builder
- * methods.
- */
- public @NonNull NetworkSpecifierBuilder setPskPassphrase(@NonNull String pskPassphrase) {
- if (!WifiAwareUtils.validatePassphrase(pskPassphrase)) {
- throw new IllegalArgumentException("Passphrase must meet length requirements");
- }
- mPskPassphrase = pskPassphrase;
- return this;
- }
-
- /**
- * Configure the PMK for the Wi-Fi Aware connection being requested. This method
- * is optional - if not called, then an Open (unencrypted) connection will be created.
- *
- * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
- * encrypting the data-path. Use the {@link #setPskPassphrase(String)} to
- * specify a Passphrase.
- * @return the current {@link NetworkSpecifierBuilder} builder, enabling chaining of builder
- * methods.
- * @hide
- */
- @SystemApi
- public @NonNull NetworkSpecifierBuilder setPmk(@NonNull byte[] pmk) {
- if (!WifiAwareUtils.validatePmk(pmk)) {
- throw new IllegalArgumentException("PMK must 32 bytes");
- }
- mPmk = pmk;
- return this;
- }
-
- /**
- * Configure the port number which will be used to create a connection over this link. This
- * configuration should only be done on the server device, e.g. the device creating the
- * {@link java.net.ServerSocket}.
- * <p>Notes:
- * <ul>
- * <li>The server device must be the Publisher device!
- * <li>The port information can only be specified on secure links, specified using
- * {@link #setPskPassphrase(String)}.
- * </ul>
- *
- * @param port A positive integer indicating the port to be used for communication.
- * @return the current {@link NetworkSpecifierBuilder} builder, enabling chaining of builder
- * methods.
- */
- public @NonNull NetworkSpecifierBuilder setPort(int port) {
- if (port <= 0 || port > 65535) {
- throw new IllegalArgumentException("The port must be a positive value (0, 65535]");
- }
- mPort = port;
- return this;
- }
-
- /**
- * Configure the transport protocol which will be used to create a connection over this
- * link. This configuration should only be done on the server device, e.g. the device
- * creating the {@link java.net.ServerSocket} for TCP.
- * <p>Notes:
- * <ul>
- * <li>The server device must be the Publisher device!
- * <li>The transport protocol information can only be specified on secure links,
- * specified using {@link #setPskPassphrase(String)}.
- * </ul>
- * The transport protocol number is assigned by the Internet Assigned Numbers Authority
- * (IANA) https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml.
- *
- * @param transportProtocol The transport protocol to be used for communication.
- * @return the current {@link NetworkSpecifierBuilder} builder, enabling chaining of builder
- * methods.
- */
- public @NonNull NetworkSpecifierBuilder setTransportProtocol(int transportProtocol) {
- if (transportProtocol < 0 || transportProtocol > 255) {
- throw new IllegalArgumentException(
- "The transport protocol must be in range [0, 255]");
- }
- mTransportProtocol = transportProtocol;
- return this;
- }
-
- /**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)}
- * for a WiFi Aware connection (link) to the specified peer. The
- * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
- * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
- * <p> The default builder constructor will initialize a NetworkSpecifier which requests an
- * open (non-encrypted) link. To request an encrypted link use the
- * {@link #setPskPassphrase(String)} builder method.
- *
- * @return A {@link NetworkSpecifier} to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass
- * to {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
- * android.net.ConnectivityManager.NetworkCallback)}
- * [or other varieties of that API].
- */
- public @NonNull NetworkSpecifier build() {
- if (mDiscoverySession == null) {
- throw new IllegalStateException("Null discovery session!?");
- }
- if (mPskPassphrase != null & mPmk != null) {
- throw new IllegalStateException(
- "Can only specify a Passphrase or a PMK - not both!");
- }
-
- int role = mDiscoverySession instanceof SubscribeDiscoverySession
- ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
- : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
-
- if (mPort != 0 || mTransportProtocol != -1) {
- if (role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
- throw new IllegalStateException(
- "Port and transport protocol information can only "
- + "be specified on the Publisher device (which is the server");
- }
- if (TextUtils.isEmpty(mPskPassphrase) && mPmk == null) {
- throw new IllegalStateException("Port and transport protocol information can "
- + "only be specified on a secure link");
- }
- }
-
- if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR && mPeerHandle == null) {
- throw new IllegalStateException("Null peerHandle!?");
- }
-
- return new WifiAwareNetworkSpecifier(
- WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB, role,
- mDiscoverySession.mClientId, mDiscoverySession.mSessionId, mPeerHandle.peerId,
- null, mPmk, mPskPassphrase, mPort, mTransportProtocol, Process.myUid());
- }
- }
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkInfo.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkInfo.java
index 020cb56..fd26817b 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkInfo.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkInfo.java
@@ -75,7 +75,7 @@
/**
* Get the port number to be used to create a network connection to the Wi-Fi Aware peer.
* The port information is provided by the app running on the peer which requested the
- * connection, using the {@link WifiAwareManager.NetworkSpecifierBuilder#setPort(int)}.
+ * connection, using the {@link WifiAwareNetworkSpecifier.Builder#setPort(int)}.
*
* @return A port number on the peer. A value of 0 indicates that no port was specified by the
* peer.
@@ -88,7 +88,7 @@
* Get the transport protocol to be used to communicate over a network connection to the Wi-Fi
* Aware peer. The transport protocol is provided by the app running on the peer which requested
* the connection, using the
- * {@link WifiAwareManager.NetworkSpecifierBuilder#setTransportProtocol(int)}.
+ * {@link WifiAwareNetworkSpecifier.Builder#setTransportProtocol(int)}.
* <p>
* The transport protocol number is assigned by the Internet Assigned Numbers Authority
* (IANA) https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml.
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
index 59f534a..b225116 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -16,9 +16,15 @@
package android.net.wifi.aware;
+import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.net.NetworkSpecifier;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
+import android.text.TextUtils;
import java.util.Arrays;
import java.util.Objects;
@@ -29,8 +35,6 @@
* {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} or
* {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)} or their secure (Passphrase)
* versions.
- *
- * @hide
*/
public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
/**
@@ -138,6 +142,8 @@
* device they all get the same link. However, the link is only set up on the first request -
* hence only the first can transmit the port information. But we don't want to expose that
* information to other apps. Limiting to secure links would (usually) imply single app usage.
+ *
+ * @hide
*/
public final int transportProtocol;
@@ -292,4 +298,197 @@
throw new SecurityException("mismatched UIDs");
}
}
+
+ /**
+ * A builder class for a Wi-Fi Aware network specifier to set up an Aware connection with a
+ * peer.
+ * <p>
+ * Note that all Wi-Fi Aware connection specifier objects must call the
+ * {@link Builder#setDiscoverySession(DiscoverySession)} to specify the context
+ * within which the connection is created, and
+ * {@link Builder#setPeerHandle(PeerHandle)} to specify the peer to which the
+ * connection is created.
+ */
+ public static final class Builder {
+ private DiscoverySession mDiscoverySession;
+ private PeerHandle mPeerHandle;
+ private String mPskPassphrase;
+ private byte[] mPmk;
+ private int mPort = 0; // invalid value
+ private int mTransportProtocol = -1; // invalid value
+
+ /**
+ * Configure the {@link PublishDiscoverySession} or {@link SubscribeDiscoverySession}
+ * discovery session in whose context the connection is created.
+ * <p>
+ * Note: this method must be called for any connection request!
+ *
+ * @param discoverySession A Wi-Fi Aware discovery session.
+ * @return the current {@link Builder} builder, enabling chaining of builder
+ * methods.
+ */
+ public @NonNull Builder setDiscoverySession(@NonNull DiscoverySession discoverySession) {
+ if (discoverySession == null) {
+ throw new IllegalArgumentException("Non-null discoverySession required");
+ }
+ mDiscoverySession = discoverySession;
+ return this;
+ }
+
+ /**
+ * Configure the {@link PeerHandle} of the peer to which the Wi-Fi Aware connection is
+ * requested. The peer is discovered through Wi-Fi Aware discovery,
+ * <p>
+ * Note: this method must be called for any connection request!
+ *
+ * @param peerHandle The peer's handle obtained through
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
+ * or
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
+ * @return the current {@link Builder} builder, enabling chaining of builder
+ * methods.
+ */
+ public @NonNull Builder setPeerHandle(@NonNull PeerHandle peerHandle) {
+ if (peerHandle == null) {
+ throw new IllegalArgumentException("Non-null peerHandle required");
+ }
+ mPeerHandle = peerHandle;
+ return this;
+ }
+
+ /**
+ * Configure the PSK Passphrase for the Wi-Fi Aware connection being requested. This method
+ * is optional - if not called, then an Open (unencrypted) connection will be created.
+ *
+ * @param pskPassphrase The (optional) passphrase to be used to encrypt the link.
+ * @return the current {@link Builder} builder, enabling chaining of builder
+ * methods.
+ */
+ public @NonNull Builder setPskPassphrase(@NonNull String pskPassphrase) {
+ if (!WifiAwareUtils.validatePassphrase(pskPassphrase)) {
+ throw new IllegalArgumentException("Passphrase must meet length requirements");
+ }
+ mPskPassphrase = pskPassphrase;
+ return this;
+ }
+
+ /**
+ * Configure the PMK for the Wi-Fi Aware connection being requested. This method
+ * is optional - if not called, then an Open (unencrypted) connection will be created.
+ *
+ * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
+ * encrypting the data-path. Use the {@link #setPskPassphrase(String)} to
+ * specify a Passphrase.
+ * @return the current {@link Builder} builder, enabling chaining of builder
+ * methods.
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setPmk(@NonNull byte[] pmk) {
+ if (!WifiAwareUtils.validatePmk(pmk)) {
+ throw new IllegalArgumentException("PMK must 32 bytes");
+ }
+ mPmk = pmk;
+ return this;
+ }
+
+ /**
+ * Configure the port number which will be used to create a connection over this link. This
+ * configuration should only be done on the server device, e.g. the device creating the
+ * {@link java.net.ServerSocket}.
+ * <p>Notes:
+ * <ul>
+ * <li>The server device must be the Publisher device!
+ * <li>The port information can only be specified on secure links, specified using
+ * {@link #setPskPassphrase(String)}.
+ * </ul>
+ *
+ * @param port A positive integer indicating the port to be used for communication.
+ * @return the current {@link Builder} builder, enabling chaining of builder
+ * methods.
+ */
+ public @NonNull Builder setPort(int port) {
+ if (port <= 0 || port > 65535) {
+ throw new IllegalArgumentException("The port must be a positive value (0, 65535]");
+ }
+ mPort = port;
+ return this;
+ }
+
+ /**
+ * Configure the transport protocol which will be used to create a connection over this
+ * link. This configuration should only be done on the server device, e.g. the device
+ * creating the {@link java.net.ServerSocket} for TCP.
+ * <p>Notes:
+ * <ul>
+ * <li>The server device must be the Publisher device!
+ * <li>The transport protocol information can only be specified on secure links,
+ * specified using {@link #setPskPassphrase(String)}.
+ * </ul>
+ * The transport protocol number is assigned by the Internet Assigned Numbers Authority
+ * (IANA) https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml.
+ *
+ * @param transportProtocol The transport protocol to be used for communication.
+ * @return the current {@link Builder} builder, enabling chaining of builder
+ * methods.
+ */
+ public @NonNull Builder setTransportProtocol(int transportProtocol) {
+ if (transportProtocol < 0 || transportProtocol > 255) {
+ throw new IllegalArgumentException(
+ "The transport protocol must be in range [0, 255]");
+ }
+ mTransportProtocol = transportProtocol;
+ return this;
+ }
+
+ /**
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)}
+ * for a WiFi Aware connection (link) to the specified peer. The
+ * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
+ * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
+ * <p> The default builder constructor will initialize a NetworkSpecifier which requests an
+ * open (non-encrypted) link. To request an encrypted link use the
+ * {@link #setPskPassphrase(String)} builder method.
+ *
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass
+ * to {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+ * android.net.ConnectivityManager.NetworkCallback)}
+ * [or other varieties of that API].
+ */
+ public @NonNull WifiAwareNetworkSpecifier build() {
+ if (mDiscoverySession == null) {
+ throw new IllegalStateException("Null discovery session!?");
+ }
+ if (mPskPassphrase != null & mPmk != null) {
+ throw new IllegalStateException(
+ "Can only specify a Passphrase or a PMK - not both!");
+ }
+
+ int role = mDiscoverySession instanceof SubscribeDiscoverySession
+ ? WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+ : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
+
+ if (mPort != 0 || mTransportProtocol != -1) {
+ if (role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
+ throw new IllegalStateException(
+ "Port and transport protocol information can only "
+ + "be specified on the Publisher device (which is the server");
+ }
+ if (TextUtils.isEmpty(mPskPassphrase) && mPmk == null) {
+ throw new IllegalStateException("Port and transport protocol information can "
+ + "only be specified on a secure link");
+ }
+ }
+
+ if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR && mPeerHandle == null) {
+ throw new IllegalStateException("Null peerHandle!?");
+ }
+
+ return new WifiAwareNetworkSpecifier(
+ WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB, role,
+ mDiscoverySession.mClientId, mDiscoverySession.mSessionId, mPeerHandle.peerId,
+ null, mPmk, mPskPassphrase, mPort, mTransportProtocol, Process.myUid());
+ }
+ }
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 245b304..3c97813 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -213,7 +213,7 @@
* This API is targeted for applications which can obtain the peer MAC address using OOB
* (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
* when using Aware discovery use the alternative network specifier method -
- * {@link android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder}.
+ * {@link android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder}.
* <p>
* To set up an encrypted link use the
* {@link #createNetworkSpecifierPassphrase(int, byte[], String)} API.
@@ -254,7 +254,7 @@
* This API is targeted for applications which can obtain the peer MAC address using OOB
* (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
* when using Aware discovery use the alternative network specifier method -
- * {@link android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder}.
+ * {@link android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder}.
*
* @param role The role of this device:
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
@@ -300,7 +300,7 @@
* This API is targeted for applications which can obtain the peer MAC address using OOB
* (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
* when using Aware discovery use the alternative network specifier method -
- * {@link android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder}.
+ * {@link android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder}.
*
* @param role The role of this device:
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 6c1b073..c3cfb02 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -227,7 +227,7 @@
public static final class Builder {
private static final MacAddress MAC_ANY_ADDRESS =
- MacAddress.fromString("00:00:00:00:00:00");
+ MacAddress.fromString("02:00:00:00:00:00");
private MacAddress mDeviceAddress = MAC_ANY_ADDRESS;
private String mNetworkName = "";
@@ -240,9 +240,9 @@
* Specify the peer's MAC address. If not set, the device will
* try to find a peer whose SSID matches the network name as
* specified by {@link #setNetworkName(String)}. Specifying null will
- * reset the peer's MAC address to "00:00:00:00:00:00".
+ * reset the peer's MAC address to "02:00:00:00:00:00".
* <p>
- * Optional. "00:00:00:00:00:00" by default.
+ * Optional. "02:00:00:00:00:00" by default.
*
* @param deviceAddress the peer's MAC address.
* @return The builder to facilitate chaining
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 29a18d2..a779378 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -793,7 +793,7 @@
* The requested {@link android.net.NetworkInfo} is available
* @param networkInfo Wi-Fi p2p {@link android.net.NetworkInfo}
*/
- void onNetworkInfoAvailable(NetworkInfo networkInfo);
+ void onNetworkInfoAvailable(@NonNull NetworkInfo networkInfo);
}
/**
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index b303496..0ce5d66 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -70,7 +70,7 @@
assertTrue(readWifiInfo.isOsuAp());
assertTrue(readWifiInfo.isPasspointAp());
assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getNetworkSuggestionOrSpecifierPackageName());
- assertEquals(TEST_FQDN, readWifiInfo.getFqdn());
- assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getProviderFriendlyName());
+ assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
+ assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
}
}
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 3cc96bf..657a338 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -958,9 +958,8 @@
WifiAwareNetworkSpecifier ns =
(WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierOpen(
peerHandle);
- WifiAwareNetworkSpecifier nsb = (WifiAwareNetworkSpecifier) new WifiAwareManager
- .NetworkSpecifierBuilder().setDiscoverySession(publishSession.getValue())
- .setPeerHandle(peerHandle).build();
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
+ publishSession.getValue()).setPeerHandle(peerHandle).build();
// validate format
collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
@@ -980,9 +979,9 @@
// (4) request an encrypted (PMK) network specifier from the session
ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPmk(
peerHandle, pmk);
- nsb = (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
- .setDiscoverySession(publishSession.getValue()).setPeerHandle(peerHandle)
- .setPmk(pmk).setPort(port).setTransportProtocol(transportProtocol).build();
+ nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
+ publishSession.getValue()).setPeerHandle(peerHandle).setPmk(pmk).setPort(
+ port).setTransportProtocol(transportProtocol).build();
// validate format
collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
@@ -1006,10 +1005,9 @@
(WifiAwareNetworkSpecifier) publishSession.getValue()
.createNetworkSpecifierPassphrase(
peerHandle, passphrase);
- nsb = (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
- .setDiscoverySession(publishSession.getValue()).setPeerHandle(peerHandle)
- .setPskPassphrase(passphrase).setPort(port).setTransportProtocol(transportProtocol)
- .build();
+ nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
+ publishSession.getValue()).setPeerHandle(peerHandle).setPskPassphrase(
+ passphrase).setPort(port).setTransportProtocol(transportProtocol).build();
// validate format
collector.checkThat("role", WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
@@ -1257,14 +1255,14 @@
// (3) create network specifier
if (doPmk) {
if (useBuilder) {
- new WifiAwareManager.NetworkSpecifierBuilder().setDiscoverySession(
+ new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
publishSession.getValue()).setPeerHandle(peerHandle).setPmk(pmk).build();
} else {
publishSession.getValue().createNetworkSpecifierPmk(peerHandle, pmk);
}
} else {
if (useBuilder) {
- new WifiAwareManager.NetworkSpecifierBuilder().setDiscoverySession(
+ new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
publishSession.getValue()).setPeerHandle(peerHandle).setPskPassphrase(
passphrase).build();
} else {
@@ -1355,10 +1353,8 @@
DiscoverySession publishSession = executeSessionStartup(true);
- WifiAwareNetworkSpecifier nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
- .setDiscoverySession(publishSession).setPeerHandle(peerHandle)
- .setPmk(pmk).setPort(port).build();
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
+ publishSession).setPeerHandle(peerHandle).setPmk(pmk).setPort(port).build();
}
/**
@@ -1372,10 +1368,8 @@
DiscoverySession publishSession = executeSessionStartup(true);
- WifiAwareNetworkSpecifier nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
- .setDiscoverySession(publishSession).setPeerHandle(peerHandle)
- .setPort(port).build();
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
+ publishSession).setPeerHandle(peerHandle).setPort(port).build();
}
/**
@@ -1389,10 +1383,8 @@
DiscoverySession subscribeSession = executeSessionStartup(false);
- WifiAwareNetworkSpecifier nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
- .setDiscoverySession(subscribeSession).setPeerHandle(peerHandle)
- .setPort(port).build();
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
+ subscribeSession).setPeerHandle(peerHandle).setPort(port).build();
}
/**
@@ -1411,8 +1403,7 @@
DiscoverySession publishSession = executeSessionStartup(true);
try {
- WifiAwareNetworkSpecifier nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
.setDiscoverySession(publishSession).setPeerHandle(peerHandle)
.setPmk(pmk).setTransportProtocol(tpNegative).build();
assertTrue("No exception on negative transport protocol!", false);
@@ -1420,23 +1411,19 @@
// nop - exception is correct!
}
try {
- WifiAwareNetworkSpecifier nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
.setDiscoverySession(publishSession).setPeerHandle(peerHandle)
.setPmk(pmk).setTransportProtocol(tpTooLarge).build();
assertTrue("No exception on >255 transport protocol!", false);
} catch (IllegalArgumentException e) {
// nop - exception is correct!
}
- WifiAwareNetworkSpecifier nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
.setDiscoverySession(publishSession).setPeerHandle(peerHandle)
.setPmk(pmk).setTransportProtocol(tpSmallest).build();
- nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
- .setDiscoverySession(
- publishSession).setPeerHandle(peerHandle).setPmk(
- pmk).setTransportProtocol(tpLargest).build();
+ nsb = new WifiAwareNetworkSpecifier.Builder().setDiscoverySession(
+ publishSession).setPeerHandle(peerHandle).setPmk(pmk).setTransportProtocol(
+ tpLargest).build();
}
/**
@@ -1450,8 +1437,7 @@
DiscoverySession publishSession = executeSessionStartup(true);
- WifiAwareNetworkSpecifier nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
.setDiscoverySession(publishSession).setPeerHandle(peerHandle)
.setTransportProtocol(transportProtocol).build();
}
@@ -1467,8 +1453,7 @@
DiscoverySession subscribeSession = executeSessionStartup(false);
- WifiAwareNetworkSpecifier nsb =
- (WifiAwareNetworkSpecifier) new WifiAwareManager.NetworkSpecifierBuilder()
+ WifiAwareNetworkSpecifier nsb = new WifiAwareNetworkSpecifier.Builder()
.setDiscoverySession(subscribeSession).setPeerHandle(peerHandle)
.setTransportProtocol(transportProtocol).build();
}