Merge "Hiding clear all when replying now" into pi-dev
diff --git a/apct-tests/perftests/core/AndroidTest.xml b/apct-tests/perftests/core/AndroidTest.xml
index 6aa34a6..1b28913 100644
--- a/apct-tests/perftests/core/AndroidTest.xml
+++ b/apct-tests/perftests/core/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.perftests.core" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/apct-tests/perftests/multiuser/AndroidTest.xml b/apct-tests/perftests/multiuser/AndroidTest.xml
index 6ede827..512dbc9 100644
--- a/apct-tests/perftests/multiuser/AndroidTest.xml
+++ b/apct-tests/perftests/multiuser/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.perftests.multiuser" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/api/current.txt b/api/current.txt
index c351bee..423e0ae 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5393,7 +5393,7 @@
method public android.app.Notification.Builder addAction(android.app.Notification.Action);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public deprecated android.app.Notification.Builder addPerson(java.lang.String);
- method public android.app.Notification.Builder addPerson(android.app.Notification.Person);
+ method public android.app.Notification.Builder addPerson(android.app.Person);
method public android.app.Notification build();
method public android.widget.RemoteViews createBigContentView();
method public android.widget.RemoteViews createContentView();
@@ -5518,15 +5518,15 @@
public static class Notification.MessagingStyle extends android.app.Notification.Style {
ctor public deprecated Notification.MessagingStyle(java.lang.CharSequence);
- ctor public Notification.MessagingStyle(android.app.Notification.Person);
+ ctor public Notification.MessagingStyle(android.app.Person);
method public android.app.Notification.MessagingStyle addHistoricMessage(android.app.Notification.MessagingStyle.Message);
method public deprecated android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
- method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, android.app.Notification.Person);
+ method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, android.app.Person);
method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
method public java.lang.CharSequence getConversationTitle();
method public java.util.List<android.app.Notification.MessagingStyle.Message> getHistoricMessages();
method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
- method public android.app.Notification.Person getUser();
+ method public android.app.Person getUser();
method public deprecated java.lang.CharSequence getUserDisplayName();
method public boolean isGroupConversation();
method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
@@ -5536,37 +5536,17 @@
public static final class Notification.MessagingStyle.Message {
ctor public deprecated Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
- ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, android.app.Notification.Person);
+ ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, android.app.Person);
method public java.lang.String getDataMimeType();
method public android.net.Uri getDataUri();
method public android.os.Bundle getExtras();
method public deprecated java.lang.CharSequence getSender();
- method public android.app.Notification.Person getSenderPerson();
+ method public android.app.Person getSenderPerson();
method public java.lang.CharSequence getText();
method public long getTimestamp();
method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
}
- public static final class Notification.Person implements android.os.Parcelable {
- ctor protected Notification.Person(android.os.Parcel);
- ctor public Notification.Person();
- method public int describeContents();
- method public android.graphics.drawable.Icon getIcon();
- method public java.lang.String getKey();
- method public java.lang.CharSequence getName();
- method public java.lang.String getUri();
- method public boolean isBot();
- method public boolean isImportant();
- method public android.app.Notification.Person setBot(boolean);
- method public android.app.Notification.Person setIcon(android.graphics.drawable.Icon);
- method public android.app.Notification.Person setImportant(boolean);
- method public android.app.Notification.Person setKey(java.lang.String);
- method public android.app.Notification.Person setName(java.lang.CharSequence);
- method public android.app.Notification.Person setUri(java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.Notification.Person> CREATOR;
- }
-
public static abstract class Notification.Style {
ctor public Notification.Style();
method public android.app.Notification build();
@@ -5817,6 +5797,30 @@
method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle);
}
+ public final class Person implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.graphics.drawable.Icon getIcon();
+ method public java.lang.String getKey();
+ method public java.lang.CharSequence getName();
+ method public java.lang.String getUri();
+ method public boolean isBot();
+ method public boolean isImportant();
+ method public android.app.Person.Builder toBuilder();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.Person> CREATOR;
+ }
+
+ public static class Person.Builder {
+ ctor public Person.Builder();
+ method public android.app.Person build();
+ method public android.app.Person.Builder setBot(boolean);
+ method public android.app.Person.Builder setIcon(android.graphics.drawable.Icon);
+ method public android.app.Person.Builder setImportant(boolean);
+ method public android.app.Person.Builder setKey(java.lang.String);
+ method public android.app.Person.Builder setName(java.lang.CharSequence);
+ method public android.app.Person.Builder setUri(java.lang.String);
+ }
+
public final class PictureInPictureParams implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -6749,6 +6753,12 @@
field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
}
+ public class FreezePeriod {
+ ctor public FreezePeriod(java.time.MonthDay, java.time.MonthDay);
+ method public java.time.MonthDay getEnd();
+ method public java.time.MonthDay getStart();
+ }
+
public abstract class NetworkEvent implements android.os.Parcelable {
method public int describeContents();
method public long getId();
@@ -6819,16 +6829,16 @@
field public static final int SECURITY_PATCH_STATE_UNKNOWN = 0; // 0x0
}
- public class SystemUpdatePolicy implements android.os.Parcelable {
+ public final class SystemUpdatePolicy implements android.os.Parcelable {
method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
method public static android.app.admin.SystemUpdatePolicy createWindowedInstallPolicy(int, int);
method public int describeContents();
- method public java.util.List<android.util.Pair<java.lang.Integer, java.lang.Integer>> getFreezePeriods();
+ method public java.util.List<android.app.admin.FreezePeriod> getFreezePeriods();
method public int getInstallWindowEnd();
method public int getInstallWindowStart();
method public int getPolicyType();
- method public android.app.admin.SystemUpdatePolicy setFreezePeriods(java.util.List<android.util.Pair<java.lang.Integer, java.lang.Integer>>);
+ method public android.app.admin.SystemUpdatePolicy setFreezePeriods(java.util.List<android.app.admin.FreezePeriod>);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.SystemUpdatePolicy> CREATOR;
field public static final int TYPE_INSTALL_AUTOMATIC = 1; // 0x1
@@ -6841,11 +6851,12 @@
method public int getErrorCode();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.SystemUpdatePolicy.ValidationFailedException> CREATOR;
- field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 5; // 0x5
- field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 4; // 0x4
- field public static final int ERROR_DUPLICATE_OR_OVERLAP = 1; // 0x1
- field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 3; // 0x3
- field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 2; // 0x2
+ field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 6; // 0x6
+ field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 5; // 0x5
+ field public static final int ERROR_DUPLICATE_OR_OVERLAP = 2; // 0x2
+ field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 4; // 0x4
+ field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 3; // 0x3
+ field public static final int ERROR_UNKNOWN = 1; // 0x1
}
}
@@ -27263,7 +27274,6 @@
method public int describeContents();
method public boolean hasCapability(int);
method public boolean hasTransport(int);
- method public boolean hasUnwantedCapability(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkRequest> CREATOR;
}
@@ -27272,7 +27282,6 @@
ctor public NetworkRequest.Builder();
method public android.net.NetworkRequest.Builder addCapability(int);
method public android.net.NetworkRequest.Builder addTransportType(int);
- method public android.net.NetworkRequest.Builder addUnwantedCapability(int);
method public android.net.NetworkRequest build();
method public android.net.NetworkRequest.Builder removeCapability(int);
method public android.net.NetworkRequest.Builder removeTransportType(int);
@@ -27618,6 +27627,7 @@
public class X509TrustManagerExtensions {
ctor public X509TrustManagerExtensions(javax.net.ssl.X509TrustManager) throws java.lang.IllegalArgumentException;
method public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.lang.String) throws java.security.cert.CertificateException;
+ method public boolean isSameTrustConfiguration(java.lang.String, java.lang.String);
method public boolean isUserAddedCertificate(java.security.cert.X509Certificate);
}
@@ -42396,7 +42406,7 @@
}
public final class SubscriptionPlan implements android.os.Parcelable {
- method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator();
+ method public java.util.Iterator<android.util.Range<java.time.ZonedDateTime>> cycleIterator();
method public int describeContents();
method public int getDataLimitBehavior();
method public long getDataLimitBytes();
@@ -42418,9 +42428,7 @@
public static class SubscriptionPlan.Builder {
method public android.telephony.SubscriptionPlan build();
method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime);
- method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime);
- method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime);
- method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period);
method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence);
@@ -44689,7 +44697,7 @@
method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
field public static final int ALL = 15; // 0xf
field public static final int EMAIL_ADDRESSES = 2; // 0x2
- field public static final int MAP_ADDRESSES = 8; // 0x8
+ field public static final deprecated int MAP_ADDRESSES = 8; // 0x8
field public static final int PHONE_NUMBERS = 4; // 0x4
field public static final int WEB_URLS = 1; // 0x1
field public static final android.text.util.Linkify.MatchFilter sPhoneNumberMatchFilter;
@@ -47880,7 +47888,7 @@
method public void setVerticalScrollBarEnabled(boolean);
method public void setVerticalScrollbarPosition(int);
method public void setVisibility(int);
- method public void setWillNotCacheDrawing(boolean);
+ method public deprecated void setWillNotCacheDrawing(boolean);
method public void setWillNotDraw(boolean);
method public void setX(float);
method public void setY(float);
@@ -47898,7 +47906,7 @@
method public void unscheduleDrawable(android.graphics.drawable.Drawable);
method public final void updateDragShadow(android.view.View.DragShadowBuilder);
method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
- method public boolean willNotCacheDrawing();
+ method public deprecated boolean willNotCacheDrawing();
method public boolean willNotDraw();
field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
@@ -51308,7 +51316,7 @@
method public void documentHasImages(android.os.Message);
method public static void enableSlowWholeDocumentDraw();
method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>);
- method public static java.lang.String findAddress(java.lang.String);
+ method public static deprecated java.lang.String findAddress(java.lang.String);
method public deprecated int findAll(java.lang.String);
method public void findAllAsync(java.lang.String);
method public void findNext(boolean);
@@ -51320,7 +51328,6 @@
method public android.graphics.Bitmap getFavicon();
method public android.webkit.WebView.HitTestResult getHitTestResult();
method public deprecated java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
- method public android.os.Looper getLooper();
method public java.lang.String getOriginalUrl();
method public int getProgress();
method public boolean getRendererPriorityWaivedWhenNotVisible();
diff --git a/api/removed.txt b/api/removed.txt
index 1d6a8c2..8d72483 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -291,6 +291,14 @@
public static abstract class NetworkBadging.Badging implements java.lang.annotation.Annotation {
}
+ public class NetworkRequest implements android.os.Parcelable {
+ method public boolean hasUnwantedCapability(int);
+ }
+
+ public static class NetworkRequest.Builder {
+ method public android.net.NetworkRequest.Builder addUnwantedCapability(int);
+ }
+
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 656001c..6186a55 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -317,6 +317,7 @@
public class BroadcastOptions {
method public static android.app.BroadcastOptions makeBasic();
+ method public void setDontSendToRestrictedApps(boolean);
method public void setTemporaryAppWhitelistDuration(long);
method public android.os.Bundle toBundle();
}
@@ -452,7 +453,7 @@
field public static final int STATE_USER_UNMANAGED = 0; // 0x0
}
- public class SystemUpdatePolicy implements android.os.Parcelable {
+ public final class SystemUpdatePolicy implements android.os.Parcelable {
method public int describeContents();
method public android.app.admin.SystemUpdatePolicy.InstallationOption getInstallationOptionAt(long);
method public void writeToParcel(android.os.Parcel, int);
@@ -1254,6 +1255,7 @@
method public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration();
method public java.util.List<android.hardware.display.BrightnessChangeEvent> getBrightnessEvents();
method public android.hardware.display.BrightnessConfiguration getDefaultBrightnessConfiguration();
+ method public android.util.Pair<float[], float[]> getMinimumBrightnessCurve();
method public android.graphics.Point getStableDisplaySize();
method public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration);
method public void setSaturationLevel(float);
@@ -4355,6 +4357,7 @@
method public byte[] getServerParams();
method public int getSnapshotVersion();
method public java.security.cert.CertPath getTrustedHardwareCertPath();
+ method public deprecated byte[] getTrustedHardwarePublicKey();
method public java.util.List<android.security.keystore.recovery.WrappedApplicationKey> getWrappedApplicationKeys();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.security.keystore.recovery.KeyChainSnapshot> CREATOR;
@@ -4379,18 +4382,25 @@
public class RecoveryController {
method public android.security.keystore.recovery.RecoverySession createRecoverySession();
+ method public byte[] generateAndStoreKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
+ method public deprecated java.security.Key generateKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
method public java.security.Key generateKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
+ method public deprecated java.util.List<java.lang.String> getAliases(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
method public java.util.List<java.lang.String> getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException;
method public static android.security.keystore.recovery.RecoveryController getInstance(android.content.Context);
method public java.security.Key getKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException, java.security.UnrecoverableKeyException;
method public android.security.keystore.recovery.KeyChainSnapshot getKeyChainSnapshot() throws android.security.keystore.recovery.InternalRecoveryServiceException;
+ method public deprecated android.security.keystore.recovery.KeyChainSnapshot getRecoveryData() throws android.security.keystore.recovery.InternalRecoveryServiceException;
method public int[] getRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException;
+ method public deprecated int getRecoveryStatus(java.lang.String, java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
method public int getRecoveryStatus(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
method public java.util.Map<java.lang.String, java.security.cert.X509Certificate> getRootCertificates();
method public java.security.Key importKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
+ method public deprecated void initRecoveryService(java.lang.String, byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
method public void initRecoveryService(java.lang.String, byte[], byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
method public void removeKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
method public void setRecoverySecretTypes(int[]) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+ method public deprecated void setRecoveryStatus(java.lang.String, java.lang.String, int) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.content.pm.PackageManager.NameNotFoundException;
method public void setRecoveryStatus(java.lang.String, int) throws android.security.keystore.recovery.InternalRecoveryServiceException;
method public void setServerParams(byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException;
method public void setSnapshotCreatedPendingIntent(android.app.PendingIntent) throws android.security.keystore.recovery.InternalRecoveryServiceException;
@@ -4402,6 +4412,9 @@
public class RecoverySession implements java.lang.AutoCloseable {
method public void close();
method public java.util.Map<java.lang.String, java.security.Key> recoverKeyChainSnapshot(byte[], java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
+ method public deprecated java.util.Map<java.lang.String, byte[]> recoverKeys(byte[], java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
+ method public deprecated byte[] start(byte[], byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
+ method public deprecated byte[] start(java.security.cert.CertPath, byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
method public byte[] start(java.lang.String, java.security.cert.CertPath, byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
}
@@ -4411,6 +4424,7 @@
public final class WrappedApplicationKey implements android.os.Parcelable {
method public int describeContents();
+ method public deprecated byte[] getAccount();
method public java.lang.String getAlias();
method public byte[] getEncryptedKeyMaterial();
method public void writeToParcel(android.os.Parcel, int);
@@ -4420,6 +4434,7 @@
public static class WrappedApplicationKey.Builder {
ctor public WrappedApplicationKey.Builder();
method public android.security.keystore.recovery.WrappedApplicationKey build();
+ method public deprecated android.security.keystore.recovery.WrappedApplicationKey.Builder setAccount(byte[]);
method public android.security.keystore.recovery.WrappedApplicationKey.Builder setAlias(java.lang.String);
method public android.security.keystore.recovery.WrappedApplicationKey.Builder setEncryptedKeyMaterial(byte[]);
}
@@ -5108,6 +5123,7 @@
}
public abstract class NetworkService extends android.app.Service {
+ ctor public NetworkService();
method protected abstract android.telephony.NetworkService.NetworkServiceProvider createNetworkServiceProvider(int);
field public static final java.lang.String NETWORK_SERVICE_EXTRA_SLOT_ID = "android.telephony.extra.SLOT_ID";
field public static final java.lang.String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService";
@@ -5176,7 +5192,7 @@
}
public final class SubscriptionPlan implements android.os.Parcelable {
- method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator();
+ method public java.util.Iterator<android.util.Range<java.time.ZonedDateTime>> cycleIterator();
method public int describeContents();
method public int getDataLimitBehavior();
method public long getDataLimitBytes();
@@ -5198,9 +5214,10 @@
public static class SubscriptionPlan.Builder {
method public android.telephony.SubscriptionPlan build();
method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime);
- method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime);
- method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime);
- method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period);
+ method public static deprecated android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime);
+ method public static deprecated android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime);
+ method public static deprecated android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence);
@@ -5389,6 +5406,7 @@
}
public abstract class DataService extends android.app.Service {
+ ctor public DataService();
method public abstract android.telephony.data.DataService.DataServiceProvider createDataServiceProvider(int);
field public static final java.lang.String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
field public static final java.lang.String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 7cf12ef..48f43e0 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -91,37 +91,6 @@
}
-package android.security.keystore.recovery {
-
- public final class KeyChainSnapshot implements android.os.Parcelable {
- method public deprecated byte[] getTrustedHardwarePublicKey();
- }
-
- public class RecoveryController {
- method public deprecated java.security.Key generateKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
- method public deprecated java.util.List<java.lang.String> getAliases(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
- method public deprecated android.security.keystore.recovery.KeyChainSnapshot getRecoveryData() throws android.security.keystore.recovery.InternalRecoveryServiceException;
- method public deprecated int getRecoveryStatus(java.lang.String, java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
- method public deprecated void initRecoveryService(java.lang.String, byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
- method public deprecated void setRecoveryStatus(java.lang.String, java.lang.String, int) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.content.pm.PackageManager.NameNotFoundException;
- }
-
- public class RecoverySession implements java.lang.AutoCloseable {
- method public deprecated java.util.Map<java.lang.String, byte[]> recoverKeys(byte[], java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
- method public deprecated byte[] start(byte[], byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
- method public deprecated byte[] start(java.security.cert.CertPath, byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
- }
-
- public final class WrappedApplicationKey implements android.os.Parcelable {
- method public deprecated byte[] getAccount();
- }
-
- public static class WrappedApplicationKey.Builder {
- method public deprecated android.security.keystore.recovery.WrappedApplicationKey.Builder setAccount(byte[]);
- }
-
-}
-
package android.service.notification {
public abstract class NotificationListenerService extends android.app.Service {
diff --git a/api/test-current.txt b/api/test-current.txt
index 4878690..94154c2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -245,6 +245,8 @@
method public abstract int getInstallReason(java.lang.String, android.os.UserHandle);
method public abstract java.lang.String[] getNamesForUids(int[]);
method public abstract java.lang.String getPermissionControllerPackageName();
+ method public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
+ method public abstract java.lang.String getSharedSystemSharedLibraryPackageName();
method public abstract boolean isPermissionReviewModeEnabled();
field public static final java.lang.String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
field public static final java.lang.String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
@@ -465,14 +467,70 @@
method public void setType(int);
}
+ public class LocationManager {
+ method public java.lang.String[] getBackgroundThrottlingWhitelist();
+ }
+
+}
+
+package android.media {
+
+ public final class AudioFocusRequest {
+ method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
+ }
+
+ public final class AudioFormat implements android.os.Parcelable {
+ method public static int channelCountFromInChannelMask(int);
+ method public static int channelCountFromOutChannelMask(int);
+ method public static int getBytesPerSample(int);
+ method public static boolean isEncodingLinearPcm(int);
+ }
+
+ public final class AudioPresentation {
+ ctor public AudioPresentation(int, int, java.util.Map<java.lang.String, java.lang.String>, java.lang.String, int, boolean, boolean, boolean);
+ method public int getPresentationId();
+ method public int getProgramId();
+ }
+
+ public final class PlaybackParams implements android.os.Parcelable {
+ method public int getAudioStretchMode();
+ method public android.media.PlaybackParams setAudioStretchMode(int);
+ }
+
+ public static final class VolumeShaper.Configuration.Builder {
+ method public android.media.VolumeShaper.Configuration.Builder setOptionFlags(int);
+ }
+
}
package android.media.audiofx {
public class AudioEffect {
+ method public static int byteArrayToInt(byte[]);
+ method public static short byteArrayToShort(byte[]);
+ method public int getParameter(byte[], byte[]) throws java.lang.IllegalStateException;
+ method public int getParameter(int, byte[]) throws java.lang.IllegalStateException;
+ method public int getParameter(int, int[]) throws java.lang.IllegalStateException;
+ method public int getParameter(int, short[]) throws java.lang.IllegalStateException;
+ method public int getParameter(int[], short[]) throws java.lang.IllegalStateException;
+ method public static byte[] intToByteArray(int);
+ method public static boolean isEffectTypeAvailable(java.util.UUID);
+ method public static boolean isError(int);
+ method public int setParameter(byte[], byte[]) throws java.lang.IllegalStateException;
+ method public int setParameter(int, int) throws java.lang.IllegalStateException;
+ method public int setParameter(int, short) throws java.lang.IllegalStateException;
+ method public int setParameter(int, byte[]) throws java.lang.IllegalStateException;
+ method public int setParameter(int[], int[]) throws java.lang.IllegalStateException;
+ method public int setParameter(int[], byte[]) throws java.lang.IllegalStateException;
+ method public void setParameterListener(android.media.audiofx.AudioEffect.OnParameterChangeListener);
+ method public static byte[] shortToByteArray(short);
field public static final java.util.UUID EFFECT_TYPE_NULL;
}
+ public static abstract interface AudioEffect.OnParameterChangeListener {
+ method public abstract void onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]);
+ }
+
}
package android.net {
@@ -497,6 +555,15 @@
field public static final int RESOURCES_SDK_INT;
}
+ public class DeviceIdleManager {
+ method public java.lang.String[] getSystemPowerWhitelist();
+ method public java.lang.String[] getSystemPowerWhitelistExceptIdle();
+ }
+
+ public class Environment {
+ method public static java.io.File buildPath(java.io.File, java.lang.String...);
+ }
+
public class IncidentManager {
method public void reportIncident(android.os.IncidentReportArgs);
}
@@ -564,12 +631,18 @@
method public abstract void log(android.os.StrictMode.ViolationInfo);
}
+ public class SystemProperties {
+ method public static java.lang.String get(java.lang.String, java.lang.String);
+ }
+
public final class UserHandle implements android.os.Parcelable {
method public static int getAppId(int);
method public int getIdentifier();
+ field public static final android.os.UserHandle SYSTEM;
}
public class UserManager {
+ method public static boolean isSplitSystemUser();
field public static final java.lang.String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
}
@@ -786,6 +859,10 @@
public class ServiceState implements android.os.Parcelable {
method public void setCdmaSystemAndNetworkId(int, int);
+ method public void setCellBandwidths(int[]);
+ method public void setChannelNumber(int);
+ method public void setRilDataRadioTechnology(int);
+ method public void setRilVoiceRadioTechnology(int);
}
public class TelephonyManager {
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 41527f6..90ce735 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -212,7 +212,10 @@
sp<MetricsManager> newMetricsManager =
new MetricsManager(key, config, mTimeBaseSec, (timestampNs - 1) / NS_PER_SEC + 1, mUidMap,
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
-
+ auto it = mMetricsManagers.find(key);
+ if (it != mMetricsManagers.end()) {
+ WriteDataToDiskLocked(it->first);
+ }
if (newMetricsManager->isConfigValid()) {
mUidMap->OnConfigUpdated(key);
if (newMetricsManager->shouldAddUidMapListener()) {
@@ -251,19 +254,10 @@
* onDumpReport dumps serialized ConfigMetricsReportList into outData.
*/
void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTimeStampNs,
+ const bool include_current_partial_bucket,
vector<uint8_t>* outData) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- auto it = mMetricsManagers.find(key);
- if (it == mMetricsManagers.end()) {
- ALOGW("Config source %s does not exist", key.ToString().c_str());
- return;
- }
-
- // This allows another broadcast to be sent within the rate-limit period if we get close to
- // filling the buffer again soon.
- mLastBroadcastTimes.erase(key);
-
ProtoOutputStream proto;
// Start of ConfigKey.
@@ -273,18 +267,26 @@
proto.end(configKeyToken);
// End of ConfigKey.
- // Start of ConfigMetricsReport (reports).
- uint64_t reportsToken =
- proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
- onConfigMetricsReportLocked(key, dumpTimeStampNs, &proto);
- proto.end(reportsToken);
- // End of ConfigMetricsReport (reports).
-
-
// Then, check stats-data directory to see there's any file containing
// ConfigMetricsReport from previous shutdowns to concatenate to reports.
StorageManager::appendConfigMetricsReport(key, &proto);
+ auto it = mMetricsManagers.find(key);
+ if (it != mMetricsManagers.end()) {
+ // This allows another broadcast to be sent within the rate-limit period if we get close to
+ // filling the buffer again soon.
+ mLastBroadcastTimes.erase(key);
+
+ // Start of ConfigMetricsReport (reports).
+ uint64_t reportsToken =
+ proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
+ onConfigMetricsReportLocked(key, dumpTimeStampNs, include_current_partial_bucket, &proto);
+ proto.end(reportsToken);
+ // End of ConfigMetricsReport (reports).
+ } else {
+ ALOGW("Config source %s does not exist", key.ToString().c_str());
+ }
+
if (outData != nullptr) {
outData->clear();
outData->resize(proto.size());
@@ -298,7 +300,7 @@
}
}
- StatsdStats::getInstance().noteMetricsReportSent(key);
+ StatsdStats::getInstance().noteMetricsReportSent(key, proto.size());
}
/*
@@ -306,16 +308,20 @@
*/
void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key,
const int64_t dumpTimeStampNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* proto) {
// We already checked whether key exists in mMetricsManagers in
// WriteDataToDisk.
auto it = mMetricsManagers.find(key);
+ if (it == mMetricsManagers.end()) {
+ return;
+ }
int64_t lastReportTimeNs = it->second->getLastReportTimeNs();
int64_t lastReportWallClockNs = it->second->getLastReportWallClockNs();
// First, fill in ConfigMetricsReport using current data on memory, which
// starts from filling in StatsLogReport's.
- it->second->onDumpReport(dumpTimeStampNs, proto);
+ it->second->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, proto);
// Fill in UidMap.
uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
@@ -331,7 +337,6 @@
(long long)lastReportWallClockNs);
proto->write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS,
(long long)getWallClockNs());
-
}
void StatsLogProcessor::resetIfConfigTtlExpiredLocked(const int64_t timestampNs) {
@@ -361,6 +366,7 @@
std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
if (it != mMetricsManagers.end()) {
+ WriteDataToDiskLocked(key);
mMetricsManagers.erase(it);
mUidMap->OnConfigRemoved(key);
}
@@ -406,22 +412,30 @@
}
}
+void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key) {
+ ProtoOutputStream proto;
+ onConfigMetricsReportLocked(key, getElapsedRealtimeNs(),
+ true /* include_current_partial_bucket*/, &proto);
+ string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
+ (long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
+ android::base::unique_fd fd(open(file_name.c_str(),
+ O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
+ if (fd == -1) {
+ ALOGE("Attempt to write %s but failed", file_name.c_str());
+ return;
+ }
+ proto.flush(fd.get());
+}
+
+void StatsLogProcessor::WriteDataToDiskLocked() {
+ for (auto& pair : mMetricsManagers) {
+ WriteDataToDiskLocked(pair.first);
+ }
+}
+
void StatsLogProcessor::WriteDataToDisk() {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- for (auto& pair : mMetricsManagers) {
- const ConfigKey& key = pair.first;
- ProtoOutputStream proto;
- onConfigMetricsReportLocked(key, getElapsedRealtimeNs(), &proto);
- string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
- (long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
- android::base::unique_fd fd(open(file_name.c_str(),
- O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
- if (fd == -1) {
- VLOG("Attempt to write %s but failed", file_name.c_str());
- return;
- }
- proto.flush(fd.get());
- }
+ WriteDataToDiskLocked();
}
} // namespace statsd
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index d37429e..1e82b1e 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -48,7 +48,8 @@
size_t GetMetricsSize(const ConfigKey& key) const;
- void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs, vector<uint8_t>* outData);
+ void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket, vector<uint8_t>* outData);
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
void onAnomalyAlarmFired(
@@ -102,7 +103,11 @@
void OnConfigUpdatedLocked(
const int64_t currentTimestampNs, const ConfigKey& key, const StatsdConfig& config);
+ void WriteDataToDiskLocked();
+ void WriteDataToDiskLocked(const ConfigKey& key);
+
void onConfigMetricsReportLocked(const ConfigKey& key, const int64_t dumpTimeStampNs,
+ const bool include_current_partial_bucket,
util::ProtoOutputStream* proto);
/* Check if we should send a broadcast if approaching memory limits and if we're over, we
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index dac73ef..d3cda63 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -178,23 +178,34 @@
}
bool verbose = false;
+ bool proto = false;
if (args.size() > 0 && !args[0].compare(String16("-v"))) {
verbose = true;
}
+ if (args.size() > 0 && !args[args.size()-1].compare(String16("--proto"))) {
+ proto = true;
+ }
- // TODO: Proto format for incident reports
- dump_impl(out, verbose);
+ dump_impl(out, verbose, proto);
fclose(out);
return NO_ERROR;
}
/**
- * Write debugging data about statsd in text format.
+ * Write debugging data about statsd in text or proto format.
*/
-void StatsService::dump_impl(FILE* out, bool verbose) {
- StatsdStats::getInstance().dumpStats(out);
- mProcessor->dumpStates(out, verbose);
+void StatsService::dump_impl(FILE* out, bool verbose, bool proto) {
+ if (proto) {
+ vector<uint8_t> data;
+ StatsdStats::getInstance().dumpStats(&data, false); // does not reset statsdStats.
+ for (size_t i = 0; i < data.size(); i ++) {
+ fprintf(out, "%c", data[i]);
+ }
+ } else {
+ StatsdStats::getInstance().dumpStats(out);
+ mProcessor->dumpStates(out, verbose);
+ }
}
/**
@@ -325,6 +336,7 @@
fprintf(out, "\n");
fprintf(out, "usage: adb shell cmd stats print-stats\n");
fprintf(out, " Prints some basic stats.\n");
+ fprintf(out, " --proto Print proto binary instead of string format.\n");
fprintf(out, "\n");
fprintf(out, "\n");
fprintf(out, "usage: adb shell cmd stats clear-puller-cache\n");
@@ -501,7 +513,7 @@
if (good) {
vector<uint8_t> data;
mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
- &data);
+ false /* include_current_bucket*/, &data);
// TODO: print the returned StatsLogReport to file instead of printing to logcat.
if (proto) {
for (size_t i = 0; i < data.size(); i ++) {
@@ -524,13 +536,28 @@
}
status_t StatsService::cmd_print_stats(FILE* out, const Vector<String8>& args) {
- vector<ConfigKey> configs = mConfigManager->GetAllConfigKeys();
- for (const ConfigKey& key : configs) {
- fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
- mProcessor->GetMetricsSize(key));
+ int argCount = args.size();
+ bool proto = false;
+ if (!std::strcmp("--proto", args[argCount-1].c_str())) {
+ proto = true;
+ argCount -= 1;
}
StatsdStats& statsdStats = StatsdStats::getInstance();
- statsdStats.dumpStats(out);
+ if (proto) {
+ vector<uint8_t> data;
+ statsdStats.dumpStats(&data, false); // does not reset statsdStats.
+ for (size_t i = 0; i < data.size(); i ++) {
+ fprintf(out, "%c", data[i]);
+ }
+
+ } else {
+ vector<ConfigKey> configs = mConfigManager->GetAllConfigKeys();
+ for (const ConfigKey& key : configs) {
+ fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
+ mProcessor->GetMetricsSize(key));
+ }
+ statsdStats.dumpStats(out);
+ }
return NO_ERROR;
}
@@ -800,7 +827,8 @@
VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
if (checkCallingPermission(String16(kPermissionDump))) {
ConfigKey configKey(ipc->getCallingUid(), key);
- mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), output);
+ mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
+ false /* include_current_bucket*/, output);
return Status::ok();
} else {
return Status::fromExceptionCode(binder::Status::EX_SECURITY);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index a4552e1..648e9c5 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -149,9 +149,9 @@
uint32_t serial);
/**
- * Text output of dumpsys.
+ * Text or proto output of dumpsys.
*/
- void dump_impl(FILE* out, bool verbose);
+ void dump_impl(FILE* out, bool verbose, bool proto);
/**
* Print usage information for the commands
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 7b2881d..b589d0d 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -76,7 +76,8 @@
const int FIELD_ID_CONFIG_STATS_VALID = 9;
const int FIELD_ID_CONFIG_STATS_BROADCAST = 10;
const int FIELD_ID_CONFIG_STATS_DATA_DROP = 11;
-const int FIELD_ID_CONFIG_STATS_DUMP_REPORT = 12;
+const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME = 12;
+const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES = 20;
const int FIELD_ID_CONFIG_STATS_MATCHER_STATS = 13;
const int FIELD_ID_CONFIG_STATS_CONDITION_STATS = 14;
const int FIELD_ID_CONFIG_STATS_METRIC_STATS = 15;
@@ -215,21 +216,22 @@
it->second->data_drop_time_sec.push_back(timeSec);
}
-void StatsdStats::noteMetricsReportSent(const ConfigKey& key) {
- noteMetricsReportSent(key, getWallClockSec());
+void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes) {
+ noteMetricsReportSent(key, num_bytes, getWallClockSec());
}
-void StatsdStats::noteMetricsReportSent(const ConfigKey& key, int32_t timeSec) {
+void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes,
+ int32_t timeSec) {
lock_guard<std::mutex> lock(mLock);
auto it = mConfigStats.find(key);
if (it == mConfigStats.end()) {
ALOGE("Config key %s not found!", key.ToString().c_str());
return;
}
- if (it->second->dump_report_time_sec.size() == kMaxTimestampCount) {
- it->second->dump_report_time_sec.pop_front();
+ if (it->second->dump_report_stats.size() == kMaxTimestampCount) {
+ it->second->dump_report_stats.pop_front();
}
- it->second->dump_report_time_sec.push_back(timeSec);
+ it->second->dump_report_stats.push_back(std::make_pair(timeSec, num_bytes));
}
void StatsdStats::noteUidMapDropped(int deltas) {
@@ -383,7 +385,7 @@
for (auto& config : mConfigStats) {
config.second->broadcast_sent_time_sec.clear();
config.second->data_drop_time_sec.clear();
- config.second->dump_report_time_sec.clear();
+ config.second->dump_report_stats.clear();
config.second->annotations.clear();
config.second->matcher_stats.clear();
config.second->condition_stats.clear();
@@ -442,8 +444,8 @@
fprintf(out, "\tdata drop time: %d\n", dataDropTime);
}
- for (const auto& dumpTime : configStats->dump_report_time_sec) {
- fprintf(out, "\tdump report time: %d\n", dumpTime);
+ for (const auto& dump : configStats->dump_report_stats) {
+ fprintf(out, "\tdump report time: %d bytes: %lld\n", dump.first, (long long)dump.second);
}
for (const auto& stats : pair.second->matcher_stats) {
@@ -536,9 +538,16 @@
drop);
}
- for (const auto& dump : configStats.dump_report_time_sec) {
- proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DUMP_REPORT | FIELD_COUNT_REPEATED,
- dump);
+ for (const auto& dump : configStats.dump_report_stats) {
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME |
+ FIELD_COUNT_REPEATED,
+ dump.first);
+ }
+
+ for (const auto& dump : configStats.dump_report_stats) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES |
+ FIELD_COUNT_REPEATED,
+ (long long)dump.second);
}
for (const auto& annotation : configStats.annotations) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 914d2af..123a703 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -43,7 +43,7 @@
std::list<int32_t> broadcast_sent_time_sec;
std::list<int32_t> data_drop_time_sec;
- std::list<int32_t> dump_report_time_sec;
+ std::list<std::pair<int32_t, int64_t>> dump_report_stats;
// Stores how many times a matcher have been matched. The map size is capped by kMaxConfigCount.
std::map<const int64_t, int> matcher_stats;
@@ -177,7 +177,7 @@
*
* The report may be requested via StatsManager API, or through adb cmd.
*/
- void noteMetricsReportSent(const ConfigKey& key);
+ void noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes);
/**
* Report the size of output tuple of a condition.
@@ -355,7 +355,7 @@
void noteDataDropped(const ConfigKey& key, int32_t timeSec);
- void noteMetricsReportSent(const ConfigKey& key, int32_t timeSec);
+ void noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes, int32_t timeSec);
void noteBroadcastSent(const ConfigKey& key, int32_t timeSec);
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 98963bd..c77e07b 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -123,8 +123,13 @@
}
void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
- flushIfNeededLocked(dumpTimeNs);
+ if (include_current_partial_bucket) {
+ flushLocked(dumpTimeNs);
+ } else {
+ flushIfNeededLocked(dumpTimeNs);
+ }
if (mPastBuckets.empty()) {
return;
}
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 5991c28..cafc882 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -54,7 +54,9 @@
const LogEvent& event) override;
private:
+
void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 19155de..3125fa7 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -439,8 +439,13 @@
}
void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
- flushIfNeededLocked(dumpTimeNs);
+ if (include_current_partial_bucket) {
+ flushLocked(dumpTimeNs);
+ } else {
+ flushIfNeededLocked(dumpTimeNs);
+ }
if (mPastBuckets.empty()) {
VLOG(" Duration metric, empty return");
return;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 80fb829..80fbdde 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -62,6 +62,7 @@
bool condition, const LogEvent& event);
void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index d55cb3f..33ab9aa 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -101,6 +101,7 @@
}
void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
if (mProto->size() <= 0) {
return;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index fbbc7e2..5c29174 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -47,6 +47,7 @@
const LogEvent& event) override;
void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 2561d1d..3c77aae 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -156,8 +156,14 @@
}
void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
VLOG("Gauge metric %lld report now...", (long long)mMetricId);
+ if (include_current_partial_bucket) {
+ flushLocked(dumpTimeNs);
+ } else {
+ flushIfNeededLocked(dumpTimeNs);
+ }
flushIfNeededLocked(dumpTimeNs);
if (mPastBuckets.empty()) {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index f49180f..04b7df9 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -88,6 +88,7 @@
private:
void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// for testing
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index db5d32c..f931e57 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -112,9 +112,11 @@
// Output the metrics data to [protoOutput]. All metrics reports end with the same timestamp.
// This method clears all the past buckets.
- void onDumpReport(const int64_t dumpTimeNs, android::util::ProtoOutputStream* protoOutput) {
+ void onDumpReport(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
+ android::util::ProtoOutputStream* protoOutput) {
std::lock_guard<std::mutex> lock(mMutex);
- return onDumpReportLocked(dumpTimeNs, protoOutput);
+ return onDumpReportLocked(dumpTimeNs, include_current_partial_bucket, protoOutput);
}
void dumpStates(FILE* out, bool verbose) const {
@@ -168,16 +170,26 @@
virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
const int64_t eventTime) = 0;
virtual void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) = 0;
virtual size_t byteSizeLocked() const = 0;
virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
/**
- * Flushes the current bucket if the eventTime is after the current bucket's end time.
+ * Flushes the current bucket if the eventTime is after the current bucket's end time. This will
+ also flush the current partial bucket in memory.
*/
virtual void flushIfNeededLocked(const int64_t& eventTime){};
/**
+ * Flushes all the data including the current partial bucket.
+ */
+ virtual void flushLocked(const int64_t& eventTime) {
+ flushIfNeededLocked(eventTime);
+ flushCurrentBucketLocked(eventTime);
+ };
+
+ /**
* For metrics that aggregate (ie, every metric producer except for EventMetricProducer),
* we need to be able to flush the current buckets on demand (ie, end the current bucket and
* start new bucket). If this function is called when eventTimeNs is greater than the current
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 22827b0..b7f1bd5 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -190,14 +190,16 @@
}
}
-void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs, ProtoOutputStream* protoOutput) {
+void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs,
+ const bool include_current_partial_bucket,
+ ProtoOutputStream* protoOutput) {
VLOG("=========================Metric Reports Start==========================");
// one StatsLogReport per MetricProduer
for (const auto& producer : mAllMetricProducers) {
if (mNoReportMetricIds.find(producer->getMetricId()) == mNoReportMetricIds.end()) {
uint64_t token =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS);
- producer->onDumpReport(dumpTimeStampNs, protoOutput);
+ producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, protoOutput);
protoOutput->end(token);
}
}
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 9a9b33c..6aa260a 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -90,8 +90,8 @@
virtual void dropData(const int64_t dropTimeNs);
- // Config source owner can call onDumpReport() to get all the metrics collected.
virtual void onDumpReport(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput);
// Computes the total byte size of all metrics managed by a single config source.
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index fd623ca..51fac8c 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -147,9 +147,14 @@
}
void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
VLOG("metric %lld dump report now...", (long long)mMetricId);
- flushIfNeededLocked(dumpTimeNs);
+ if (include_current_partial_bucket) {
+ flushLocked(dumpTimeNs);
+ } else {
+ flushIfNeededLocked(dumpTimeNs);
+ }
if (mPastBuckets.empty()) {
return;
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index c8f7062..b5f6429 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -87,6 +87,7 @@
private:
void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 3b86d2d..36b24c8 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -243,10 +243,10 @@
optional int32 matcher_count = 7;
optional int32 alert_count = 8;
optional bool is_valid = 9;
-
repeated int32 broadcast_sent_time_sec = 10;
repeated int32 data_drop_time_sec = 11;
repeated int32 dump_report_time_sec = 12;
+ repeated int32 dump_report_data_size = 20;
repeated MatcherStats matcher_stats = 13;
repeated ConditionStats condition_stats = 14;
repeated MetricStats metric_stats = 15;
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 09daf75..fb8877a 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -139,7 +139,7 @@
// Expect to get no metrics, but snapshot specified above in uidmap.
vector<uint8_t> bytes;
- p.onDumpReport(key, 1, &bytes);
+ p.onDumpReport(key, 1, false, &bytes);
ConfigMetricsReportList output;
output.ParseFromArray(bytes.data(), bytes.size());
@@ -167,7 +167,7 @@
// Expect to get no metrics, but snapshot specified above in uidmap.
vector<uint8_t> bytes;
- p.onDumpReport(key, 1, &bytes);
+ p.onDumpReport(key, 1, false, &bytes);
ConfigMetricsReportList output;
output.ParseFromArray(bytes.data(), bytes.size());
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index a97bc41..4dd0da8 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -144,7 +144,7 @@
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -286,7 +286,7 @@
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
index 63e23ce..eb57d470 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
@@ -172,7 +172,8 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1,
+ false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -488,7 +489,8 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
+ &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -731,7 +733,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
index c2334d8..9729a2e 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
@@ -130,7 +130,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -342,7 +342,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -521,7 +521,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -718,7 +718,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
index ab37140..4e2c36e 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
@@ -142,7 +142,8 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
+ &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -433,7 +434,8 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
+ &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -650,7 +652,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 2b91324..18a0485 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -148,7 +148,7 @@
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(1, reports.reports_size());
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 1440f29..1952a6f 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -200,7 +200,7 @@
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -314,7 +314,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index bfae8bc..f2d47c7 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -127,7 +127,7 @@
FeedEvents(config, processor);
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -161,7 +161,7 @@
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -208,7 +208,7 @@
processor->OnLogEvent(event.get());
}
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -237,7 +237,7 @@
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -262,7 +262,7 @@
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -304,7 +304,7 @@
processor->OnLogEvent(event.get());
}
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 5c35d96..e99e402 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -129,9 +129,9 @@
stats.noteDataDropped(key);
// dump report -> 3
- stats.noteMetricsReportSent(key);
- stats.noteMetricsReportSent(key);
- stats.noteMetricsReportSent(key);
+ stats.noteMetricsReportSent(key, 0);
+ stats.noteMetricsReportSent(key, 0);
+ stats.noteMetricsReportSent(key, 0);
vector<uint8_t> output;
stats.dumpStats(&output, true); // Dump and reset stats
@@ -143,6 +143,7 @@
EXPECT_EQ(2, configReport.broadcast_sent_time_sec_size());
EXPECT_EQ(1, configReport.data_drop_time_sec_size());
EXPECT_EQ(3, configReport.dump_report_time_sec_size());
+ EXPECT_EQ(3, configReport.dump_report_data_size_size());
EXPECT_EQ(1, configReport.annotation_size());
EXPECT_EQ(123, configReport.annotation(0).field_int64());
EXPECT_EQ(456, configReport.annotation(0).field_int32());
@@ -268,7 +269,7 @@
for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
stats.noteDataDropped(key, timestamps[i]);
stats.noteBroadcastSent(key, timestamps[i]);
- stats.noteMetricsReportSent(key, timestamps[i]);
+ stats.noteMetricsReportSent(key, 0, timestamps[i]);
}
int32_t newTimestamp = 10000;
@@ -276,7 +277,7 @@
// now it should trigger removing oldest timestamp
stats.noteDataDropped(key, 10000);
stats.noteBroadcastSent(key, 10000);
- stats.noteMetricsReportSent(key, 10000);
+ stats.noteMetricsReportSent(key, 0, 10000);
EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
const auto& configStats = stats.mConfigStats[key];
@@ -284,7 +285,7 @@
size_t maxCount = StatsdStats::kMaxTimestampCount;
EXPECT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
EXPECT_EQ(maxCount, configStats->data_drop_time_sec.size());
- EXPECT_EQ(maxCount, configStats->dump_report_time_sec.size());
+ EXPECT_EQ(maxCount, configStats->dump_report_stats.size());
// the oldest timestamp is the second timestamp in history
EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
@@ -294,7 +295,7 @@
// the last timestamp is the newest timestamp.
EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
- EXPECT_EQ(newTimestamp, configStats->dump_report_time_sec.back());
+ EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
}
} // namespace statsd
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 479fe27..73d1102 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2,8 +2,8 @@
Landroid/accounts/IAccountAuthenticatorResponse$Stub;-><init>()V
Landroid/accounts/IAccountManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManager;
Landroid/accounts/IAccountManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/animation/LayoutTransition;->cancel()V
Landroid/animation/LayoutTransition;->cancel(I)V
+Landroid/animation/LayoutTransition;->cancel()V
Landroid/animation/ValueAnimator;->animateValue(F)V
Landroid/animation/ValueAnimator;->sDurationScale:F
Landroid/app/Activity;->getActivityOptions()Landroid/app/ActivityOptions;
@@ -153,6 +153,8 @@
Landroid/app/AlarmManager;->WINDOW_EXACT:J
Landroid/app/AlarmManager;->WINDOW_HEURISTIC:J
Landroid/app/AlertDialog$Builder;->P:Lcom/android/internal/app/AlertController$AlertParams;
+Landroid/app/AlertDialog$Builder;->setRecycleOnMeasureEnabled(Z)Landroid/app/AlertDialog$Builder;
+Landroid/app/AlertDialog$Builder;->setView(Landroid/view/View;IIII)Landroid/app/AlertDialog$Builder;
Landroid/app/AlertDialog;->mAlert:Lcom/android/internal/app/AlertController;
Landroid/app/AppGlobals;->getInitialApplication()Landroid/app/Application;
Landroid/app/AppGlobals;->getInitialPackage()Ljava/lang/String;
@@ -190,6 +192,7 @@
Landroid/app/AppOpsManager;->OP_FINE_LOCATION:I
Landroid/app/AppOpsManager;->OP_GET_USAGE_STATS:I
Landroid/app/AppOpsManager;->OP_POST_NOTIFICATION:I
+Landroid/app/AppOpsManager;->OP_PROJECT_MEDIA:I
Landroid/app/AppOpsManager;->OP_READ_CONTACTS:I
Landroid/app/AppOpsManager;->OP_READ_PHONE_STATE:I
Landroid/app/AppOpsManager;->OP_READ_SMS:I
@@ -206,6 +209,7 @@
Landroid/app/backup/BackupDataOutput;->mBackupWriter:J
Landroid/app/backup/BackupHelperDispatcher$Header;->chunkSize:I
Landroid/app/backup/BackupHelperDispatcher$Header;->keyPrefix:Ljava/lang/String;
+Landroid/app/backup/FileBackupHelperBase;->writeNewStateDescription(Landroid/os/ParcelFileDescriptor;)V
Landroid/app/backup/FullBackup;->backupToTar(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/FullBackupDataOutput;)I
Landroid/app/backup/FullBackupDataOutput;->addSize(J)V
Landroid/app/backup/FullBackupDataOutput;-><init>(Landroid/os/ParcelFileDescriptor;)V
@@ -259,6 +263,7 @@
Landroid/app/IActivityManager;->publishContentProviders(Landroid/app/IApplicationThread;Ljava/util/List;)V
Landroid/app/IActivityManager;->requestBugReport(I)V
Landroid/app/IActivityManager;->resumeAppSwitches()V
+Landroid/app/IActivityManager;->setActivityController(Landroid/app/IActivityController;Z)V
Landroid/app/IActivityManager;->setRequestedOrientation(Landroid/os/IBinder;I)V
Landroid/app/IActivityManager;->setTaskResizeable(II)V
Landroid/app/IActivityManager;->stopService(Landroid/app/IApplicationThread;Landroid/content/Intent;Ljava/lang/String;I)I
@@ -328,6 +333,7 @@
Landroid/app/Notification$Builder;->mActions:Ljava/util/ArrayList;
Landroid/app/Notification$Builder;->makePublicContentView()Landroid/widget/RemoteViews;
Landroid/app/Notification$Builder;->setChannel(Ljava/lang/String;)Landroid/app/Notification$Builder;
+Landroid/app/Notification;-><init>(Landroid/content/Context;ILjava/lang/CharSequence;JLjava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/content/Intent;)V
Landroid/app/Notification;->isGroupSummary()Z
Landroid/app/NotificationManager;->getService()Landroid/app/INotificationManager;
Landroid/app/NotificationManager;->notifyAsUser(Ljava/lang/String;ILandroid/app/Notification;Landroid/os/UserHandle;)V
@@ -373,6 +379,7 @@
Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/app/usage/UsageStatsManager;->mService:Landroid/app/usage/IUsageStatsManager;
Landroid/app/usage/UsageStats;->mLastEvent:I
+Landroid/app/usage/UsageStats;->mLaunchCount:I
Landroid/app/usage/UsageStats;->mTotalTimeInForeground:J
Landroid/app/Vr2dDisplayProperties$Builder;->build()Landroid/app/Vr2dDisplayProperties;
Landroid/app/Vr2dDisplayProperties$Builder;-><init>()V
@@ -413,6 +420,10 @@
Landroid/bluetooth/BluetoothGatt;->mAuthRetryState:I
Landroid/bluetooth/BluetoothGatt;->refresh()Z
Landroid/bluetooth/BluetoothHeadset;->close()V
+Landroid/bluetooth/BluetoothHeadset;->connectAudio()Z
+Landroid/bluetooth/BluetoothHeadset;->disconnectAudio()Z
+Landroid/bluetooth/BluetoothHeadset;->startScoUsingVirtualVoiceCall(Landroid/bluetooth/BluetoothDevice;)Z
+Landroid/bluetooth/BluetoothHeadset;->stopScoUsingVirtualVoiceCall(Landroid/bluetooth/BluetoothDevice;)Z
Landroid/bluetooth/BluetoothMapClient;->sendMessage(Landroid/bluetooth/BluetoothDevice;[Landroid/net/Uri;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)Z
Landroid/bluetooth/BluetoothPan;->isTetheringOn()Z
Landroid/bluetooth/BluetoothPan;->setBluetoothTethering(Z)V
@@ -449,6 +460,7 @@
Landroid/content/ContentResolver;->mPackageName:Ljava/lang/String;
Landroid/content/ContentResolver;->releaseProvider(Landroid/content/IContentProvider;)Z
Landroid/content/ContentResolver;->releaseUnstableProvider(Landroid/content/IContentProvider;)Z
+Landroid/content/ContentResolver;->takePersistableUriPermission(Ljava/lang/String;Landroid/net/Uri;I)V
Landroid/content/ContentResolver;->unstableProviderDied(Landroid/content/IContentProvider;)V
Landroid/content/ContentValues;-><init>(Ljava/util/HashMap;)V
Landroid/content/ContentValues;->mValues:Ljava/util/HashMap;
@@ -474,6 +486,7 @@
Landroid/content/IntentFilter;->mActions:Ljava/util/ArrayList;
Landroid/content/Intent;->mExtras:Landroid/os/Bundle;
Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/IBinder;)Landroid/content/Intent;
+Landroid/content/Intent;->toInsecureString()Ljava/lang/String;
Landroid/content/pm/ActivityInfo;->resizeMode:I
Landroid/content/pm/ActivityInfo;->supportsPictureInPicture()Z
Landroid/content/pm/ApplicationInfo;->enabledSetting:I
@@ -514,6 +527,7 @@
Landroid/content/pm/LauncherActivityInfo;->mActivityInfo:Landroid/content/pm/ActivityInfo;
Landroid/content/pm/LauncherApps;->mPm:Landroid/content/pm/PackageManager;
Landroid/content/pm/LauncherApps;->startShortcut(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Rect;Landroid/os/Bundle;I)V
+Landroid/content/pm/PackageInfo;->INSTALL_LOCATION_UNSPECIFIED:I
Landroid/content/pm/PackageItemInfo;->setForceSafeLabels(Z)V
Landroid/content/pm/PackageManager;->buildRequestPermissionsIntent([Ljava/lang/String;)Landroid/content/Intent;
Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V
@@ -583,6 +597,7 @@
Landroid/content/res/AssetFileDescriptor;->mStartOffset:J
Landroid/content/res/AssetManager;->addAssetPathAsSharedLibrary(Ljava/lang/String;)I
Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I
+Landroid/content/res/AssetManager;->applyStyle(JIILandroid/content/res/XmlBlock$Parser;[IJJ)V
Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray;
Landroid/content/res/AssetManager;->getResourceBagText(II)Ljava/lang/CharSequence;
Landroid/content/res/AssetManager;->getResourceEntryName(I)Ljava/lang/String;
@@ -598,12 +613,14 @@
Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;I)Ljava/io/InputStream;
Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;)Ljava/io/InputStream;
Landroid/content/res/AssetManager;->resolveAttrs(JII[I[I[I[I)Z
+Landroid/content/res/AssetManager;->retrieveAttributes(Landroid/content/res/XmlBlock$Parser;[I[I[I)Z
Landroid/content/res/AssetManager;->setConfiguration(IILjava/lang/String;IIIIIIIIIIIIIII)V
Landroid/content/res/ColorStateList$ColorStateListFactory;-><init>(Landroid/content/res/ColorStateList;)V
Landroid/content/res/ColorStateList;->getColors()[I
Landroid/content/res/ColorStateList;->mColors:[I
Landroid/content/res/ColorStateList;->mDefaultColor:I
Landroid/content/res/ColorStateList;->mFactory:Landroid/content/res/ColorStateList$ColorStateListFactory;
+Landroid/content/res/ColorStateList;->mStateSpecs:[[I
Landroid/content/res/CompatibilityInfo;->applicationScale:F
Landroid/content/res/CompatibilityInfo;->DEFAULT_COMPATIBILITY_INFO:Landroid/content/res/CompatibilityInfo;
Landroid/content/res/DrawableCache;->getInstance(JLandroid/content/res/Resources;Landroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
@@ -660,6 +677,7 @@
Landroid/database/AbstractCursor;->mExtras:Landroid/os/Bundle;
Landroid/database/AbstractCursor;->mNotifyUri:Landroid/net/Uri;
Landroid/database/AbstractCursor;->mRowIdColumnIndex:I
+Landroid/database/AbstractWindowedCursor;->clearOrCreateWindow(Ljava/lang/String;)V
Landroid/database/CursorWindow;->mWindowPtr:J
Landroid/database/CursorWindow;->sCursorWindowSize:I
Landroid/database/CursorWindow;->sWindowToPidMap:Landroid/util/LongSparseArray;
@@ -668,12 +686,14 @@
Landroid/database/sqlite/SQLiteCustomFunction;->name:Ljava/lang/String;
Landroid/database/sqlite/SQLiteCustomFunction;->numArgs:I
Landroid/database/sqlite/SQLiteDatabaseConfiguration;->maxSqlCacheSize:I
+Landroid/database/sqlite/SQLiteDatabase;->CONFLICT_VALUES:[Ljava/lang/String;
Landroid/database/sqlite/SQLiteDatabase;->mConfigurationLocked:Landroid/database/sqlite/SQLiteDatabaseConfiguration;
Landroid/database/sqlite/SQLiteDatabase;->mConnectionPoolLocked:Landroid/database/sqlite/SQLiteConnectionPool;
Landroid/database/sqlite/SQLiteDebug$PagerStats;->largestMemAlloc:I
Landroid/database/sqlite/SQLiteDebug$PagerStats;->memoryUsed:I
Landroid/database/sqlite/SQLiteDebug$PagerStats;->pageCacheOverflow:I
Landroid/database/sqlite/SQLiteOpenHelper;->mName:Ljava/lang/String;
+Landroid/database/sqlite/SQLiteStatement;-><init>(Landroid/database/sqlite/SQLiteDatabase;Ljava/lang/String;[Ljava/lang/Object;)V
Landroid/ddm/DdmHandleAppName;->getAppName()Ljava/lang/String;
Landroid/graphics/AvoidXfermode$Mode;->AVOID:Landroid/graphics/AvoidXfermode$Mode;
Landroid/graphics/AvoidXfermode$Mode;->TARGET:Landroid/graphics/AvoidXfermode$Mode;
@@ -743,6 +763,7 @@
Landroid/graphics/drawable/Icon;->hasTint()Z
Landroid/graphics/drawable/Icon;->mType:I
Landroid/graphics/drawable/InsetDrawable;->mState:Landroid/graphics/drawable/InsetDrawable$InsetState;
+Landroid/graphics/drawable/LayerDrawable;->mLayerState:Landroid/graphics/drawable/LayerDrawable$LayerState;
Landroid/graphics/drawable/NinePatchDrawable;->mNinePatchState:Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;
Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;->mNinePatch:Landroid/graphics/NinePatch;
Landroid/graphics/drawable/StateListDrawable;->extractStateSet(Landroid/util/AttributeSet;)[I
@@ -774,6 +795,7 @@
Landroid/graphics/PixelXorXfermode;-><init>(I)V
Landroid/graphics/PorterDuffColorFilter;->setColor(I)V
Landroid/graphics/PorterDuffColorFilter;->setMode(Landroid/graphics/PorterDuff$Mode;)V
+Landroid/graphics/Rect;->scale(F)V
Landroid/graphics/Region;-><init>(JI)V
Landroid/graphics/Region;->mNativeRegion:J
Landroid/graphics/SurfaceTexture;->mFrameAvailableListener:J
@@ -1019,6 +1041,7 @@
Landroid/media/AudioSystem;->errorCallbackFromNative(I)V
Landroid/media/AudioSystem;->getPrimaryOutputFrameCount()I
Landroid/media/AudioSystem;->getPrimaryOutputSamplingRate()I
+Landroid/media/AudioSystem;->isSourceActive(I)Z
Landroid/media/AudioSystem;->isStreamActive(II)Z
Landroid/media/AudioSystem;->recordingCallbackFromNative(IIII[I)V
Landroid/media/AudioSystem;->setDeviceConnectionState(IILjava/lang/String;Ljava/lang/String;)I
@@ -1046,11 +1069,13 @@
Landroid/media/MediaCodec;->getBuffers(Z)[Ljava/nio/ByteBuffer;
Landroid/media/MediaCodec;->releaseOutputBuffer(IZZJ)V
Landroid/media/MediaFile;->FIRST_AUDIO_FILE_TYPE:I
+Landroid/media/MediaFile;->getFileTypeForMimeType(Ljava/lang/String;)I
Landroid/media/MediaFile;->getFileType(Ljava/lang/String;)Landroid/media/MediaFile$MediaFileType;
Landroid/media/MediaFile;->getMimeTypeForFile(Ljava/lang/String;)Ljava/lang/String;
Landroid/media/MediaFile;-><init>()V
Landroid/media/MediaFile;->isAudioFileType(I)Z
Landroid/media/MediaFile;->isImageFileType(I)Z
+Landroid/media/MediaFile;->isPlayListFileType(I)Z
Landroid/media/MediaFile;->isVideoFileType(I)Z
Landroid/media/MediaFile;->LAST_AUDIO_FILE_TYPE:I
Landroid/media/MediaFile$MediaFileType;->fileType:I
@@ -1067,6 +1092,7 @@
Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)V
Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;)V
Landroid/media/MediaPlayer;->setRetransmitEndpoint(Ljava/net/InetSocketAddress;)V
+Landroid/media/MediaRecorder;->setParameter(Ljava/lang/String;)V
Landroid/media/MediaRouter$RouteInfo;->getStatusCode()I
Landroid/media/MediaRouter$RouteInfo;->STATUS_CONNECTING:I
Landroid/media/MediaRouter;->selectRouteInt(ILandroid/media/MediaRouter$RouteInfo;Z)V
@@ -1137,8 +1163,10 @@
Landroid/net/ConnectivityManager;->isNetworkSupported(I)Z
Landroid/net/ConnectivityManager;->isNetworkTypeMobile(I)Z
Landroid/net/ConnectivityManager;->mService:Landroid/net/IConnectivityManager;
+Landroid/net/ConnectivityManager;->registerNetworkFactory(Landroid/os/Messenger;Ljava/lang/String;)V
Landroid/net/ConnectivityManager;->requestRouteToHostAddress(ILjava/net/InetAddress;)Z
Landroid/net/ConnectivityManager;->requestRouteToHost(II)Z
+Landroid/net/ConnectivityManager;->setBackgroundDataSetting(Z)V
Landroid/net/ConnectivityManager;->TYPE_MOBILE_CBS:I
Landroid/net/ConnectivityManager;->TYPE_MOBILE_EMERGENCY:I
Landroid/net/ConnectivityManager;->TYPE_MOBILE_FOTA:I
@@ -1208,6 +1236,9 @@
Landroid/net/SSLCertificateSocketFactory;->TAG:Ljava/lang/String;
Landroid/net/SSLCertificateSocketFactory;->verifyHostname(Ljava/net/Socket;Ljava/lang/String;)V
Landroid/net/SSLSessionCache;->mSessionCache:Lcom/android/org/conscrypt/SSLClientSessionCache;
+Landroid/net/StaticIpConfiguration;->gateway:Ljava/net/InetAddress;
+Landroid/net/StaticIpConfiguration;-><init>()V
+Landroid/net/StaticIpConfiguration;->ipAddress:Landroid/net/LinkAddress;
Landroid/net/TrafficStats;->getMobileIfaces()[Ljava/lang/String;
Landroid/net/TrafficStats;->getRxBytes(Ljava/lang/String;)J
Landroid/net/TrafficStats;->getStatsService()Landroid/net/INetworkStatsService;
@@ -1220,11 +1251,11 @@
Landroid/net/wifi/p2p/WifiP2pGroup;->TEMPORARY_NET_ID:I
Landroid/net/wifi/p2p/WifiP2pManager$Channel;->mAsyncChannel:Lcom/android/internal/util/AsyncChannel;
Landroid/net/wifi/p2p/WifiP2pManager$Channel;->putListener(Ljava/lang/Object;)I
+Landroid/net/wifi/p2p/WifiP2pManager;->CREATE_GROUP:I
Landroid/net/wifi/p2p/WifiP2pManager;->deletePersistentGroup(Landroid/net/wifi/p2p/WifiP2pManager$Channel;ILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
Landroid/net/wifi/p2p/WifiP2pManager;->requestPersistentGroupInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pManager$PersistentGroupInfoListener;)V
Landroid/net/wifi/p2p/WifiP2pManager;->setDeviceName(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Ljava/lang/String;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
Landroid/net/wifi/p2p/WifiP2pManager;->setWifiP2pChannels(Landroid/net/wifi/p2p/WifiP2pManager$Channel;IILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
-Landroid/net/wifi/p2p/WifiP2pManager;->CREATE_GROUP:I
Landroid/net/wifi/ScanResult;->anqpDomainId:I
Landroid/net/wifi/ScanResult;->anqpLines:Ljava/util/List;
Landroid/net/wifi/ScanResult;->distanceCm:I
@@ -1256,6 +1287,8 @@
Landroid/net/wifi/WifiConfiguration;->defaultGwMacAddress:Ljava/lang/String;
Landroid/net/wifi/WifiConfiguration;->lastConnectUid:I
Landroid/net/wifi/WifiConfiguration;->mIpConfiguration:Landroid/net/IpConfiguration;
+Landroid/net/wifi/WifiConfiguration;->setIpAssignment(Landroid/net/IpConfiguration$IpAssignment;)V
+Landroid/net/wifi/WifiConfiguration;->setStaticIpConfiguration(Landroid/net/StaticIpConfiguration;)V
Landroid/net/wifi/WifiConfiguration;->validatedInternetAccess:Z
Landroid/net/wifi/WifiEnterpriseConfig;->getCaCertificateAlias()Ljava/lang/String;
Landroid/net/wifi/WifiEnterpriseConfig;->getClientCertificateAlias()Ljava/lang/String;
@@ -1275,6 +1308,7 @@
Landroid/opengl/GLSurfaceView$EglHelper;->mEglContext:Ljavax/microedition/khronos/egl/EGLContext;
Landroid/opengl/GLSurfaceView$GLThread;->mEglHelper:Landroid/opengl/GLSurfaceView$EglHelper;
Landroid/opengl/GLSurfaceView;->mGLThread:Landroid/opengl/GLSurfaceView$GLThread;
+Landroid/opengl/GLSurfaceView;->mRenderer:Landroid/opengl/GLSurfaceView$Renderer;
Landroid/os/AsyncTask;->mFuture:Ljava/util/concurrent/FutureTask;
Landroid/os/AsyncTask;->mStatus:Landroid/os/AsyncTask$Status;
Landroid/os/AsyncTask;->mTaskInvoked:Ljava/util/concurrent/atomic/AtomicBoolean;
@@ -1283,6 +1317,7 @@
Landroid/os/AsyncTask;->setDefaultExecutor(Ljava/util/concurrent/Executor;)V
Landroid/os/BatteryStats$Counter;->getCountLocked(I)I
Landroid/os/BatteryStats;->getUidStats()Landroid/util/SparseArray;
+Landroid/os/BatteryStats$HistoryItem;->CMD_UPDATE:B
Landroid/os/BatteryStats$HistoryItem;->states2:I
Landroid/os/BatteryStats;->NUM_DATA_CONNECTION_TYPES:I
Landroid/os/BatteryStats;->startIteratingHistoryLocked()Z
@@ -1502,7 +1537,6 @@
Landroid/os/UserHandle;->MU_ENABLED:Z
Landroid/os/UserHandle;->OWNER:Landroid/os/UserHandle;
Landroid/os/UserHandle;->PER_USER_RANGE:I
-Landroid/os/UserHandle;->SYSTEM:Landroid/os/UserHandle;
Landroid/os/UserHandle;->USER_ALL:I
Landroid/os/UserHandle;->USER_CURRENT:I
Landroid/os/UserHandle;->USER_CURRENT_OR_SELF:I
@@ -1591,6 +1625,7 @@
Landroid/provider/Browser;->clearSearches(Landroid/content/ContentResolver;)V
Landroid/provider/Browser;->deleteFromHistory(Landroid/content/ContentResolver;Ljava/lang/String;)V
Landroid/provider/Browser;->getVisitedHistory(Landroid/content/ContentResolver;)[Ljava/lang/String;
+Landroid/provider/Browser;->HISTORY_PROJECTION:[Ljava/lang/String;
Landroid/provider/Browser;->SEARCHES_URI:Landroid/net/Uri;
Landroid/provider/Browser;->sendString(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
Landroid/provider/Browser;->updateVisitedHistory(Landroid/content/ContentResolver;Ljava/lang/String;Z)V
@@ -1894,6 +1929,7 @@
Landroid/system/OsConstants;->XATTR_CREATE:I
Landroid/system/OsConstants;->XATTR_REPLACE:I
Landroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
+Landroid/telecom/AudioState;->isMuted:Z
Landroid/telecom/TelecomManager;->EXTRA_IS_HANDOVER:Ljava/lang/String;
Landroid/telecom/TelecomManager;->getUserSelectedOutgoingPhoneAccount()Landroid/telecom/PhoneAccountHandle;
Landroid/telecom/TelecomManager;->setUserSelectedOutgoingPhoneAccount(Landroid/telecom/PhoneAccountHandle;)V
@@ -1928,6 +1964,8 @@
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_MODERATE:I
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_NONE_OR_UNKNOWN:I
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I
+Landroid/telephony/SmsManager;->sendMultipartTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;Ljava/util/ArrayList;Ljava/util/ArrayList;IZI)V
+Landroid/telephony/SmsManager;->sendTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;IZI)V
Landroid/telephony/SmsMessage;->getSubId()I
Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase;
Landroid/telephony/SubscriptionManager;->getActiveSubscriptionIdList()[I
@@ -2022,6 +2060,7 @@
Landroid/text/SpannableStringInternal;->setSpan(Ljava/lang/Object;IIIZ)V
Landroid/text/SpannableStringInternal;->START:I
Landroid/text/SpanSet;->spans:[Ljava/lang/Object;
+Landroid/text/StaticLayout;->getHeight(Z)I
Landroid/text/StaticLayout;-><init>(Ljava/lang/CharSequence;IILandroid/text/TextPaint;ILandroid/text/Layout$Alignment;Landroid/text/TextDirectionHeuristic;FFZLandroid/text/TextUtils$TruncateAt;II)V
Landroid/text/StaticLayout$LineBreaks;->ascents:[F
Landroid/text/StaticLayout$LineBreaks;->breaks:[I
@@ -2080,17 +2119,22 @@
Landroid/view/accessibility/AccessibilityManager;->mIsHighTextContrastEnabled:Z
Landroid/view/accessibility/AccessibilityManager;->sInstance:Landroid/view/accessibility/AccessibilityManager;
Landroid/view/accessibility/AccessibilityManager;->sInstanceSync:Ljava/lang/Object;
+Landroid/view/accessibility/AccessibilityNodeInfo;->isSealed()Z
+Landroid/view/accessibility/AccessibilityNodeInfo;->mChildNodeIds:Landroid/util/LongArray;
Landroid/view/accessibility/AccessibilityNodeInfo;->refresh(Landroid/os/Bundle;Z)Z
+Landroid/view/accessibility/AccessibilityNodeInfo;->setSealed(Z)V
Landroid/view/accessibility/AccessibilityRecord;->getSourceNodeId()J
Landroid/view/accessibility/IAccessibilityManager;->getEnabledAccessibilityServiceList(II)Ljava/util/List;
Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/accessibility/IAccessibilityManager;
Landroid/view/accessibility/IAccessibilityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/view/animation/Animation;->initializeInvalidateRegion(IIII)V
Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener;
Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/view/Choreographer$CallbackQueue;->addCallbackLocked(JLjava/lang/Object;Ljava/lang/Object;)V
Landroid/view/Choreographer;->doFrame(JI)V
Landroid/view/Choreographer;->getFrameTime()J
Landroid/view/Choreographer;->mCallbackQueues:[Landroid/view/Choreographer$CallbackQueue;
+Landroid/view/Choreographer;->mFrameIntervalNanos:J
Landroid/view/Choreographer;->mLastFrameTimeNanos:J
Landroid/view/Choreographer;->mLock:Ljava/lang/Object;
Landroid/view/Choreographer;->scheduleVsyncLocked()V
@@ -2226,13 +2270,15 @@
Landroid/view/Surface;->mLock:Ljava/lang/Object;
Landroid/view/Surface;->mNativeObject:J
Landroid/view/SurfaceSession;->mNativeClient:J
+Landroid/view/Surface;->transferFrom(Landroid/view/Surface;)V
+Landroid/view/SurfaceView;->isFixedSize()Z
Landroid/view/SurfaceView;->mCallbacks:Ljava/util/ArrayList;
Landroid/view/SurfaceView;->mFormat:I
Landroid/view/SurfaceView;->mRequestedFormat:I
Landroid/view/SurfaceView;->mSurfaceHolder:Landroid/view/SurfaceHolder;
+Landroid/view/SurfaceView;->setFrame(IIII)Z
Landroid/view/SurfaceView;->surfacePositionLost_uiRtSync(J)V
Landroid/view/SurfaceView;->updateSurfacePosition_renderWorker(JIIII)V
-Landroid/view/textclassifier/Logger;->DISABLED:Landroid/view/textclassifier/Logger;
Landroid/view/textclassifier/logging/SmartSelectionEventTracker;-><init>(Landroid/content/Context;I)V
Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->logEvent(Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;)V
Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(III)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
@@ -2275,6 +2321,7 @@
Landroid/view/View;->dispatchDetachedFromWindow()V
Landroid/view/View;->fitsSystemWindows()Z
Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate;
+Landroid/view/View;->getAccessibilityViewId()I
Landroid/view/View;->getBoundsOnScreen(Landroid/graphics/Rect;)V
Landroid/view/View;->getHorizontalScrollFactor()F
Landroid/view/View;->getInverseMatrix()Landroid/graphics/Matrix;
@@ -2300,6 +2347,7 @@
Landroid/view/ViewGroup;->mOnHierarchyChangeListener:Landroid/view/ViewGroup$OnHierarchyChangeListener;
Landroid/view/ViewGroup;->mPersistentDrawingCache:I
Landroid/view/ViewGroup;->offsetChildrenTopAndBottom(I)V
+Landroid/view/ViewGroup;->onChildVisibilityChanged(Landroid/view/View;II)V
Landroid/view/ViewGroup;->resetResolvedDrawables()V
Landroid/view/ViewGroup;->resetResolvedLayoutDirection()V
Landroid/view/ViewGroup;->resetResolvedPadding()V
@@ -2310,6 +2358,7 @@
Landroid/view/View;->initializeScrollbars(Landroid/content/res/TypedArray;)V
Landroid/view/View;->internalSetPadding(IIII)V
Landroid/view/View;->isPaddingResolved()Z
+Landroid/view/View;->isRootNamespace()Z
Landroid/view/View;->isVisibleToUser(Landroid/graphics/Rect;)Z
Landroid/view/View;->isVisibleToUser()Z
Landroid/view/View$ListenerInfo;-><init>()V
@@ -2332,6 +2381,7 @@
Landroid/view/View;->mPaddingRight:I
Landroid/view/View;->mPaddingTop:I
Landroid/view/View;->mParent:Landroid/view/ViewParent;
+Landroid/view/View;->mPrivateFlags2:I
Landroid/view/View;->mPrivateFlags3:I
Landroid/view/View;->mPrivateFlags:I
Landroid/view/View;->mRecreateDisplayList:Z
@@ -2412,8 +2462,31 @@
Landroid/view/Window;->mContext:Landroid/content/Context;
Landroid/view/Window;->mHardwareAccelerated:Z
Landroid/view/Window;->mWindowStyle:Landroid/content/res/TypedArray;
+Landroid/webkit/CacheManager;->cacheDisabled()Z
+Landroid/webkit/CacheManager$CacheResult;->getContentDisposition()Ljava/lang/String;
+Landroid/webkit/CacheManager$CacheResult;->getContentLength()J
+Landroid/webkit/CacheManager$CacheResult;->getEncoding()Ljava/lang/String;
+Landroid/webkit/CacheManager$CacheResult;->getETag()Ljava/lang/String;
+Landroid/webkit/CacheManager$CacheResult;->getExpires()J
+Landroid/webkit/CacheManager$CacheResult;->getExpiresString()Ljava/lang/String;
+Landroid/webkit/CacheManager$CacheResult;->getHttpStatusCode()I
+Landroid/webkit/CacheManager$CacheResult;->getInputStream()Ljava/io/InputStream;
+Landroid/webkit/CacheManager$CacheResult;->getLastModified()Ljava/lang/String;
+Landroid/webkit/CacheManager$CacheResult;->getLocalPath()Ljava/lang/String;
+Landroid/webkit/CacheManager$CacheResult;->getLocation()Ljava/lang/String;
+Landroid/webkit/CacheManager$CacheResult;->getMimeType()Ljava/lang/String;
+Landroid/webkit/CacheManager$CacheResult;->getOutputStream()Ljava/io/OutputStream;
+Landroid/webkit/CacheManager$CacheResult;-><init>()V
+Landroid/webkit/CacheManager$CacheResult;->setEncoding(Ljava/lang/String;)V
+Landroid/webkit/CacheManager$CacheResult;->setInputStream(Ljava/io/InputStream;)V
+Landroid/webkit/CacheManager;->endCacheTransaction()Z
+Landroid/webkit/CacheManager;->getCacheFileBaseDir()Ljava/io/File;
+Landroid/webkit/CacheManager;->getCacheFile(Ljava/lang/String;Ljava/util/Map;)Landroid/webkit/CacheManager$CacheResult;
+Landroid/webkit/CacheManager;->saveCacheFile(Ljava/lang/String;Landroid/webkit/CacheManager$CacheResult;)V
+Landroid/webkit/CacheManager;->startCacheTransaction()Z
Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/webkit/WebResourceResponse;->mImmutable:Z
+Landroid/webkit/WebSettings$TextSize;->value:I
Landroid/webkit/WebSyncManager;->mHandler:Landroid/os/Handler;
Landroid/webkit/WebViewClient;->onUnhandledInputEvent(Landroid/webkit/WebView;Landroid/view/InputEvent;)V
Landroid/webkit/WebView;->debugDump()V
@@ -2424,11 +2497,13 @@
Landroid/webkit/WebViewFactory;->getWebViewContextAndSetProvider()Landroid/content/Context;
Landroid/webkit/WebViewFactory;->sPackageInfo:Landroid/content/pm/PackageInfo;
Landroid/webkit/WebViewFactory;->sProviderInstance:Landroid/webkit/WebViewFactoryProvider;
+Landroid/webkit/WebView;->getContentWidth()I
Landroid/webkit/WebView;->getTouchIconUrl()Ljava/lang/String;
Landroid/webkit/WebView;->getVisibleTitleHeight()I
Landroid/webkit/WebView;->isPaused()Z
Landroid/webkit/WebView;->mProvider:Landroid/webkit/WebViewProvider;
Landroid/webkit/WebView;->notifyFindDialogDismissed()V
+Landroid/webkit/WebView;->onDrawVerticalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
Landroid/webkit/WebView;->restorePicture(Landroid/os/Bundle;Ljava/io/File;)Z
Landroid/webkit/WebView;->savePicture(Landroid/os/Bundle;Ljava/io/File;)Z
Landroid/webkit/WebView;->sEnforceThreadChecking:Z
@@ -2443,6 +2518,7 @@
Landroid/widget/AbsListView;->mFastScroll:Landroid/widget/FastScroller;
Landroid/widget/AbsListView;->mFlingRunnable:Landroid/widget/AbsListView$FlingRunnable;
Landroid/widget/AbsListView;->mIsChildViewEnabled:Z
+Landroid/widget/AbsListView;->mLayoutMode:I
Landroid/widget/AbsListView;->mMaximumVelocity:I
Landroid/widget/AbsListView;->mMotionPosition:I
Landroid/widget/AbsListView;->mOnScrollListener:Landroid/widget/AbsListView$OnScrollListener;
@@ -2472,6 +2548,8 @@
Landroid/widget/ActivityChooserView;->setExpandActivityOverflowButtonDrawable(Landroid/graphics/drawable/Drawable;)V
Landroid/widget/AdapterView;->mDataChanged:Z
Landroid/widget/AdapterView;->mFirstPosition:I
+Landroid/widget/AdapterView;->mNextSelectedPosition:I
+Landroid/widget/AdapterView;->mNextSelectedRowId:J
Landroid/widget/AdapterView;->mOldSelectedPosition:I
Landroid/widget/AdapterView;->setNextSelectedPositionInt(I)V
Landroid/widget/AdapterView;->setSelectedPositionInt(I)V
@@ -2481,6 +2559,7 @@
Landroid/widget/AutoCompleteTextView;->mPopup:Landroid/widget/ListPopupWindow;
Landroid/widget/AutoCompleteTextView;->setDropDownAlwaysVisible(Z)V
Landroid/widget/AutoCompleteTextView;->setForceIgnoreOutsideTouch(Z)V
+Landroid/widget/BaseAdapter;->mDataSetObservable:Landroid/database/DataSetObservable;
Landroid/widget/CompoundButton;->mButtonDrawable:Landroid/graphics/drawable/Drawable;
Landroid/widget/CompoundButton;->mOnCheckedChangeListener:Landroid/widget/CompoundButton$OnCheckedChangeListener;
Landroid/widget/CursorAdapter;->mChangeObserver:Landroid/widget/CursorAdapter$ChangeObserver;
@@ -2522,6 +2601,7 @@
Landroid/widget/HorizontalScrollView;->mEdgeGlowLeft:Landroid/widget/EdgeEffect;
Landroid/widget/HorizontalScrollView;->mEdgeGlowRight:Landroid/widget/EdgeEffect;
Landroid/widget/HorizontalScrollView;->mScroller:Landroid/widget/OverScroller;
+Landroid/widget/ImageView;->animateTransform(Landroid/graphics/Matrix;)V
Landroid/widget/ImageView;->mAdjustViewBounds:Z
Landroid/widget/ImageView;->mAlpha:I
Landroid/widget/ImageView;->mDrawMatrix:Landroid/graphics/Matrix;
@@ -2729,6 +2809,10 @@
Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setFeatureTag(Ljava/lang/String;)V
Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setTimestamp(Ljava/lang/String;)V
Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
+Lcom/android/internal/app/AlertController;->mCustomTitleView:Landroid/view/View;
+Lcom/android/internal/app/AlertController;->mForceInverseBackground:Z
+Lcom/android/internal/app/AlertController;->mTitle:Ljava/lang/CharSequence;
+Lcom/android/internal/app/AlertController;->mView:Landroid/view/View;
Lcom/android/internal/app/AlertController$RecycleListView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
Lcom/android/internal/app/IAppOpsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IAppOpsService;
Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
@@ -3000,6 +3084,8 @@
Lcom/android/internal/telephony/ITelephony;->getCallState()I
Lcom/android/internal/telephony/ITelephony;->getDataState()I
Lcom/android/internal/telephony/ITelephony;->isIdle(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallState(ILjava/lang/String;)V
+Lcom/android/internal/telephony/ITelephonyRegistry$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephonyRegistry;
Lcom/android/internal/telephony/ITelephony;->silenceRinger()V
Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephony;
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->endCall()Z
@@ -3183,6 +3269,7 @@
Ljava/lang/Double;->value:D
Ljava/lang/Float;->value:F
Ljava/lang/Integer;->value:I
+Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;I)V
Ljava/lang/Long;->value:J
Ljava/lang/ref/FinalizerReference;->add(Ljava/lang/Object;)V
Ljava/lang/ref/FinalizerReference;->head:Ljava/lang/ref/FinalizerReference;
@@ -3196,6 +3283,7 @@
Ljava/lang/ref/Reference;->referent:Ljava/lang/Object;
Ljava/lang/Runtime;->loadLibrary(Ljava/lang/String;Ljava/lang/ClassLoader;)V
Ljava/lang/Runtime;->load(Ljava/lang/String;Ljava/lang/ClassLoader;)V
+Ljava/lang/Runtime;->mLibPaths:[Ljava/lang/String;
Ljava/lang/Runtime;->nativeLoad(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/String;
Ljava/lang/Short;->value:S
Ljava/lang/String;-><init>(II[C)V
@@ -3217,7 +3305,9 @@
Ljava/lang/Thread;->lock:Ljava/lang/Object;
Ljava/lang/Thread;->name:Ljava/lang/String;
Ljava/lang/Thread;->nativePeer:J
+Ljava/lang/Thread;->parkBlocker:Ljava/lang/Object;
Ljava/lang/Thread;->priority:I
+Ljava/lang/Thread;->threadLocals:Ljava/lang/ThreadLocal$ThreadLocalMap;
Ljava/lang/Throwable;->backtrace:Ljava/lang/Object;
Ljava/lang/Throwable;->cause:Ljava/lang/Throwable;
Ljava/lang/Throwable;->detailMessage:Ljava/lang/String;
@@ -3249,7 +3339,10 @@
Ljava/net/Socket;->impl:Ljava/net/SocketImpl;
Ljava/net/SocketImpl;->serverSocket:Ljava/net/ServerSocket;
Ljava/net/SocketImpl;->socket:Ljava/net/Socket;
+Ljava/net/URI;->fragment:Ljava/lang/String;
Ljava/net/URI;->host:Ljava/lang/String;
+Ljava/net/URI;->port:I
+Ljava/net/URI;->string:Ljava/lang/String;
Ljava/net/URL;->handler:Ljava/net/URLStreamHandler;
Ljava/net/URL;->handlers:Ljava/util/Hashtable;
Ljava/nio/Buffer;->address:J
@@ -3270,6 +3363,9 @@
Ljava/text/DateFormat;->is24Hour:Ljava/lang/Boolean;
Ljava/time/Duration;->toSeconds()Ljava/math/BigDecimal;
Ljava/time/OffsetDateTime;-><init>(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;)V
+Ljava/util/ArrayDeque;->elements:[Ljava/lang/Object;
+Ljava/util/ArrayDeque;->head:I
+Ljava/util/ArrayDeque;->tail:I
Ljava/util/ArrayList;->elementData:[Ljava/lang/Object;
Ljava/util/ArrayList;->size:I
Ljava/util/ArrayList$SubList;->parent:Ljava/util/AbstractList;
@@ -3282,22 +3378,37 @@
Ljava/util/Collections$SynchronizedMap;->m:Ljava/util/Map;
Ljava/util/Collections$UnmodifiableCollection;->c:Ljava/util/Collection;
Ljava/util/Collections$UnmodifiableMap;->m:Ljava/util/Map;
+Ljava/util/concurrent/atomic/AtomicInteger;->value:I
Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;->hasMoreElements()Z
+Ljava/util/concurrent/CopyOnWriteArraySet;->al:Ljava/util/concurrent/CopyOnWriteArrayList;
Ljava/util/concurrent/Executors$RunnableAdapter;->task:Ljava/lang/Runnable;
Ljava/util/concurrent/FutureTask;->callable:Ljava/util/concurrent/Callable;
Ljava/util/concurrent/FutureTask;->EXCEPTIONAL:I
Ljava/util/concurrent/FutureTask;->outcome:Ljava/lang/Object;
Ljava/util/concurrent/FutureTask;->state:I
+Ljava/util/concurrent/LinkedBlockingDeque;->first:Ljava/util/concurrent/LinkedBlockingDeque$Node;
+Ljava/util/concurrent/LinkedBlockingDeque;->lock:Ljava/util/concurrent/locks/ReentrantLock;
Ljava/util/concurrent/LinkedBlockingQueue;->capacity:I
+Ljava/util/concurrent/LinkedBlockingQueue;->head:Ljava/util/concurrent/LinkedBlockingQueue$Node;
+Ljava/util/concurrent/LinkedBlockingQueue;->putLock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/LinkedBlockingQueue;->takeLock:Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/ThreadPoolExecutor;->allowCoreThreadTimeOut:Z
Ljava/util/EnumMap;->keyType:Ljava/lang/Class;
Ljava/util/EnumSet;->elementType:Ljava/lang/Class;
Ljava/util/HashMap$HashIterator;->hasNext()Z
+Ljava/util/HashMap;->modCount:I
+Ljava/util/HashMap;->table:[Ljava/util/HashMap$Node;
+Ljava/util/HashSet;->map:Ljava/util/HashMap;
Ljava/util/jar/JarFile;->manifest:Ljava/util/jar/Manifest;
Ljava/util/LinkedHashMap;->eldest()Ljava/util/Map$Entry;
Ljava/util/LinkedHashMap$LinkedHashIterator;->hasNext()Z
+Ljava/util/LinkedList;->size:I
Ljava/util/Locale;->createConstant(Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale;
+Ljava/util/PriorityQueue;->modCount:I
+Ljava/util/PriorityQueue;->size:I
Ljava/util/Random;->seedUniquifier()J
Ljava/util/regex/Matcher;->appendPos:I
+Ljava/util/Vector;->elementData(I)Ljava/lang/Object;
Ljava/util/zip/Deflater;->buf:[B
Ljava/util/zip/Deflater;->finished:Z
Ljava/util/zip/Deflater;->finish:Z
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index f3bc206..b598296 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -312,9 +312,7 @@
Landroid/net/SntpClient;->requestTime(Ljava/lang/String;I)Z
Landroid/net/StaticIpConfiguration;->dnsServers:Ljava/util/ArrayList;
Landroid/net/StaticIpConfiguration;->domains:Ljava/lang/String;
-Landroid/net/StaticIpConfiguration;->gateway:Ljava/net/InetAddress;
Landroid/net/StaticIpConfiguration;->getRoutes(Ljava/lang/String;)Ljava/util/List;
-Landroid/net/StaticIpConfiguration;->ipAddress:Landroid/net/LinkAddress;
Landroid/net/StringNetworkSpecifier;->specifier:Ljava/lang/String;
Landroid/net/TrafficStats;->getMobileTcpRxPackets()J
Landroid/net/TrafficStats;->getMobileTcpTxPackets()J
@@ -717,6 +715,7 @@
Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V
Lcom/android/ims/internal/uce/presence/PresCapInfo;->getCapInfo()Lcom/android/ims/internal/uce/common/CapInfo;
Lcom/android/ims/internal/uce/presence/PresCapInfo;->getContactUri()Ljava/lang/String;
+Lcom/android/ims/internal/uce/presence/PresCapInfo;->mContactUri:Ljava/lang/String;
Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getMediaType()I
Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceDesc()Ljava/lang/String;
Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceId()Ljava/lang/String;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 09dcbf2..ecd99a7 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1139,7 +1139,8 @@
* {@link android.app.admin.DevicePolicyManager} can run in LockTask mode. Therefore, if
* {@link android.app.admin.DevicePolicyManager#isLockTaskPermitted(String)} returns
* {@code false} for the package of the target activity, a {@link SecurityException} will be
- * thrown during {@link Context#startActivity(Intent, Bundle)}.
+ * thrown during {@link Context#startActivity(Intent, Bundle)}. This method doesn't affect
+ * activities that are already running — relaunch the activity to run in lock task mode.
*
* Defaults to {@code false} if not set.
*
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index b6cff38..69c3632 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -32,6 +32,7 @@
private long mTemporaryAppWhitelistDuration;
private int mMinManifestReceiverApiLevel = 0;
private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
+ private boolean mDontSendToRestrictedApps = false;
/**
* How long to temporarily put an app on the power whitelist when executing this broadcast
@@ -52,6 +53,12 @@
static final String KEY_MAX_MANIFEST_RECEIVER_API_LEVEL
= "android:broadcast.maxManifestReceiverApiLevel";
+ /**
+ * Corresponds to {@link #setMaxManifestReceiverApiLevel}.
+ */
+ static final String KEY_DONT_SEND_TO_RESTRICTED_APPS =
+ "android:broadcast.dontSendToRestrictedApps";
+
public static BroadcastOptions makeBasic() {
BroadcastOptions opts = new BroadcastOptions();
return opts;
@@ -66,6 +73,7 @@
mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0);
mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL,
Build.VERSION_CODES.CUR_DEVELOPMENT);
+ mDontSendToRestrictedApps = opts.getBoolean(KEY_DONT_SEND_TO_RESTRICTED_APPS, false);
}
/**
@@ -123,6 +131,23 @@
}
/**
+ * Sets whether pending intent can be sent for an application with background restrictions
+ * @param dontSendToRestrictedApps if true, pending intent will not be sent for an application
+ * with background restrictions. Default value is {@code false}
+ */
+ public void setDontSendToRestrictedApps(boolean dontSendToRestrictedApps) {
+ mDontSendToRestrictedApps = dontSendToRestrictedApps;
+ }
+
+ /**
+ * @hide
+ * @return #setDontSendToRestrictedApps
+ */
+ public boolean isDontSendToRestrictedApps() {
+ return mDontSendToRestrictedApps;
+ }
+
+ /**
* Returns the created options as a Bundle, which can be passed to
* {@link android.content.Context#sendBroadcast(android.content.Intent)
* Context.sendBroadcast(Intent)} and related methods.
@@ -141,6 +166,9 @@
if (mMaxManifestReceiverApiLevel != Build.VERSION_CODES.CUR_DEVELOPMENT) {
b.putInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, mMaxManifestReceiverApiLevel);
}
+ if (mDontSendToRestrictedApps) {
+ b.putBoolean(KEY_DONT_SEND_TO_RESTRICTED_APPS, true);
+ }
return b.isEmpty() ? null : b;
}
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 86fedb1..4ab6724 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3902,7 +3902,7 @@
* @deprecated use {@link #addPerson(Person)}
*/
public Builder addPerson(String uri) {
- addPerson(new Person().setUri(uri));
+ addPerson(new Person.Builder().setUri(uri).build());
return this;
}
@@ -6384,7 +6384,7 @@
* @deprecated use {@code MessagingStyle(Person)}
*/
public MessagingStyle(@NonNull CharSequence userDisplayName) {
- this(new Person().setName(userDisplayName));
+ this(new Person.Builder().setName(userDisplayName).build());
}
/**
@@ -6431,6 +6431,7 @@
/**
* @return the user to be displayed for any replies sent by the user
*/
+ @NonNull
public Person getUser() {
return mUser;
}
@@ -6489,7 +6490,7 @@
*/
public MessagingStyle addMessage(CharSequence text, long timestamp, CharSequence sender) {
return addMessage(text, timestamp,
- sender == null ? null : new Person().setName(sender));
+ sender == null ? null : new Person.Builder().setName(sender).build());
}
/**
@@ -6505,7 +6506,8 @@
*
* @return this object for method chaining
*/
- public MessagingStyle addMessage(CharSequence text, long timestamp, Person sender) {
+ public MessagingStyle addMessage(@NonNull CharSequence text, long timestamp,
+ @Nullable Person sender) {
return addMessage(new Message(text, timestamp, sender));
}
@@ -6661,7 +6663,7 @@
mUser = extras.getParcelable(EXTRA_MESSAGING_PERSON);
if (mUser == null) {
CharSequence displayName = extras.getCharSequence(EXTRA_SELF_DISPLAY_NAME);
- mUser = new Person().setName(displayName);
+ mUser = new Person.Builder().setName(displayName).build();
}
mConversationTitle = extras.getCharSequence(EXTRA_CONVERSATION_TITLE);
Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
@@ -6916,7 +6918,8 @@
* @deprecated use {@code Message(CharSequence, long, Person)}
*/
public Message(CharSequence text, long timestamp, CharSequence sender){
- this(text, timestamp, sender == null ? null : new Person().setName(sender));
+ this(text, timestamp, sender == null ? null
+ : new Person.Builder().setName(sender).build());
}
/**
@@ -6927,13 +6930,14 @@
* Should be <code>null</code> for messages by the current user, in which case
* the platform will insert the user set in {@code MessagingStyle(Person)}.
* <p>
- * The person provided should contain an Icon, set with {@link Person#setIcon(Icon)}
- * and also have a name provided with {@link Person#setName(CharSequence)}. If multiple
- * users have the same name, consider providing a key with {@link Person#setKey(String)}
- * in order to differentiate between the different users.
+ * The person provided should contain an Icon, set with
+ * {@link Person.Builder#setIcon(Icon)} and also have a name provided
+ * with {@link Person.Builder#setName(CharSequence)}. If multiple users have the same
+ * name, consider providing a key with {@link Person.Builder#setKey(String)} in order
+ * to differentiate between the different users.
* </p>
*/
- public Message(CharSequence text, long timestamp, @Nullable Person sender){
+ public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender) {
mText = text;
mTimestamp = timestamp;
mSender = sender;
@@ -7092,7 +7096,7 @@
// the native api instead
CharSequence senderName = bundle.getCharSequence(KEY_SENDER);
if (senderName != null) {
- senderPerson = new Person().setName(senderName);
+ senderPerson = new Person.Builder().setName(senderName).build();
}
}
Message message = new Message(bundle.getCharSequence(KEY_TEXT),
@@ -7787,217 +7791,6 @@
}
}
- /**
- * A Person associated with this Notification.
- */
- public static final class Person implements Parcelable {
- @Nullable private CharSequence mName;
- @Nullable private Icon mIcon;
- @Nullable private String mUri;
- @Nullable private String mKey;
- private boolean mBot;
- private boolean mImportant;
-
- protected Person(Parcel in) {
- mName = in.readCharSequence();
- if (in.readInt() != 0) {
- mIcon = Icon.CREATOR.createFromParcel(in);
- }
- mUri = in.readString();
- mKey = in.readString();
- mImportant = in.readBoolean();
- mBot = in.readBoolean();
- }
-
- /**
- * Create a new person.
- */
- public Person() {
- }
-
- /**
- * Give this person a name.
- *
- * @param name the name of this person
- */
- public Person setName(@Nullable CharSequence name) {
- this.mName = name;
- return this;
- }
-
- /**
- * Add an icon for this person.
- * <br />
- * This is currently only used for {@link MessagingStyle} notifications and should not be
- * provided otherwise, in order to save memory. The system will prefer this icon over any
- * images that are resolved from the URI.
- *
- * @param icon the icon of the person
- */
- public Person setIcon(@Nullable Icon icon) {
- this.mIcon = icon;
- return this;
- }
-
- /**
- * Set a URI associated with this person.
- *
- * <P>
- * Depending on user preferences, adding a URI to a Person may allow the notification to
- * pass through interruption filters, if this notification is of
- * category {@link #CATEGORY_CALL} or {@link #CATEGORY_MESSAGE}.
- * The addition of people may also cause this notification to appear more prominently in
- * the user interface.
- * </P>
- *
- * <P>
- * The person should be specified by the {@code String} representation of a
- * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
- * </P>
- *
- * <P>The system will also attempt to resolve {@code mailto:} and {@code tel:} schema
- * URIs. The path part of these URIs must exist in the contacts database, in the
- * appropriate column, or the reference will be discarded as invalid. Telephone schema
- * URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}.
- * </P>
- *
- * @param uri a URI for the person
- */
- public Person setUri(@Nullable String uri) {
- mUri = uri;
- return this;
- }
-
- /**
- * Add a key to this person in order to uniquely identify it.
- * This is especially useful if the name doesn't uniquely identify this person or if the
- * display name is a short handle of the actual name.
- *
- * <P>If no key is provided, the name serves as as the key for the purpose of
- * identification.</P>
- *
- * @param key the key that uniquely identifies this person
- */
- public Person setKey(@Nullable String key) {
- mKey = key;
- return this;
- }
-
- /**
- * Sets whether this is an important person. Use this method to denote users who frequently
- * interact with the user of this device, when it is not possible to refer to the user
- * by {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
- *
- * @param isImportant {@code true} if this is an important person, {@code false} otherwise.
- */
- public Person setImportant(boolean isImportant) {
- mImportant = isImportant;
- return this;
- }
-
- /**
- * Sets whether this person is a machine rather than a human.
- *
- * @param isBot {@code true} if this person is a machine, {@code false} otherwise.
- */
- public Person setBot(boolean isBot) {
- mBot = isBot;
- return this;
- }
-
- /**
- * @return the uri provided for this person or {@code null} if no Uri was provided
- */
- @Nullable
- public String getUri() {
- return mUri;
- }
-
- /**
- * @return the name provided for this person or {@code null} if no name was provided
- */
- @Nullable
- public CharSequence getName() {
- return mName;
- }
-
- /**
- * @return the icon provided for this person or {@code null} if no icon was provided
- */
- @Nullable
- public Icon getIcon() {
- return mIcon;
- }
-
- /**
- * @return the key provided for this person or {@code null} if no key was provided
- */
- @Nullable
- public String getKey() {
- return mKey;
- }
-
- /**
- * @return whether this Person is a machine.
- */
- public boolean isBot() {
- return mBot;
- }
-
- /**
- * @return whether this Person is important.
- */
- public boolean isImportant() {
- return mImportant;
- }
-
- /**
- * @return the URI associated with this person, or "name:mName" otherwise
- * @hide
- */
- public String resolveToLegacyUri() {
- if (mUri != null) {
- return mUri;
- }
- if (mName != null) {
- return "name:" + mName;
- }
- return "";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, @WriteFlags int flags) {
- dest.writeCharSequence(mName);
- if (mIcon != null) {
- dest.writeInt(1);
- mIcon.writeToParcel(dest, 0);
- } else {
- dest.writeInt(0);
- }
- dest.writeString(mUri);
- dest.writeString(mKey);
- dest.writeBoolean(mImportant);
- dest.writeBoolean(mBot);
- }
-
- public static final Creator<Person> CREATOR = new Creator<Person>() {
- @Override
- public Person createFromParcel(Parcel in) {
- return new Person(in);
- }
-
- @Override
- public Person[] newArray(int size) {
- return new Person[size];
- }
- };
- }
-
// When adding a new Style subclass here, don't forget to update
// Builder.getNotificationStyleClass.
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 46d1264..757fc64 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1145,6 +1145,21 @@
SUPPRESSED_EFFECT_NOTIFICATION_LIST
};
+ private static final int[] SCREEN_OFF_SUPPRESSED_EFFECTS = {
+ SUPPRESSED_EFFECT_SCREEN_OFF,
+ SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
+ SUPPRESSED_EFFECT_LIGHTS,
+ SUPPRESSED_EFFECT_AMBIENT,
+ };
+
+ private static final int[] SCREEN_ON_SUPPRESSED_EFFECTS = {
+ SUPPRESSED_EFFECT_SCREEN_ON,
+ SUPPRESSED_EFFECT_PEEK,
+ SUPPRESSED_EFFECT_STATUS_BAR,
+ SUPPRESSED_EFFECT_BADGE,
+ SUPPRESSED_EFFECT_NOTIFICATION_LIST
+ };
+
/**
* Visual effects to suppress for a notification that is filtered by Do Not Disturb mode.
* Bitmask of SUPPRESSED_EFFECT_* constants.
@@ -1297,6 +1312,58 @@
return true;
}
+ /**
+ * @hide
+ */
+ public static boolean areAnyScreenOffEffectsSuppressed(int effects) {
+ for (int i = 0; i < SCREEN_OFF_SUPPRESSED_EFFECTS.length; i++) {
+ final int effect = SCREEN_OFF_SUPPRESSED_EFFECTS[i];
+ if ((effects & effect) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean areAnyScreenOnEffectsSuppressed(int effects) {
+ for (int i = 0; i < SCREEN_ON_SUPPRESSED_EFFECTS.length; i++) {
+ final int effect = SCREEN_ON_SUPPRESSED_EFFECTS[i];
+ if ((effects & effect) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @hide
+ */
+ public static int toggleScreenOffEffectsSuppressed(int currentEffects, boolean suppress) {
+ return toggleEffects(currentEffects, SCREEN_OFF_SUPPRESSED_EFFECTS, suppress);
+ }
+
+ /**
+ * @hide
+ */
+ public static int toggleScreenOnEffectsSuppressed(int currentEffects, boolean suppress) {
+ return toggleEffects(currentEffects, SCREEN_ON_SUPPRESSED_EFFECTS, suppress);
+ }
+
+ private static int toggleEffects(int currentEffects, int[] effects, boolean suppress) {
+ for (int i = 0; i < effects.length; i++) {
+ final int effect = effects[i];
+ if (suppress) {
+ currentEffects |= effect;
+ } else {
+ currentEffects &= ~effect;
+ }
+ }
+ return currentEffects;
+ }
+
public static String suppressedEffectsToString(int effects) {
if (effects <= 0) return "";
final StringBuilder sb = new StringBuilder();
diff --git a/core/java/android/app/Person.java b/core/java/android/app/Person.java
new file mode 100644
index 0000000..3884a8d
--- /dev/null
+++ b/core/java/android/app/Person.java
@@ -0,0 +1,270 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.drawable.Icon;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Provides an immutable reference to an entity that appears repeatedly on different surfaces of the
+ * platform. For example, this could represent the sender of a message.
+ */
+public final class Person implements Parcelable {
+
+ @Nullable private CharSequence mName;
+ @Nullable private Icon mIcon;
+ @Nullable private String mUri;
+ @Nullable private String mKey;
+ private boolean mIsBot;
+ private boolean mIsImportant;
+
+ private Person(Parcel in) {
+ mName = in.readCharSequence();
+ if (in.readInt() != 0) {
+ mIcon = Icon.CREATOR.createFromParcel(in);
+ }
+ mUri = in.readString();
+ mKey = in.readString();
+ mIsImportant = in.readBoolean();
+ mIsBot = in.readBoolean();
+ }
+
+ private Person(Builder builder) {
+ mName = builder.mName;
+ mIcon = builder.mIcon;
+ mUri = builder.mUri;
+ mKey = builder.mKey;
+ mIsBot = builder.mIsBot;
+ mIsImportant = builder.mIsImportant;
+ }
+
+ /** Creates and returns a new {@link Builder} initialized with this Person's data. */
+ public Builder toBuilder() {
+ return new Builder(this);
+ }
+
+ /**
+ * @return the uri provided for this person or {@code null} if no Uri was provided.
+ */
+ @Nullable
+ public String getUri() {
+ return mUri;
+ }
+
+ /**
+ * @return the name provided for this person or {@code null} if no name was provided.
+ */
+ @Nullable
+ public CharSequence getName() {
+ return mName;
+ }
+
+ /**
+ * @return the icon provided for this person or {@code null} if no icon was provided.
+ */
+ @Nullable
+ public Icon getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * @return the key provided for this person or {@code null} if no key was provided.
+ */
+ @Nullable
+ public String getKey() {
+ return mKey;
+ }
+
+ /**
+ * @return whether this Person is a machine.
+ */
+ public boolean isBot() {
+ return mIsBot;
+ }
+
+ /**
+ * @return whether this Person is important.
+ */
+ public boolean isImportant() {
+ return mIsImportant;
+ }
+
+ /**
+ * @return the URI associated with this person, or "name:mName" otherwise
+ * @hide
+ */
+ public String resolveToLegacyUri() {
+ if (mUri != null) {
+ return mUri;
+ }
+ if (mName != null) {
+ return "name:" + mName;
+ }
+ return "";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, @WriteFlags int flags) {
+ dest.writeCharSequence(mName);
+ if (mIcon != null) {
+ dest.writeInt(1);
+ mIcon.writeToParcel(dest, 0);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeString(mUri);
+ dest.writeString(mKey);
+ dest.writeBoolean(mIsImportant);
+ dest.writeBoolean(mIsBot);
+ }
+
+ /** Builder for the immutable {@link Person} class. */
+ public static class Builder {
+ @Nullable private CharSequence mName;
+ @Nullable private Icon mIcon;
+ @Nullable private String mUri;
+ @Nullable private String mKey;
+ private boolean mIsBot;
+ private boolean mIsImportant;
+
+ /** Creates a new, empty {@link Builder}. */
+ public Builder() {
+ }
+
+ private Builder(Person person) {
+ mName = person.mName;
+ mIcon = person.mIcon;
+ mUri = person.mUri;
+ mKey = person.mKey;
+ mIsBot = person.mIsBot;
+ mIsImportant = person.mIsImportant;
+ }
+
+ /**
+ * Give this person a name.
+ *
+ * @param name the name of this person.
+ */
+ @NonNull
+ public Person.Builder setName(@Nullable CharSequence name) {
+ this.mName = name;
+ return this;
+ }
+
+ /**
+ * Add an icon for this person.
+ * <br />
+ * The system will prefer this icon over any images that are resolved from the URI.
+ *
+ * @param icon the icon of the person.
+ */
+ @NonNull
+ public Person.Builder setIcon(@Nullable Icon icon) {
+ this.mIcon = icon;
+ return this;
+ }
+
+ /**
+ * Set a URI associated with this person.
+ *
+ * <P>
+ * The person should be specified by the {@code String} representation of a
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
+ * </P>
+ *
+ * <P>The system will also attempt to resolve {@code mailto:} and {@code tel:} schema
+ * URIs. The path part of these URIs must exist in the contacts database, in the
+ * appropriate column, or the reference will be discarded as invalid. Telephone schema
+ * URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}.
+ * </P>
+ *
+ * @param uri a URI for the person.
+ */
+ @NonNull
+ public Person.Builder setUri(@Nullable String uri) {
+ mUri = uri;
+ return this;
+ }
+
+ /**
+ * Add a key to this person in order to uniquely identify it.
+ * This is especially useful if the name doesn't uniquely identify this person or if the
+ * display name is a short handle of the actual name.
+ *
+ * <P>If no key is provided, the name serves as the key for the purpose of
+ * identification.</P>
+ *
+ * @param key the key that uniquely identifies this person.
+ */
+ @NonNull
+ public Person.Builder setKey(@Nullable String key) {
+ mKey = key;
+ return this;
+ }
+
+ /**
+ * Sets whether this is an important person. Use this method to denote users who frequently
+ * interact with the user of this device when {@link #setUri(String)} isn't provided with
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}, and instead with
+ * the {@code mailto:} or {@code tel:} schemas.
+ *
+ * @param isImportant {@code true} if this is an important person, {@code false} otherwise.
+ */
+ @NonNull
+ public Person.Builder setImportant(boolean isImportant) {
+ mIsImportant = isImportant;
+ return this;
+ }
+
+ /**
+ * Sets whether this person is a machine rather than a human.
+ *
+ * @param isBot {@code true} if this person is a machine, {@code false} otherwise.
+ */
+ @NonNull
+ public Person.Builder setBot(boolean isBot) {
+ mIsBot = isBot;
+ return this;
+ }
+
+ /** Creates and returns the {@link Person} this builder represents. */
+ @NonNull
+ public Person build() {
+ return new Person(this);
+ }
+ }
+
+ public static final Creator<Person> CREATOR = new Creator<Person>() {
+ @Override
+ public Person createFromParcel(Parcel in) {
+ return new Person(in);
+ }
+
+ @Override
+ public Person[] newArray(int size) {
+ return new Person[size];
+ }
+ };
+}
diff --git a/core/java/android/app/RemoteAction.java b/core/java/android/app/RemoteAction.java
index 47741c0..c174665 100644
--- a/core/java/android/app/RemoteAction.java
+++ b/core/java/android/app/RemoteAction.java
@@ -122,6 +122,7 @@
public RemoteAction clone() {
RemoteAction action = new RemoteAction(mIcon, mTitle, mContentDescription, mActionIntent);
action.setEnabled(mEnabled);
+ action.setShouldShowIcon(mShouldShowIcon);
return action;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 3ee1ed5..246d4a3 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -105,10 +105,12 @@
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Build;
+import android.os.DeviceIdleManager;
import android.os.DropBoxManager;
import android.os.HardwarePropertiesManager;
import android.os.IBatteryPropertiesRegistrar;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.IHardwarePropertiesManager;
import android.os.IPowerManager;
import android.os.IRecoverySystem;
@@ -984,6 +986,17 @@
ctx.mMainThread.getHandler());
}
});
+
+ registerService(Context.DEVICE_IDLE_CONTROLLER, DeviceIdleManager.class,
+ new CachedServiceFetcher<DeviceIdleManager>() {
+ @Override
+ public DeviceIdleManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IDeviceIdleController service = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(
+ Context.DEVICE_IDLE_CONTROLLER));
+ return new DeviceIdleManager(ctx.getOuterContext(), service);
+ }});
}
/**
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 465340f..17bc6ea 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -401,7 +401,8 @@
}
}
synchronized (this) {
- if (mCachedWallpaper != null && mCachedWallpaperUserId == userId) {
+ if (mCachedWallpaper != null && mCachedWallpaperUserId == userId
+ && !mCachedWallpaper.isRecycled()) {
return mCachedWallpaper;
}
mCachedWallpaper = null;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8f1b328..990147b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6198,6 +6198,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public @Nullable List<String> getPermittedAccessibilityServices(int userId) {
throwIfParentInstance("getPermittedAccessibilityServices");
if (mService != null) {
diff --git a/core/java/android/app/admin/FreezeInterval.java b/core/java/android/app/admin/FreezePeriod.java
similarity index 74%
rename from core/java/android/app/admin/FreezeInterval.java
rename to core/java/android/app/admin/FreezePeriod.java
index de5e21a..657f017 100644
--- a/core/java/android/app/admin/FreezeInterval.java
+++ b/core/java/android/app/admin/FreezePeriod.java
@@ -20,49 +20,88 @@
import android.util.Pair;
import java.time.LocalDate;
+import java.time.MonthDay;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
/**
- * An interval representing one freeze period which repeats annually. We use the number of days
- * since the start of (non-leap) year to define the start and end dates of an interval, both
- * inclusive. If the end date is smaller than the start date, the interval is considered wrapped
- * around the year-end. As far as an interval is concerned, February 29th should be treated as
- * if it were February 28th: so an interval starting or ending on February 28th are not
- * distinguishable from an interval on February 29th. When calulating interval length or
- * distance between two dates, February 29th is also disregarded.
+ * A class that represents one freeze period which repeats <em>annually</em>. A freeze period has
+ * two {@link java.time#MonthDay} values that define the start and end dates of the period, both
+ * inclusive. If the end date is earlier than the start date, the period is considered wrapped
+ * around the year-end. As far as freeze period is concerned, leap year is disregarded and February
+ * 29th should be treated as if it were February 28th: so a freeze starting or ending on February
+ * 28th is identical to a freeze starting or ending on February 29th. When calulating the length of
+ * a freeze or the distance bewteen two freee periods, February 29th is also ignored.
*
* @see SystemUpdatePolicy#setFreezePeriods
- * @hide
*/
-public class FreezeInterval {
- private static final String TAG = "FreezeInterval";
+public class FreezePeriod {
+ private static final String TAG = "FreezePeriod";
private static final int DUMMY_YEAR = 2001;
static final int DAYS_IN_YEAR = 365; // 365 since DUMMY_YEAR is not a leap year
- final int mStartDay; // [1,365]
- final int mEndDay; // [1,365]
+ private final MonthDay mStart;
+ private final MonthDay mEnd;
- FreezeInterval(int startDay, int endDay) {
- if (startDay < 1 || startDay > 365 || endDay < 1 || endDay > 365) {
- throw new RuntimeException("Bad dates for Interval: " + startDay + "," + endDay);
- }
- mStartDay = startDay;
- mEndDay = endDay;
+ /*
+ * Start and end dates represented by number of days since the beginning of the year.
+ * They are internal representations of mStart and mEnd with normalized Leap year days
+ * (Feb 29 == Feb 28 == 59th day of year). All internal calclations are based on
+ * these two values so that leap year days are disregarded.
+ */
+ private final int mStartDay; // [1, 365]
+ private final int mEndDay; // [1, 365]
+
+ /**
+ * Creates a freeze period by its start and end dates. If the end date is earlier than the start
+ * date, the freeze period is considered wrapping year-end.
+ */
+ public FreezePeriod(MonthDay start, MonthDay end) {
+ mStart = start;
+ mStartDay = mStart.atYear(DUMMY_YEAR).getDayOfYear();
+ mEnd = end;
+ mEndDay = mEnd.atYear(DUMMY_YEAR).getDayOfYear();
}
+ /**
+ * Returns the start date (inclusive) of this freeze period.
+ */
+ public MonthDay getStart() {
+ return mStart;
+ }
+
+ /**
+ * Returns the end date (inclusive) of this freeze period.
+ */
+ public MonthDay getEnd() {
+ return mEnd;
+ }
+
+ /**
+ * @hide
+ */
+ private FreezePeriod(int startDay, int endDay) {
+ mStartDay = startDay;
+ mStart = dayOfYearToMonthDay(startDay);
+ mEndDay = endDay;
+ mEnd = dayOfYearToMonthDay(endDay);
+ }
+
+ /** @hide */
int getLength() {
return getEffectiveEndDay() - mStartDay + 1;
}
+ /** @hide */
boolean isWrapped() {
return mEndDay < mStartDay;
}
/**
* Returns the effective end day, taking wrapping around year-end into consideration
+ * @hide
*/
int getEffectiveEndDay() {
if (!isWrapped()) {
@@ -72,6 +111,7 @@
}
}
+ /** @hide */
boolean contains(LocalDate localDate) {
final int daysOfYear = dayOfYearDisregardLeapYear(localDate);
if (!isWrapped()) {
@@ -84,6 +124,7 @@
}
}
+ /** @hide */
boolean after(LocalDate localDate) {
return mStartDay > dayOfYearDisregardLeapYear(localDate);
}
@@ -95,6 +136,7 @@
* include now, the returned dates represents the next future interval.
* The result will always have the same month and dayOfMonth value as the non-instantiated
* interval itself.
+ * @hide
*/
Pair<LocalDate, LocalDate> toCurrentOrFutureRealDates(LocalDate now) {
final int nowDays = dayOfYearDisregardLeapYear(now);
@@ -138,14 +180,24 @@
+ LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).format(formatter);
}
- // Treat the supplied date as in a non-leap year and return its day of year.
- static int dayOfYearDisregardLeapYear(LocalDate date) {
+ /** @hide */
+ private static MonthDay dayOfYearToMonthDay(int dayOfYear) {
+ LocalDate date = LocalDate.ofYearDay(DUMMY_YEAR, dayOfYear);
+ return MonthDay.of(date.getMonth(), date.getDayOfMonth());
+ }
+
+ /**
+ * Treat the supplied date as in a non-leap year and return its day of year.
+ * @hide
+ */
+ private static int dayOfYearDisregardLeapYear(LocalDate date) {
return date.withYear(DUMMY_YEAR).getDayOfYear();
}
/**
* Compute the number of days between first (inclusive) and second (exclusive),
* treating all years in between as non-leap.
+ * @hide
*/
public static int distanceWithoutLeapYear(LocalDate first, LocalDate second) {
return dayOfYearDisregardLeapYear(first) - dayOfYearDisregardLeapYear(second)
@@ -165,16 +217,16 @@
* 3. At most one wrapped Interval remains, and it will be at the end of the list
* @hide
*/
- protected static List<FreezeInterval> canonicalizeIntervals(List<FreezeInterval> intervals) {
+ static List<FreezePeriod> canonicalizePeriods(List<FreezePeriod> intervals) {
boolean[] taken = new boolean[DAYS_IN_YEAR];
// First convert the intervals into flat array
- for (FreezeInterval interval : intervals) {
+ for (FreezePeriod interval : intervals) {
for (int i = interval.mStartDay; i <= interval.getEffectiveEndDay(); i++) {
taken[(i - 1) % DAYS_IN_YEAR] = true;
}
}
// Then reconstruct intervals from the array
- List<FreezeInterval> result = new ArrayList<>();
+ List<FreezePeriod> result = new ArrayList<>();
int i = 0;
while (i < DAYS_IN_YEAR) {
if (!taken[i]) {
@@ -183,14 +235,14 @@
}
final int intervalStart = i + 1;
while (i < DAYS_IN_YEAR && taken[i]) i++;
- result.add(new FreezeInterval(intervalStart, i));
+ result.add(new FreezePeriod(intervalStart, i));
}
// Check if the last entry can be merged to the first entry to become one single
// wrapped interval
final int lastIndex = result.size() - 1;
if (lastIndex > 0 && result.get(lastIndex).mEndDay == DAYS_IN_YEAR
&& result.get(0).mStartDay == 1) {
- FreezeInterval wrappedInterval = new FreezeInterval(result.get(lastIndex).mStartDay,
+ FreezePeriod wrappedInterval = new FreezePeriod(result.get(lastIndex).mStartDay,
result.get(0).mEndDay);
result.set(lastIndex, wrappedInterval);
result.remove(0);
@@ -207,18 +259,18 @@
*
* @hide
*/
- protected static void validatePeriods(List<FreezeInterval> periods) {
- List<FreezeInterval> allPeriods = FreezeInterval.canonicalizeIntervals(periods);
+ static void validatePeriods(List<FreezePeriod> periods) {
+ List<FreezePeriod> allPeriods = FreezePeriod.canonicalizePeriods(periods);
if (allPeriods.size() != periods.size()) {
throw SystemUpdatePolicy.ValidationFailedException.duplicateOrOverlapPeriods();
}
for (int i = 0; i < allPeriods.size(); i++) {
- FreezeInterval current = allPeriods.get(i);
+ FreezePeriod current = allPeriods.get(i);
if (current.getLength() > SystemUpdatePolicy.FREEZE_PERIOD_MAX_LENGTH) {
throw SystemUpdatePolicy.ValidationFailedException.freezePeriodTooLong("Freeze "
+ "period " + current + " is too long: " + current.getLength() + " days");
}
- FreezeInterval previous = i > 0 ? allPeriods.get(i - 1)
+ FreezePeriod previous = i > 0 ? allPeriods.get(i - 1)
: allPeriods.get(allPeriods.size() - 1);
if (previous != current) {
final int separation;
@@ -247,7 +299,7 @@
*
* @hide
*/
- protected static void validateAgainstPreviousFreezePeriod(List<FreezeInterval> periods,
+ static void validateAgainstPreviousFreezePeriod(List<FreezePeriod> periods,
LocalDate prevPeriodStart, LocalDate prevPeriodEnd, LocalDate now) {
if (periods.size() == 0 || prevPeriodStart == null || prevPeriodEnd == null) {
return;
@@ -258,14 +310,14 @@
// Clock was adjusted backwards. We can continue execution though, the separation
// and length validation below still works under this condition.
}
- List<FreezeInterval> allPeriods = FreezeInterval.canonicalizeIntervals(periods);
+ List<FreezePeriod> allPeriods = FreezePeriod.canonicalizePeriods(periods);
// Given current time now, find the freeze period that's either current, or the one
// that's immediately afterwards. For the later case, it might be after the year-end,
// but this can only happen if there is only one freeze period.
- FreezeInterval curOrNextFreezePeriod = allPeriods.get(0);
- for (FreezeInterval interval : allPeriods) {
+ FreezePeriod curOrNextFreezePeriod = allPeriods.get(0);
+ for (FreezePeriod interval : allPeriods) {
if (interval.contains(now)
- || interval.mStartDay > FreezeInterval.dayOfYearDisregardLeapYear(now)) {
+ || interval.mStartDay > FreezePeriod.dayOfYearDisregardLeapYear(now)) {
curOrNextFreezePeriod = interval;
break;
}
@@ -282,7 +334,7 @@
// Now validate [prevPeriodStart, prevPeriodEnd] against curOrNextFreezeDates
final String periodsDescription = "Prev: " + prevPeriodStart + "," + prevPeriodEnd
+ "; cur: " + curOrNextFreezeDates.first + "," + curOrNextFreezeDates.second;
- long separation = FreezeInterval.distanceWithoutLeapYear(curOrNextFreezeDates.first,
+ long separation = FreezePeriod.distanceWithoutLeapYear(curOrNextFreezeDates.first,
prevPeriodEnd) - 1;
if (separation > 0) {
// Two intervals do not overlap, check separation
@@ -292,7 +344,7 @@
}
} else {
// Two intervals overlap, check combined length
- long length = FreezeInterval.distanceWithoutLeapYear(curOrNextFreezeDates.second,
+ long length = FreezePeriod.distanceWithoutLeapYear(curOrNextFreezeDates.second,
prevPeriodStart) + 1;
if (length > SystemUpdatePolicy.FREEZE_PERIOD_MAX_LENGTH) {
throw ValidationFailedException.combinedPeriodTooLong("Combined freeze period "
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 47b3a81..20eef6c 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -38,9 +38,11 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
+import java.time.MonthDay;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -51,7 +53,7 @@
* @see DevicePolicyManager#setSystemUpdatePolicy
* @see DevicePolicyManager#getSystemUpdatePolicy
*/
-public class SystemUpdatePolicy implements Parcelable {
+public final class SystemUpdatePolicy implements Parcelable {
private static final String TAG = "SystemUpdatePolicy";
/** @hide */
@@ -163,6 +165,7 @@
ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE,
ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG,
ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE,
+ ERROR_UNKNOWN,
})
@Retention(RetentionPolicy.SOURCE)
@interface ValidationFailureType {}
@@ -171,33 +174,38 @@
public static final int ERROR_NONE = 0;
/**
+ * Validation failed with unknown error.
+ */
+ public static final int ERROR_UNKNOWN = 1;
+
+ /**
* The freeze periods contains duplicates, periods that overlap with each
* other or periods whose start and end joins.
*/
- public static final int ERROR_DUPLICATE_OR_OVERLAP = 1;
+ public static final int ERROR_DUPLICATE_OR_OVERLAP = 2;
/**
* There exists at least one freeze period whose length exceeds 90 days.
*/
- public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 2;
+ public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 3;
/**
* There exists some freeze period which starts within 60 days of the preceding period's
* end time.
*/
- public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 3;
+ public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 4;
/**
* The device has been in a freeze period and when combining with the new freeze period
* to be set, it will result in the total freeze period being longer than 90 days.
*/
- public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 4;
+ public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 5;
/**
* The device has been in a freeze period and some new freeze period to be set is less
* than 60 days from the end of the last freeze period the device went through.
*/
- public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 5;
+ public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 6;
@ValidationFailureType
private final int mErrorCode;
@@ -272,7 +280,7 @@
private int mMaintenanceWindowStart;
private int mMaintenanceWindowEnd;
- private final ArrayList<FreezeInterval> mFreezePeriods;
+ private final ArrayList<FreezePeriod> mFreezePeriods;
private SystemUpdatePolicy() {
mPolicyType = TYPE_UNKNOWN;
@@ -444,12 +452,10 @@
* requirement set above
* @return this instance
*/
- public SystemUpdatePolicy setFreezePeriods(List<Pair<Integer, Integer>> freezePeriods) {
- List<FreezeInterval> newPeriods = freezePeriods.stream().map(
- p -> new FreezeInterval(p.first, p.second)).collect(Collectors.toList());
- FreezeInterval.validatePeriods(newPeriods);
+ public SystemUpdatePolicy setFreezePeriods(List<FreezePeriod> freezePeriods) {
+ FreezePeriod.validatePeriods(freezePeriods);
mFreezePeriods.clear();
- mFreezePeriods.addAll(newPeriods);
+ mFreezePeriods.addAll(freezePeriods);
return this;
}
@@ -458,12 +464,8 @@
*
* @return the list of freeze periods, or an empty list if none was set.
*/
- public List<Pair<Integer, Integer>> getFreezePeriods() {
- List<Pair<Integer, Integer>> result = new ArrayList<>(mFreezePeriods.size());
- for (FreezeInterval interval : mFreezePeriods) {
- result.add(new Pair<>(interval.mStartDay, interval.mEndDay));
- }
- return result;
+ public List<FreezePeriod> getFreezePeriods() {
+ return Collections.unmodifiableList(mFreezePeriods);
}
/**
@@ -472,7 +474,7 @@
* @hide
*/
public Pair<LocalDate, LocalDate> getCurrentFreezePeriod(LocalDate now) {
- for (FreezeInterval interval : mFreezePeriods) {
+ for (FreezePeriod interval : mFreezePeriods) {
if (interval.contains(now)) {
return interval.toCurrentOrFutureRealDates(now);
}
@@ -485,10 +487,10 @@
* is not within a freeze period.
*/
private long timeUntilNextFreezePeriod(long now) {
- List<FreezeInterval> sortedPeriods = FreezeInterval.canonicalizeIntervals(mFreezePeriods);
+ List<FreezePeriod> sortedPeriods = FreezePeriod.canonicalizePeriods(mFreezePeriods);
LocalDate nowDate = millisToDate(now);
LocalDate nextFreezeStart = null;
- for (FreezeInterval interval : sortedPeriods) {
+ for (FreezePeriod interval : sortedPeriods) {
if (interval.after(nowDate)) {
nextFreezeStart = interval.toCurrentOrFutureRealDates(nowDate).first;
break;
@@ -506,13 +508,13 @@
/** @hide */
public void validateFreezePeriods() {
- FreezeInterval.validatePeriods(mFreezePeriods);
+ FreezePeriod.validatePeriods(mFreezePeriods);
}
/** @hide */
public void validateAgainstPreviousFreezePeriod(LocalDate prevPeriodStart,
LocalDate prevPeriodEnd, LocalDate now) {
- FreezeInterval.validateAgainstPreviousFreezePeriod(mFreezePeriods, prevPeriodStart,
+ FreezePeriod.validateAgainstPreviousFreezePeriod(mFreezePeriods, prevPeriodStart,
prevPeriodEnd, now);
}
@@ -521,10 +523,10 @@
* updates and how long this action is valid for, given the current system update policy. Its
* action could be one of the following
* <ul>
- * <li> {@code TYPE_INSTALL_AUTOMATIC} system updates should be installed immedately and without
- * user intervention as soon as they become available.
- * <li> {@code TYPE_POSTPONE} system updates should be postponed for a maximum of 30 days
- * <li> {@code TYPE_PAUSE} system updates should be postponed indefinitely until further notice
+ * <li> {@link #TYPE_INSTALL_AUTOMATIC} system updates should be installed immedately and
+ * without user intervention as soon as they become available.
+ * <li> {@link #TYPE_POSTPONE} system updates should be postponed for a maximum of 30 days
+ * <li> {@link #TYPE_PAUSE} system updates should be postponed indefinitely until further notice
* </ul>
*
* The effective time measures how long this installation option is valid for from the queried
@@ -535,18 +537,38 @@
*/
@SystemApi
public static class InstallationOption {
+ /** @hide */
+ @IntDef(prefix = { "TYPE_" }, value = {
+ TYPE_INSTALL_AUTOMATIC,
+ TYPE_PAUSE,
+ TYPE_POSTPONE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface InstallationOptionType {}
+
+ @InstallationOptionType
private final int mType;
private long mEffectiveTime;
- InstallationOption(int type, long effectiveTime) {
+ InstallationOption(@InstallationOptionType int type, long effectiveTime) {
this.mType = type;
this.mEffectiveTime = effectiveTime;
}
- public int getType() {
+ /**
+ * Returns the type of the current installation option, could be one of
+ * {@link #TYPE_INSTALL_AUTOMATIC}, {@link #TYPE_POSTPONE} and {@link #TYPE_PAUSE}.
+ * @return type of installation option.
+ */
+ public @InstallationOptionType int getType() {
return mType;
}
+ /**
+ * Returns how long the current installation option in effective for, starting from the time
+ * of query.
+ * @return the effective time in milliseconds.
+ */
public long getEffectiveTime() {
return mEffectiveTime;
}
@@ -667,9 +689,11 @@
int freezeCount = mFreezePeriods.size();
dest.writeInt(freezeCount);
for (int i = 0; i < freezeCount; i++) {
- FreezeInterval interval = mFreezePeriods.get(i);
- dest.writeInt(interval.mStartDay);
- dest.writeInt(interval.mEndDay);
+ FreezePeriod interval = mFreezePeriods.get(i);
+ dest.writeInt(interval.getStart().getMonthValue());
+ dest.writeInt(interval.getStart().getDayOfMonth());
+ dest.writeInt(interval.getEnd().getMonthValue());
+ dest.writeInt(interval.getEnd().getDayOfMonth());
}
}
@@ -686,8 +710,9 @@
int freezeCount = source.readInt();
policy.mFreezePeriods.ensureCapacity(freezeCount);
for (int i = 0; i < freezeCount; i++) {
- policy.mFreezePeriods.add(
- new FreezeInterval(source.readInt(), source.readInt()));
+ MonthDay start = MonthDay.of(source.readInt(), source.readInt());
+ MonthDay end = MonthDay.of(source.readInt(), source.readInt());
+ policy.mFreezePeriods.add(new FreezePeriod(start, end));
}
return policy;
}
@@ -730,9 +755,9 @@
if (!parser.getName().equals(KEY_FREEZE_TAG)) {
continue;
}
- policy.mFreezePeriods.add(new FreezeInterval(
- Integer.parseInt(parser.getAttributeValue(null, KEY_FREEZE_START)),
- Integer.parseInt(parser.getAttributeValue(null, KEY_FREEZE_END))));
+ policy.mFreezePeriods.add(new FreezePeriod(
+ MonthDay.parse(parser.getAttributeValue(null, KEY_FREEZE_START)),
+ MonthDay.parse(parser.getAttributeValue(null, KEY_FREEZE_END))));
}
return policy;
}
@@ -751,10 +776,10 @@
out.attribute(null, KEY_INSTALL_WINDOW_START, Integer.toString(mMaintenanceWindowStart));
out.attribute(null, KEY_INSTALL_WINDOW_END, Integer.toString(mMaintenanceWindowEnd));
for (int i = 0; i < mFreezePeriods.size(); i++) {
- FreezeInterval interval = mFreezePeriods.get(i);
+ FreezePeriod interval = mFreezePeriods.get(i);
out.startTag(null, KEY_FREEZE_TAG);
- out.attribute(null, KEY_FREEZE_START, Integer.toString(interval.mStartDay));
- out.attribute(null, KEY_FREEZE_END, Integer.toString(interval.mEndDay));
+ out.attribute(null, KEY_FREEZE_START, interval.getStart().toString());
+ out.attribute(null, KEY_FREEZE_END, interval.getEnd().toString());
out.endTag(null, KEY_FREEZE_TAG);
}
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index b2fe958..85f4efc 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -305,6 +305,8 @@
* {@link java.lang.System#currentTimeMillis}.
* @param uid UID of app
* @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
+ * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
+ * traffic from all states.
* @return Statistics object or null if an error happened during statistics collection.
* @throws SecurityException if permissions are insufficient to read network statistics.
*/
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 37360ba..49cc498 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -37,6 +37,7 @@
import android.widget.RemoteViews;
import android.widget.RemoteViews.OnClickHandler;
+import com.android.internal.R;
import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;
@@ -171,8 +172,9 @@
return;
}
sServiceInitialized = true;
- if (!context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_APP_WIDGETS)) {
+ PackageManager packageManager = context.getPackageManager();
+ if (!packageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)
+ && !context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
return;
}
IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE);
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 8f8083e..159e165 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -421,29 +421,29 @@
}
/**
- * Check whether the device is active.
+ * Get the connected physical Hearing Aid devices that are active
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
* permission.
*
- * @return the connected device that is active or null if no device
- * is active
+ * @return the list of active devices. The first element is the left active
+ * device; the second element is the right active device. If either or both side
+ * is not active, it will be null on that position. Returns empty list on error.
* @hide
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public boolean isActiveDevice(@Nullable BluetoothDevice device) {
- if (VDBG) log("isActiveDevice()");
+ public List<BluetoothDevice> getActiveDevices() {
+ if (VDBG) log("getActiveDevices()");
try {
mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
- && ((device == null) || isValidDevice(device))) {
- return mService.isActiveDevice(device);
+ if (mService != null && isEnabled()) {
+ return mService.getActiveDevices();
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return false;
+ return new ArrayList<>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return false;
+ return new ArrayList<>();
} finally {
mServiceLock.readLock().unlock();
}
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index af99bf7..3bc8544 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -701,6 +701,28 @@
}
/**
+ * Gets the application name of the current HidDeviceService user.
+ *
+ * @return the current user name, or empty string if cannot get the name
+ * {@hide}
+ */
+ public String getUserAppName() {
+ final IBluetoothHidDevice service = mService;
+
+ if (service != null) {
+ try {
+ return service.getUserAppName();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return "";
+ }
+
+ /**
* Initiates connection to host which is currently paired with this device. If the application
* is not registered, #connect(BluetoothDevice) will fail. The connection state should be
* tracked by the application by handling callback from Callback#onConnectionStateChanged. The
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 9f3df37..f7908b6 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -51,7 +51,6 @@
import android.util.EventLog;
import android.util.Log;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.MimeIconUtils;
import com.android.internal.util.Preconditions;
@@ -602,6 +601,8 @@
try {
return provider.getType(url);
} catch (RemoteException e) {
+ // Arbitrary and not worth documenting, as Activity
+ // Manager will kill this process shortly anyway.
return null;
} catch (java.lang.Exception e) {
Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
@@ -620,9 +621,7 @@
ContentProvider.getUriWithoutUserId(url), resolveUserId(url));
return type;
} catch (RemoteException e) {
- // Arbitrary and not worth documenting, as Activity
- // Manager will kill this process shortly anyway.
- return null;
+ throw e.rethrowFromSystemServer();
} catch (java.lang.Exception e) {
Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
return null;
@@ -1964,6 +1963,7 @@
getContentService().registerContentObserver(uri, notifyForDescendents,
observer.getContentObserver(), userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1982,6 +1982,7 @@
contentObserver);
}
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2089,6 +2090,7 @@
syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2105,6 +2107,7 @@
observer != null && observer.deliverSelfNotifications(), flags,
userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2126,6 +2129,7 @@
ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
resolveUserId(uri));
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2141,6 +2145,7 @@
ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage,
resolveUserId(uri));
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2160,6 +2165,7 @@
ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
resolveUserId(uri));
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2178,7 +2184,7 @@
return ActivityManager.getService()
.getPersistedUriPermissions(mPackageName, true).getList();
} catch (RemoteException e) {
- throw new RuntimeException("Activity manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2194,7 +2200,7 @@
return ActivityManager.getService()
.getPersistedUriPermissions(mPackageName, false).getList();
} catch (RemoteException e) {
- throw new RuntimeException("Activity manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2273,7 +2279,7 @@
try {
getContentService().syncAsUser(request, userId);
} catch(RemoteException e) {
- // Shouldn't happen.
+ throw e.rethrowFromSystemServer();
}
}
@@ -2285,7 +2291,7 @@
try {
getContentService().sync(request);
} catch(RemoteException e) {
- // Shouldn't happen.
+ throw e.rethrowFromSystemServer();
}
}
@@ -2349,6 +2355,7 @@
try {
getContentService().cancelSync(account, authority, null);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2360,6 +2367,7 @@
try {
getContentService().cancelSyncAsUser(account, authority, null, userId);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2371,7 +2379,7 @@
try {
return getContentService().getSyncAdapterTypes();
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2383,7 +2391,7 @@
try {
return getContentService().getSyncAdapterTypesAsUser(userId);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2397,8 +2405,8 @@
try {
return getContentService().getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return ArrayUtils.emptyArray(String.class);
}
/**
@@ -2414,7 +2422,7 @@
try {
return getContentService().getSyncAutomatically(account, authority);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2427,7 +2435,7 @@
try {
return getContentService().getSyncAutomaticallyAsUser(account, authority, userId);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2453,8 +2461,7 @@
try {
getContentService().setSyncAutomaticallyAsUser(account, authority, sync, userId);
} catch (RemoteException e) {
- // exception ignored; if this is thrown then it means the runtime is in the midst of
- // being restarted
+ throw e.rethrowFromSystemServer();
}
}
@@ -2500,8 +2507,7 @@
try {
getContentService().addPeriodicSync(account, authority, extras, pollFrequency);
} catch (RemoteException e) {
- // exception ignored; if this is thrown then it means the runtime is in the midst of
- // being restarted
+ throw e.rethrowFromSystemServer();
}
}
@@ -2540,7 +2546,7 @@
try {
getContentService().removePeriodicSync(account, authority, extras);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2564,8 +2570,7 @@
try {
getContentService().cancelRequest(request);
} catch (RemoteException e) {
- // exception ignored; if this is thrown then it means the runtime is in the midst of
- // being restarted
+ throw e.rethrowFromSystemServer();
}
}
@@ -2582,7 +2587,7 @@
try {
return getContentService().getPeriodicSyncs(account, authority, null);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2596,7 +2601,7 @@
try {
return getContentService().getIsSyncable(account, authority);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2609,7 +2614,7 @@
try {
return getContentService().getIsSyncableAsUser(account, authority, userId);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2623,8 +2628,7 @@
try {
getContentService().setIsSyncable(account, authority, syncable);
} catch (RemoteException e) {
- // exception ignored; if this is thrown then it means the runtime is in the midst of
- // being restarted
+ throw e.rethrowFromSystemServer();
}
}
@@ -2640,7 +2644,7 @@
try {
return getContentService().getMasterSyncAutomatically();
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2652,7 +2656,7 @@
try {
return getContentService().getMasterSyncAutomaticallyAsUser(userId);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2676,8 +2680,7 @@
try {
getContentService().setMasterSyncAutomaticallyAsUser(sync, userId);
} catch (RemoteException e) {
- // exception ignored; if this is thrown then it means the runtime is in the midst of
- // being restarted
+ throw e.rethrowFromSystemServer();
}
}
@@ -2701,7 +2704,7 @@
try {
return getContentService().isSyncActive(account, authority, null);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2727,7 +2730,7 @@
}
return syncs.get(0);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2744,7 +2747,7 @@
try {
return getContentService().getCurrentSyncs();
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2756,7 +2759,7 @@
try {
return getContentService().getCurrentSyncsAsUser(userId);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2771,7 +2774,7 @@
try {
return getContentService().getSyncStatus(account, authority, null);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2784,7 +2787,7 @@
try {
return getContentService().getSyncStatusAsUser(account, authority, null, userId);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2809,7 +2812,7 @@
try {
return getContentService().isSyncPendingAsUser(account, authority, null, userId);
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2841,7 +2844,7 @@
getContentService().addStatusChangeListener(mask, observer);
return observer;
} catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2856,8 +2859,7 @@
try {
getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle);
} catch (RemoteException e) {
- // exception ignored; if this is thrown then it means the runtime is in the midst of
- // being restarted
+ throw e.rethrowFromSystemServer();
}
}
@@ -3027,9 +3029,7 @@
return sContentService;
}
IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME);
- if (false) Log.v("ContentService", "default service binder = " + b);
sContentService = IContentService.Stub.asInterface(b);
- if (false) Log.v("ContentService", "default service = " + sContentService);
return sContentService;
}
@@ -3038,7 +3038,7 @@
return mPackageName;
}
- private static IContentService sContentService;
+ private static volatile IContentService sContentService;
private final Context mContext;
final String mPackageName;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 920056a..ede7ee4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3780,7 +3780,7 @@
public static final String DROPBOX_SERVICE = "dropbox";
/**
- * System service name for the DeviceIdleController. There is no Java API for this.
+ * System service name for the DeviceIdleManager.
* @see #getSystemService(String)
* @hide
*/
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index efc9b6d..01ee671 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6810,6 +6810,9 @@
case "--activity-task-on-home":
intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
break;
+ case "--activity-match-external":
+ intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
+ break;
case "--receiver-registered-only":
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
break;
@@ -6946,7 +6949,7 @@
" [--activity-no-user-action] [--activity-previous-is-top]",
" [--activity-reorder-to-front] [--activity-reset-task-if-needed]",
" [--activity-single-top] [--activity-clear-task]",
- " [--activity-task-on-home]",
+ " [--activity-task-on-home] [--activity-match-external]",
" [--receiver-registered-only] [--receiver-replace-pending]",
" [--receiver-foreground] [--receiver-no-abort]",
" [--receiver-include-background]",
diff --git a/core/java/android/content/QuickViewConstants.java b/core/java/android/content/QuickViewConstants.java
index a25513d..132d43f 100644
--- a/core/java/android/content/QuickViewConstants.java
+++ b/core/java/android/content/QuickViewConstants.java
@@ -45,8 +45,8 @@
* Feature to delete an individual document. Quick viewer implementations must use
* Storage Access Framework to both verify delete permission and to delete content.
*
- * @see DocumentsContract#Document#FLAG_SUPPORTS_DELETE
- * @see DocumentsContract#deleteDocument(ContentResolver resolver, Uri documentUri)
+ * @see DocumentsContract.Document#FLAG_SUPPORTS_DELETE
+ * @see DocumentsContract#deleteDocument(ContentResolver, Uri)
*/
public static final String FEATURE_DELETE = "android:delete";
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 6748cdb..c5a39f4 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -26,6 +26,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
@@ -1132,11 +1133,12 @@
*/
public static final int HIDDEN_API_ENFORCEMENT_NONE = 0;
/**
- * Light grey list enforcement, the strictest option. Enforces the light grey, dark grey and
- * black lists.
+ * No API enforcement, but enable the detection logic and warnings. Observed behaviour is the
+ * same as {@link #HIDDEN_API_ENFORCEMENT_NONE} but you may see warnings in the log when APIs
+ * are accessed.
* @hide
* */
- public static final int HIDDEN_API_ENFORCEMENT_ALL_LISTS = 1;
+ public static final int HIDDEN_API_ENFORCEMENT_JUST_WARN = 1;
/**
* Dark grey list enforcement. Enforces the dark grey and black lists
* @hide
@@ -1158,14 +1160,15 @@
@IntDef(prefix = { "HIDDEN_API_ENFORCEMENT_" }, value = {
HIDDEN_API_ENFORCEMENT_DEFAULT,
HIDDEN_API_ENFORCEMENT_NONE,
- HIDDEN_API_ENFORCEMENT_ALL_LISTS,
+ HIDDEN_API_ENFORCEMENT_JUST_WARN,
HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK,
HIDDEN_API_ENFORCEMENT_BLACK,
})
@Retention(RetentionPolicy.SOURCE)
public @interface HiddenApiEnforcementPolicy {}
- private boolean isValidHiddenApiEnforcementPolicy(int policy) {
+ /** @hide */
+ public static boolean isValidHiddenApiEnforcementPolicy(int policy) {
return policy >= HIDDEN_API_ENFORCEMENT_DEFAULT && policy <= HIDDEN_API_ENFORCEMENT_MAX;
}
@@ -1685,13 +1688,17 @@
* @hide
*/
public @HiddenApiEnforcementPolicy int getHiddenApiEnforcementPolicy() {
- if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
- return mHiddenApiPolicy;
- }
if (isAllowedToUseHiddenApis()) {
return HIDDEN_API_ENFORCEMENT_NONE;
}
- return HIDDEN_API_ENFORCEMENT_BLACK;
+ if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
+ return mHiddenApiPolicy;
+ }
+ if (targetSdkVersion <= Build.VERSION_CODES.O_MR1) {
+ return HIDDEN_API_ENFORCEMENT_BLACK;
+ } else {
+ return HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK;
+ }
}
/**
@@ -1705,6 +1712,31 @@
}
/**
+ * Updates the hidden API enforcement policy for this app from the given values, if appropriate.
+ *
+ * This will have no effect if this app is not subject to hidden API enforcement, i.e. if it
+ * is on the package whitelist.
+ *
+ * @param policyPreP configured policy for pre-P apps, or {@link
+ * #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
+ * @param policyP configured policy for apps targeting P or later, or {@link
+ * #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
+ * @hide
+ */
+ public void maybeUpdateHiddenApiEnforcementPolicy(
+ @HiddenApiEnforcementPolicy int policyPreP, @HiddenApiEnforcementPolicy int policyP) {
+ if (isPackageWhitelistedForHiddenApis()) {
+ return;
+ }
+ if (targetSdkVersion <= Build.VERSION_CODES.O_MR1) {
+ setHiddenApiEnforcementPolicy(policyPreP);
+ } else if (targetSdkVersion > Build.VERSION_CODES.O_MR1) {
+ setHiddenApiEnforcementPolicy(policyP);
+ }
+
+ }
+
+ /**
* @hide
*/
public void setVersionCode(long newVersionCode) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index dd86d47..34e3d8b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3952,6 +3952,7 @@
*
* @hide
*/
+ @TestApi
public abstract @NonNull String getServicesSystemSharedLibraryPackageName();
/**
@@ -3961,6 +3962,7 @@
*
* @hide
*/
+ @TestApi
public abstract @NonNull String getSharedSystemSharedLibraryPackageName();
/**
@@ -6129,7 +6131,9 @@
* signed. This should be used instead of {@code getPackageInfo} with {@code GET_SIGNATURES}
* since it takes into account the possibility of signing certificate rotation, except in the
* case of packages that are signed by multiple certificates, for which signing certificate
- * rotation is not supported.
+ * rotation is not supported. This method is analogous to using {@code getPackageInfo} with
+ * {@code GET_SIGNING_CERTIFICATES} and then searching through the resulting {@code
+ * signingCertificateHistory} field to see if the desired certificate is present.
*
* @param packageName package whose signing certificates to check
* @param certificate signing certificate for which to search
@@ -6143,13 +6147,19 @@
}
/**
- * Searches the set of signing certificates by which the given uid has proven to have been
- * signed. This should be used instead of {@code getPackageInfo} with {@code GET_SIGNATURES}
+ * Searches the set of signing certificates by which the package(s) for the given uid has proven
+ * to have been signed. For multiple packages sharing the same uid, this will return the
+ * signing certificates found in the signing history of the "newest" package, where "newest"
+ * indicates the package with the newest signing certificate in the shared uid group. This
+ * method should be used instead of {@code getPackageInfo} with {@code GET_SIGNATURES}
* since it takes into account the possibility of signing certificate rotation, except in the
* case of packages that are signed by multiple certificates, for which signing certificate
- * rotation is not supported.
+ * rotation is not supported. This method is analogous to using {@code getPackagesForUid}
+ * followed by {@code getPackageInfo} with {@code GET_SIGNING_CERTIFICATES}, selecting the
+ * {@code PackageInfo} of the newest-signed bpackage , and finally searching through the
+ * resulting {@code signingCertificateHistory} field to see if the desired certificate is there.
*
- * @param uid package whose signing certificates to check
+ * @param uid uid whose signing certificates to check
* @param certificate signing certificate for which to search
* @param type representation of the {@code certificate}
* @return true if this package was or is signed by exactly the certificate {@code certificate}
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index a9d0911..699e81b 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -521,6 +521,11 @@
public abstract @Nullable PackageParser.Package getPackage(@NonNull String packageName);
/**
+ * Returns a {@link com.android.server.pm.PackageSetting} for a given package name.
+ */
+ public abstract @Nullable Object getPackageSetting(String packageName);
+
+ /**
* Returns a list without a change observer.
*
* {@see #getPackageList(PackageListObserver)}
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 67e97bf..6d9ba77 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -86,7 +86,9 @@
sb.append("(").append(mLux[i]).append(", ").append(mNits[i]).append(")");
}
sb.append("], '");
- sb.append(mDescription);
+ if (mDescription != null) {
+ sb.append(mDescription);
+ }
sb.append("'}");
return sb.toString();
}
@@ -96,7 +98,9 @@
int result = 1;
result = result * 31 + Arrays.hashCode(mLux);
result = result * 31 + Arrays.hashCode(mNits);
- result = result * 31 + mDescription.hashCode();
+ if (mDescription != null) {
+ result = result * 31 + mDescription.hashCode();
+ }
return result;
}
diff --git a/core/java/android/hardware/display/Curve.aidl b/core/java/android/hardware/display/Curve.aidl
new file mode 100644
index 0000000..796493e
--- /dev/null
+++ b/core/java/android/hardware/display/Curve.aidl
@@ -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.
+ */
+
+package android.hardware.display;
+
+parcelable Curve;
diff --git a/core/java/android/hardware/display/Curve.java b/core/java/android/hardware/display/Curve.java
new file mode 100644
index 0000000..ac28fdd
--- /dev/null
+++ b/core/java/android/hardware/display/Curve.java
@@ -0,0 +1,62 @@
+/*
+ * 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.hardware.display;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public final class Curve implements Parcelable {
+ private final float[] mX;
+ private final float[] mY;
+
+ public Curve(float[] x, float[] y) {
+ mX = x;
+ mY = y;
+ }
+
+ public float[] getX() {
+ return mX;
+ }
+
+ public float[] getY() {
+ return mY;
+ }
+
+ public static final Creator<Curve> CREATOR = new Creator<Curve>() {
+ public Curve createFromParcel(Parcel in) {
+ float[] x = in.createFloatArray();
+ float[] y = in.createFloatArray();
+ return new Curve(x, y);
+ }
+
+ public Curve[] newArray(int size) {
+ return new Curve[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeFloatArray(mX);
+ out.writeFloatArray(mY);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index efb9517..b182fa2 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -28,6 +28,7 @@
import android.graphics.Point;
import android.media.projection.MediaProjection;
import android.os.Handler;
+import android.util.Pair;
import android.util.SparseArray;
import android.view.Display;
import android.view.Surface;
@@ -748,6 +749,22 @@
}
/**
+ * Returns the minimum brightness curve, which guarantess that any brightness curve that dips
+ * below it is rejected by the system.
+ * This prevent auto-brightness from setting the screen so dark as to prevent the user from
+ * resetting or disabling it, and maps lux to the absolute minimum nits that are still readable
+ * in that ambient brightness.
+ *
+ * @return The minimum brightness curve (as lux values and their corresponding nits values).
+ *
+ * @hide
+ */
+ @SystemApi
+ public Pair<float[], float[]> getMinimumBrightnessCurve() {
+ return mGlobal.getMinimumBrightnessCurve();
+ }
+
+ /**
* Listens for changes in available display devices.
*/
public interface DisplayListener {
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 2d0ef2f..d968a3e 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -31,6 +31,7 @@
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayAdjustments;
@@ -563,6 +564,24 @@
}
/**
+ * Returns the minimum brightness curve, which guarantess that any brightness curve that dips
+ * below it is rejected by the system.
+ * This prevent auto-brightness from setting the screen so dark as to prevent the user from
+ * resetting or disabling it, and maps lux to the absolute minimum nits that are still readable
+ * in that ambient brightness.
+ *
+ * @return The minimum brightness curve (as lux values and their corresponding nits values).
+ */
+ public Pair<float[], float[]> getMinimumBrightnessCurve() {
+ try {
+ Curve curve = mDm.getMinimumBrightnessCurve();
+ return Pair.create(curve.getX(), curve.getY());
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Retrieves ambient brightness stats.
*/
public List<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index b77de748..b575997 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -19,6 +19,7 @@
import android.content.pm.ParceledListSlice;
import android.graphics.Point;
import android.hardware.display.BrightnessConfiguration;
+import android.hardware.display.Curve;
import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.WifiDisplay;
@@ -112,4 +113,7 @@
// Temporarily sets the auto brightness adjustment factor.
void setTemporaryAutoBrightnessAdjustment(float adjustment);
+
+ // Get the minimum brightness curve.
+ Curve getMinimumBrightnessCurve();
}
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index ade6374..8732375 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -337,6 +337,9 @@
*/
public void applyTransportModeTransform(@NonNull Socket socket,
@PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
+ // Ensure creation of FD. See b/77548890 for more details.
+ socket.getSoLinger();
+
applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
}
@@ -441,6 +444,9 @@
* @throws IOException indicating that the transform could not be removed from the socket
*/
public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException {
+ // Ensure creation of FD. See b/77548890 for more details.
+ socket.getSoLinger();
+
removeTransportModeTransforms(socket.getFileDescriptor$());
}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 1a28732..e84c85e 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -19,7 +19,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.BackupUtils;
-import android.util.Pair;
+import android.util.Range;
import android.util.RecurrenceRule;
import com.android.internal.util.Preconditions;
@@ -136,7 +136,7 @@
return 0;
}
- public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() {
+ public Iterator<Range<ZonedDateTime>> cycleIterator() {
return cycleRule.cycleIterator();
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index bf6b7e0..6546c39 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -31,6 +31,7 @@
import android.os.UserHandle;
import android.util.DebugUtils;
import android.util.Pair;
+import android.util.Range;
import com.google.android.collect.Sets;
@@ -258,8 +259,21 @@
}
/** {@hide} */
+ @Deprecated
public static Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator(NetworkPolicy policy) {
- return policy.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = policy.cycleIterator();
+ return new Iterator<Pair<ZonedDateTime, ZonedDateTime>>() {
+ @Override
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ @Override
+ public Pair<ZonedDateTime, ZonedDateTime> next() {
+ final Range<ZonedDateTime> r = it.next();
+ return Pair.create(r.getLower(), r.getUpper());
+ }
+ };
}
/**
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 82af5d3..6f812ac 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -233,6 +233,8 @@
*
* @param capability The capability to add to unwanted capability list.
* @return The builder to facilitate chaining.
+ *
+ * @removed
*/
public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
mNetworkCapabilities.addUnwantedCapability(capability);
@@ -439,6 +441,8 @@
/**
* @see Builder#addUnwantedCapability(int)
+ *
+ * @removed
*/
public boolean hasUnwantedCapability(@NetCapability int capability) {
return networkCapabilities.hasUnwantedCapability(capability);
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index b00cb48..321f971 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -26,6 +26,8 @@
* @hide
*/
public class NetworkState implements Parcelable {
+ private static final boolean SANITY_CHECK_ROAMING = false;
+
public static final NetworkState EMPTY = new NetworkState(null, null, null, null, null, null);
public final NetworkInfo networkInfo;
@@ -47,7 +49,7 @@
// This object is an atomic view of a network, so the various components
// should always agree on roaming state.
- if (networkInfo != null && networkCapabilities != null) {
+ if (SANITY_CHECK_ROAMING && networkInfo != null && networkCapabilities != null) {
if (networkInfo.isRoaming() == networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)) {
Slog.wtf("NetworkState", "Roaming state disagreement between " + networkInfo
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index e0fa63a..f9b6dfc 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -21,7 +21,6 @@
import com.android.org.conscrypt.TrustManagerImpl;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.cert.CertificateException;
@@ -133,8 +132,6 @@
/**
* Returns {@code true} if the TrustManager uses the same trust configuration for the provided
* hostnames.
- *
- * @hide
*/
@SystemApi
public boolean isSameTrustConfiguration(String hostname1, String hostname2) {
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index 3b0dc7e..76a781d 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -20,7 +20,7 @@
import android.os.Parcelable;
/**
- * An event logged for an interface with APF capabilities when its IpManager state machine exits.
+ * An event logged for an interface with APF capabilities when its IpClient state machine exits.
* {@hide}
*/
public final class ApfStats implements Parcelable {
diff --git a/core/java/android/os/DeviceIdleManager.java b/core/java/android/os/DeviceIdleManager.java
new file mode 100644
index 0000000..9039f92
--- /dev/null
+++ b/core/java/android/os/DeviceIdleManager.java
@@ -0,0 +1,69 @@
+/*
+ * 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.os;
+
+import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.content.Context;
+
+/**
+ * Access to the service that keeps track of device idleness and drives low power mode based on
+ * that.
+ *
+ * @hide
+ */
+@TestApi
+@SystemService(Context.DEVICE_IDLE_CONTROLLER)
+public class DeviceIdleManager {
+ private final Context mContext;
+ private final IDeviceIdleController mService;
+
+ /**
+ * @hide
+ */
+ public DeviceIdleManager(@NonNull Context context, @NonNull IDeviceIdleController service) {
+ mContext = context;
+ mService = service;
+ }
+
+ /**
+ * @return package names the system has white-listed to opt out of power save restrictions,
+ * except for device idle mode.
+ */
+ public @NonNull String[] getSystemPowerWhitelistExceptIdle() {
+ try {
+ return mService.getSystemPowerWhitelistExceptIdle();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return new String[0];
+ }
+ }
+
+ /**
+ * @return package names the system has white-listed to opt out of power save restrictions for
+ * all modes.
+ */
+ public @NonNull String[] getSystemPowerWhitelist() {
+ try {
+ return mService.getSystemPowerWhitelist();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return new String[0];
+ }
+ }
+}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 03203d0..213260f 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.TestApi;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.storage.StorageManager;
@@ -1033,6 +1034,7 @@
*
* @hide
*/
+ @TestApi
public static File buildPath(File base, String... segments) {
File cur = base;
for (String segment : segments) {
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 8eb39c0..7d3ba6a 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.util.Log;
import android.util.MutableInt;
@@ -35,6 +36,7 @@
* {@hide}
*/
@SystemApi
+@TestApi
public class SystemProperties {
private static final String TAG = "SystemProperties";
private static final boolean TRACK_KEY_ACCESS = false;
@@ -110,6 +112,7 @@
*/
@NonNull
@SystemApi
+ @TestApi
public static String get(@NonNull String key, @Nullable String def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get(key, def);
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 094f004..4d4f31d 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -82,6 +82,7 @@
public static final int USER_SERIAL_SYSTEM = 0;
/** @hide A user handle to indicate the "system" user of the device */
+ @TestApi
public static final UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
/**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a9eb360..9b20ed2 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1149,6 +1149,7 @@
* primary user are two separate users. Previously system user and primary user are combined as
* a single owner user. see @link {android.os.UserHandle#USER_OWNER}
*/
+ @TestApi
public static boolean isSplitSystemUser() {
return RoSystemProperties.FW_SYSTEM_USER_SPLIT;
}
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index b9dd376..d1d5d8e 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -467,7 +467,8 @@
* <p>The list of exemptions will take affect for all new processes forked from the zygote after
* this call.
*
- * @param exemptions List of hidden API exemption prefixes.
+ * @param exemptions List of hidden API exemption prefixes. Any matching members are treated as
+ * whitelisted/public APIs (i.e. allowed, no logging of usage).
*/
public void setApiBlacklistExemptions(List<String> exemptions) {
synchronized (mLock) {
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index 9114107..d493cce 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -17,6 +17,7 @@
package android.os.storage;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
@@ -93,7 +94,7 @@
return true;
}
- public String getDescription() {
+ public @Nullable String getDescription() {
final Resources res = Resources.getSystem();
if ((flags & FLAG_SD) != 0) {
if (isInteresting(label)) {
@@ -112,6 +113,17 @@
}
}
+ public @Nullable String getShortDescription() {
+ final Resources res = Resources.getSystem();
+ if (isSd()) {
+ return res.getString(com.android.internal.R.string.storage_sd_card);
+ } else if (isUsb()) {
+ return res.getString(com.android.internal.R.string.storage_usb_drive);
+ } else {
+ return null;
+ }
+ }
+
public boolean isAdoptable() {
return (flags & FLAG_ADOPTABLE) != 0;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b2a2c60..c7c2c15 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1179,6 +1179,23 @@
public static final String ACTION_ZEN_MODE_SETTINGS = "android.settings.ZEN_MODE_SETTINGS";
/**
+ * Activity Action: Show Zen Mode visual effects configuration settings.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ZEN_MODE_BLOCKED_EFFECTS_SETTINGS =
+ "android.settings.ZEN_MODE_BLOCKED_EFFECTS_SETTINGS";
+
+ /**
+ * Activity Action: Show Zen Mode onboarding activity.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ZEN_MODE_ONBOARDING = "android.settings.ZEN_MODE_ONBOARDING";
+
+ /**
* Activity Action: Show Zen Mode (aka Do Not Disturb) priority configuration settings.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -3113,6 +3130,9 @@
*/
public static final String DISPLAY_COLOR_MODE = "display_color_mode";
+ private static final Validator DISPLAY_COLOR_MODE_VALIDATOR =
+ new SettingsValidators.InclusiveIntegerRangeValidator(0, 2);
+
/**
* The amount of time in milliseconds before the device goes to sleep or begins
* to dream after a period of inactivity. This value is also known as the
@@ -3133,9 +3153,6 @@
*/
public static final String SCREEN_BRIGHTNESS = "screen_brightness";
- private static final Validator SCREEN_BRIGHTNESS_VALIDATOR =
- new SettingsValidators.InclusiveIntegerRangeValidator(0, 255);
-
/**
* The screen backlight brightness between 0 and 255.
* @hide
@@ -4060,7 +4077,6 @@
FONT_SCALE,
DIM_SCREEN,
SCREEN_OFF_TIMEOUT,
- SCREEN_BRIGHTNESS,
SCREEN_BRIGHTNESS_MODE,
SCREEN_AUTO_BRIGHTNESS_ADJ,
SCREEN_BRIGHTNESS_FOR_VR,
@@ -4096,6 +4112,7 @@
SHOW_BATTERY_PERCENT,
NOTIFICATION_VIBRATION_INTENSITY,
HAPTIC_FEEDBACK_INTENSITY,
+ DISPLAY_COLOR_MODE
};
/**
@@ -4208,6 +4225,7 @@
PRIVATE_SETTINGS.add(LOCK_TO_APP_ENABLED);
PRIVATE_SETTINGS.add(EGG_MODE);
PRIVATE_SETTINGS.add(SHOW_BATTERY_PERCENT);
+ PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE);
}
/**
@@ -4229,8 +4247,8 @@
VALIDATORS.put(NEXT_ALARM_FORMATTED, NEXT_ALARM_FORMATTED_VALIDATOR);
VALIDATORS.put(FONT_SCALE, FONT_SCALE_VALIDATOR);
VALIDATORS.put(DIM_SCREEN, DIM_SCREEN_VALIDATOR);
+ VALIDATORS.put(DISPLAY_COLOR_MODE, DISPLAY_COLOR_MODE_VALIDATOR);
VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR);
- VALIDATORS.put(SCREEN_BRIGHTNESS, SCREEN_BRIGHTNESS_VALIDATOR);
VALIDATORS.put(SCREEN_BRIGHTNESS_FOR_VR, SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR);
VALIDATORS.put(SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_VALIDATOR);
VALIDATORS.put(MODE_RINGER_STREAMS_AFFECTED, MODE_RINGER_STREAMS_AFFECTED_VALIDATOR);
@@ -7381,6 +7399,17 @@
BOOLEAN_VALIDATOR;
/**
+ * Whether the swipe up gesture to switch apps should be enabled.
+ *
+ * @hide
+ */
+ public static final String SWIPE_UP_TO_SWITCH_APPS_ENABLED =
+ "swipe_up_to_switch_apps_enabled";
+
+ private static final Validator SWIPE_UP_TO_SWITCH_APPS_ENABLED_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
+ /**
* Whether or not the smart camera lift trigger that launches the camera when the user moves
* the phone into a position for taking photos should be enabled.
*
@@ -7891,6 +7920,7 @@
NIGHT_DISPLAY_AUTO_MODE,
SYNC_PARENT_SOUNDS,
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
+ SWIPE_UP_TO_SWITCH_APPS_ENABLED,
CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
SYSTEM_NAVIGATION_KEYS_ENABLED,
QS_TILES,
@@ -8024,6 +8054,8 @@
VALIDATORS.put(SYNC_PARENT_SOUNDS, SYNC_PARENT_SOUNDS_VALIDATOR);
VALIDATORS.put(CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED_VALIDATOR);
+ VALIDATORS.put(SWIPE_UP_TO_SWITCH_APPS_ENABLED,
+ SWIPE_UP_TO_SWITCH_APPS_ENABLED_VALIDATOR);
VALIDATORS.put(CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED_VALIDATOR);
VALIDATORS.put(SYSTEM_NAVIGATION_KEYS_ENABLED,
@@ -8935,6 +8967,20 @@
/** {@hide} */
public static final String NETSTATS_UID_TAG_DELETE_AGE = "netstats_uid_tag_delete_age";
+ /** {@hide} */
+ public static final String NETPOLICY_QUOTA_ENABLED = "netpolicy_quota_enabled";
+ /** {@hide} */
+ public static final String NETPOLICY_QUOTA_UNLIMITED = "netpolicy_quota_unlimited";
+ /** {@hide} */
+ public static final String NETPOLICY_QUOTA_LIMITED = "netpolicy_quota_limited";
+ /** {@hide} */
+ public static final String NETPOLICY_QUOTA_FRAC_JOBS = "netpolicy_quota_frac_jobs";
+ /** {@hide} */
+ public static final String NETPOLICY_QUOTA_FRAC_MULTIPATH = "netpolicy_quota_frac_multipath";
+
+ /** {@hide} */
+ public static final String NETPOLICY_OVERRIDE_ENABLED = "netpolicy_override_enabled";
+
/**
* User preference for which network(s) should be used. Only the
* connectivity service should touch this.
@@ -10806,6 +10852,15 @@
= "time_only_mode_constants";
/**
+ * Whether of not to send keycode sleep for ungaze when Home is the foreground activity on
+ * watch type devices.
+ * Type: int (0 for false, 1 for true)
+ * Default: 0
+ * @hide
+ */
+ public static final String UNGAZE_SLEEP_ENABLED = "ungaze_sleep_enabled";
+
+ /**
* Whether or not Network Watchlist feature is enabled.
* Type: int (0 for false, 1 for true)
* Default: 0
@@ -11085,6 +11140,14 @@
public static final String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
/**
+ * If nonzero, all system error dialogs will be hidden. For example, the
+ * crash and ANR dialogs will not be shown, and the system will just proceed
+ * as if they had been accepted by the user.
+ * @hide
+ */
+ public static final String HIDE_ERROR_DIALOGS = "hide_error_dialogs";
+
+ /**
* Use Dock audio output for media:
* 0 = disabled
* 1 = enabled
@@ -11703,6 +11766,29 @@
"hidden_api_blacklist_exemptions";
/**
+ * Hidden API enforcement policy for apps targeting SDK versions prior to the latest
+ * version.
+ *
+ * Values correspond to @{@link
+ * android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
+ *
+ * @hide
+ */
+ public static final String HIDDEN_API_POLICY_PRE_P_APPS =
+ "hidden_api_policy_pre_p_apps";
+
+ /**
+ * Hidden API enforcement policy for apps targeting the current SDK version.
+ *
+ * Values correspond to @{@link
+ * android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
+ *
+ * @hide
+ */
+ public static final String HIDDEN_API_POLICY_P_APPS =
+ "hidden_api_policy_p_apps";
+
+ /**
* Timeout for a single {@link android.media.soundtrigger.SoundTriggerDetectionService}
* operation (in ms).
*
diff --git a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
index 73a6a74..9334aa9 100644
--- a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
+++ b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
@@ -118,7 +118,7 @@
*
* See implementation for binary key format.
*
- * @removed Use {@link #getTrustedHardwareCertPath} instead.
+ * @deprecated Use {@link #getTrustedHardwareCertPath} instead.
*/
@Deprecated
public @NonNull byte[] getTrustedHardwarePublicKey() {
@@ -227,7 +227,7 @@
*
* @param publicKey The public key
* @return This builder.
- * @removed Use {@link #setTrustedHardwareCertPath} instead.
+ * @deprecated Use {@link #setTrustedHardwareCertPath} instead.
*/
@Deprecated
public Builder setTrustedHardwarePublicKey(byte[] publicKey) {
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index 2c48bf4..f351c5a 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -288,7 +288,7 @@
}
/**
- * @removed Use {@link #initRecoveryService(String, byte[], byte[])} instead.
+ * @deprecated Use {@link #initRecoveryService(String, byte[], byte[])} instead.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
@@ -359,7 +359,7 @@
}
/**
- * @removed Use {@link #getKeyChainSnapshot()}
+ * @deprecated Use {@link #getKeyChainSnapshot()}
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
@@ -435,7 +435,7 @@
}
/**
- * @removed Use {@link #getAliases()}.
+ * @deprecated Use {@link #getAliases()}.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
@@ -460,7 +460,7 @@
}
/**
- * @removed Use {@link #setRecoveryStatus(String, int)}
+ * @deprecated Use {@link #setRecoveryStatus(String, int)}
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
@@ -494,7 +494,7 @@
}
/**
- * @removed Use {@link #getRecoveryStatus(String)}.
+ * @deprecated Use {@link #getRecoveryStatus(String)}.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
@@ -576,7 +576,26 @@
}
/**
- * @removed Use {@link #generateKey(String)}.
+ * Deprecated.
+ * Generates a AES256/GCM/NoPADDING key called {@code alias} and loads it into the recoverable
+ * key store. Returns the raw material of the key.
+ *
+ * @param alias The key alias.
+ * @param account The account associated with the key
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ * @throws LockScreenRequiredException if the user has not set a lock screen. This is required
+ * to generate recoverable keys, as the snapshots are encrypted using a key derived from the
+ * lock screen.
+ */
+ @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+ public byte[] generateAndStoreKey(@NonNull String alias, byte[] account)
+ throws InternalRecoveryServiceException, LockScreenRequiredException {
+ throw new UnsupportedOperationException("Operation is not supported, use generateKey");
+ }
+
+ /**
+ * @deprecated Use {@link #generateKey(String)}.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
diff --git a/core/java/android/security/keystore/recovery/RecoverySession.java b/core/java/android/security/keystore/recovery/RecoverySession.java
index 87dc6b4..8353389 100644
--- a/core/java/android/security/keystore/recovery/RecoverySession.java
+++ b/core/java/android/security/keystore/recovery/RecoverySession.java
@@ -78,7 +78,7 @@
}
/**
- * @removed Use {@link #start(String, CertPath, byte[], byte[], List)} instead.
+ * @deprecated Use {@link #start(String, CertPath, byte[], byte[], List)} instead.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
@@ -109,7 +109,7 @@
}
/**
- * @removed Use {@link #start(String, CertPath, byte[], byte[], List)} instead.
+ * @deprecated Use {@link #start(String, CertPath, byte[], byte[], List)} instead.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
@@ -198,7 +198,7 @@
}
/**
- * @removed Use {@link #recoverKeyChainSnapshot(byte[], List)} instead.
+ * @deprecated Use {@link #recoverKeyChainSnapshot(byte[], List)} instead.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
index 86419d8..32952db 100644
--- a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
@@ -75,7 +75,7 @@
}
/**
- * @removed AOSP does not associate keys with accounts. This may be done by system app.
+ * @deprecated AOSP does not associate keys with accounts. This may be done by system app.
*/
@Deprecated
public Builder setAccount(@NonNull byte[] account) {
@@ -133,7 +133,7 @@
}
/**
- * @removed AOSP does not associate keys with accounts. This may be done by system app.
+ * @deprecated AOSP does not associate keys with accounts. This may be done by system app.
*/
@Deprecated
public @NonNull byte[] getAccount() {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 3726e66..32737c5 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -28,6 +28,7 @@
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
+import android.app.Person;
import android.app.Service;
import android.companion.CompanionDeviceManager;
import android.content.ComponentName;
@@ -1195,13 +1196,13 @@
*/
private void maybePopulatePeople(Notification notification) {
if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P) {
- ArrayList<Notification.Person> people = notification.extras.getParcelableArrayList(
+ ArrayList<Person> people = notification.extras.getParcelableArrayList(
Notification.EXTRA_PEOPLE_LIST);
if (people != null && people.isEmpty()) {
int size = people.size();
String[] peopleArray = new String[size];
for (int i = 0; i < size; i++) {
- Notification.Person person = people.get(i);
+ Person person = people.get(i);
peopleArray[i] = person.resolveToLegacyUri();
}
notification.extras.putStringArray(Notification.EXTRA_PEOPLE, peopleArray);
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 3830b7a..daecea7 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1487,14 +1487,18 @@
/**
* Returns a description of the current do not disturb settings from config.
* - If turned on manually and end time is known, returns end time.
+ * - If turned on manually and end time is on forever until turned off, return null if
+ * describeForeverCondition is false, else return String describing indefinite behavior
* - If turned on by an automatic rule, returns the automatic rule name.
* - If on due to an app, returns the app name.
* - If there's a combination of rules/apps that trigger, then shows the one that will
* last the longest if applicable.
- * @return null if do not disturb is off.
+ * @return null if DND is off or describeForeverCondition is false and
+ * DND is on forever (until turned off)
*/
- public static String getDescription(Context context, boolean zenOn, ZenModeConfig config) {
- if (!zenOn) {
+ public static String getDescription(Context context, boolean zenOn, ZenModeConfig config,
+ boolean describeForeverCondition) {
+ if (!zenOn || config == null) {
return null;
}
@@ -1513,8 +1517,11 @@
} else {
if (id == null) {
// Do not disturb manually triggered to remain on forever until turned off
- // No subtext
- return null;
+ if (describeForeverCondition) {
+ return context.getString(R.string.zen_mode_forever);
+ } else {
+ return null;
+ }
} else {
latestEndTime = tryParseCountdownConditionId(id);
if (latestEndTime > 0) {
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 3445658..5256e47 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -180,7 +180,7 @@
* Remove the selection or cursor, if any, from the text.
*/
public static final void removeSelection(Spannable text) {
- text.removeSpan(SELECTION_START);
+ text.removeSpan(SELECTION_START, Spanned.SPAN_INTERMEDIATE);
text.removeSpan(SELECTION_END);
removeMemory(text);
}
diff --git a/core/java/android/text/Spannable.java b/core/java/android/text/Spannable.java
index 39b78eb..8315b2a 100644
--- a/core/java/android/text/Spannable.java
+++ b/core/java/android/text/Spannable.java
@@ -46,6 +46,19 @@
public void removeSpan(Object what);
/**
+ * Remove the specified object from the range of text to which it
+ * was attached, if any. It is OK to remove an object that was never
+ * attached in the first place.
+ *
+ * See {@link Spanned} for an explanation of what the flags mean.
+ *
+ * @hide
+ */
+ default void removeSpan(Object what, int flags) {
+ removeSpan(what);
+ }
+
+ /**
* Factory used by TextView to create new {@link Spannable Spannables}. You can subclass
* it to provide something other than {@link SpannableString}.
*
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index d41dfdc..41a9c45 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -312,7 +312,7 @@
// The following condition indicates that the span would become empty
(textIsRemoved || mSpanStarts[i] > start || mSpanEnds[i] < mGapStart)) {
mIndexOfSpan.remove(mSpans[i]);
- removeSpan(i);
+ removeSpan(i, 0 /* flags */);
return true;
}
return resolveGap(mSpanStarts[i]) <= end && (i & 1) != 0 &&
@@ -472,7 +472,7 @@
}
// Note: caller is responsible for removing the mIndexOfSpan entry.
- private void removeSpan(int i) {
+ private void removeSpan(int i, int flags) {
Object object = mSpans[i];
int start = mSpanStarts[i];
@@ -496,7 +496,9 @@
// Invariants must be restored before sending span removed notifications.
restoreInvariants();
- sendSpanRemoved(object, start, end);
+ if ((flags & Spanned.SPAN_INTERMEDIATE) == 0) {
+ sendSpanRemoved(object, start, end);
+ }
}
// Documentation from interface
@@ -782,10 +784,19 @@
* Remove the specified markup object from the buffer.
*/
public void removeSpan(Object what) {
+ removeSpan(what, 0 /* flags */);
+ }
+
+ /**
+ * Remove the specified markup object from the buffer.
+ *
+ * @hide
+ */
+ public void removeSpan(Object what, int flags) {
if (mIndexOfSpan == null) return;
Integer i = mIndexOfSpan.remove(what);
if (i != null) {
- removeSpan(i.intValue());
+ removeSpan(i.intValue(), flags);
}
}
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 5dd1a52..bcc2fda 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -249,6 +249,13 @@
}
/* package */ void removeSpan(Object what) {
+ removeSpan(what, 0 /* flags */);
+ }
+
+ /**
+ * @hide
+ */
+ public void removeSpan(Object what, int flags) {
int count = mSpanCount;
Object[] spans = mSpans;
int[] data = mSpanData;
@@ -262,11 +269,13 @@
System.arraycopy(spans, i + 1, spans, i, c);
System.arraycopy(data, (i + 1) * COLUMNS,
- data, i * COLUMNS, c * COLUMNS);
+ data, i * COLUMNS, c * COLUMNS);
mSpanCount--;
- sendSpanRemoved(what, ostart, oend);
+ if ((flags & Spanned.SPAN_INTERMEDIATE) == 0) {
+ sendSpanRemoved(what, ostart, oend);
+ }
return;
}
}
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index ad3b4b6..de86a66 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -40,6 +40,10 @@
public static final int FLAG_SHORTER = 1 << 0;
/** {@hide} */
public static final int FLAG_CALCULATE_ROUNDED = 1 << 1;
+ /** {@hide} */
+ public static final int FLAG_SI_UNITS = 1 << 2;
+ /** {@hide} */
+ public static final int FLAG_IEC_UNITS = 1 << 3;
/** {@hide} */
public static class BytesResult {
@@ -90,7 +94,7 @@
if (context == null) {
return "";
}
- final BytesResult res = formatBytes(context.getResources(), sizeBytes, 0);
+ final BytesResult res = formatBytes(context.getResources(), sizeBytes, FLAG_SI_UNITS);
return bidiWrap(context, context.getString(com.android.internal.R.string.fileSizeSuffix,
res.value, res.units));
}
@@ -103,41 +107,43 @@
if (context == null) {
return "";
}
- final BytesResult res = formatBytes(context.getResources(), sizeBytes, FLAG_SHORTER);
+ final BytesResult res = formatBytes(context.getResources(), sizeBytes,
+ FLAG_SI_UNITS | FLAG_SHORTER);
return bidiWrap(context, context.getString(com.android.internal.R.string.fileSizeSuffix,
res.value, res.units));
}
/** {@hide} */
public static BytesResult formatBytes(Resources res, long sizeBytes, int flags) {
+ final int unit = ((flags & FLAG_IEC_UNITS) != 0) ? 1024 : 1000;
final boolean isNegative = (sizeBytes < 0);
float result = isNegative ? -sizeBytes : sizeBytes;
int suffix = com.android.internal.R.string.byteShort;
long mult = 1;
if (result > 900) {
suffix = com.android.internal.R.string.kilobyteShort;
- mult = 1000;
- result = result / 1000;
+ mult = unit;
+ result = result / unit;
}
if (result > 900) {
suffix = com.android.internal.R.string.megabyteShort;
- mult *= 1000;
- result = result / 1000;
+ mult *= unit;
+ result = result / unit;
}
if (result > 900) {
suffix = com.android.internal.R.string.gigabyteShort;
- mult *= 1000;
- result = result / 1000;
+ mult *= unit;
+ result = result / unit;
}
if (result > 900) {
suffix = com.android.internal.R.string.terabyteShort;
- mult *= 1000;
- result = result / 1000;
+ mult *= unit;
+ result = result / unit;
}
if (result > 900) {
suffix = com.android.internal.R.string.petabyteShort;
- mult *= 1000;
- result = result / 1000;
+ mult *= unit;
+ result = result / unit;
}
// Note we calculate the rounded long by ourselves, but still let String.format()
// compute the rounded value. String.format("%f", 0.1) might not return "0.1" due to
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index 9c6a3f5..c905f49 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -100,13 +100,20 @@
* take an options mask. Note that this uses the
* {@link android.webkit.WebView#findAddress(String) findAddress()} method in
* {@link android.webkit.WebView} for finding addresses, which has various
- * limitations.
+ * limitations and has been deprecated.
+ * @deprecated use {@link android.view.textclassifier.TextClassifier#generateLinks(
+ * TextLinks.Request)} instead and avoid it even when targeting API levels where no alternative
+ * is available.
*/
+ @Deprecated
public static final int MAP_ADDRESSES = 0x08;
/**
* Bit mask indicating that all available patterns should be matched in
* methods that take an options mask
+ * <p><strong>Note:</strong></p> {@link #MAP_ADDRESSES} is deprecated.
+ * Use {@link android.view.textclassifier.TextClassifier#generateLinks(TextLinks.Request)}
+ * instead and avoid it even when targeting API levels where no alternative is available.
*/
public static final int ALL = WEB_URLS | EMAIL_ADDRESSES | PHONE_NUMBERS | MAP_ADDRESSES;
diff --git a/core/java/android/util/RecurrenceRule.java b/core/java/android/util/RecurrenceRule.java
index 9f115eb..975ad48 100644
--- a/core/java/android/util/RecurrenceRule.java
+++ b/core/java/android/util/RecurrenceRule.java
@@ -158,7 +158,7 @@
&& period.getDays() == 0;
}
- public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() {
+ public Iterator<Range<ZonedDateTime>> cycleIterator() {
if (period != null) {
return new RecurringIterator();
} else {
@@ -166,7 +166,7 @@
}
}
- private class NonrecurringIterator implements Iterator<Pair<ZonedDateTime, ZonedDateTime>> {
+ private class NonrecurringIterator implements Iterator<Range<ZonedDateTime>> {
boolean hasNext;
public NonrecurringIterator() {
@@ -179,13 +179,13 @@
}
@Override
- public Pair<ZonedDateTime, ZonedDateTime> next() {
+ public Range<ZonedDateTime> next() {
hasNext = false;
- return new Pair<>(start, end);
+ return new Range<>(start, end);
}
}
- private class RecurringIterator implements Iterator<Pair<ZonedDateTime, ZonedDateTime>> {
+ private class RecurringIterator implements Iterator<Range<ZonedDateTime>> {
int i;
ZonedDateTime cycleStart;
ZonedDateTime cycleEnd;
@@ -231,12 +231,12 @@
}
@Override
- public Pair<ZonedDateTime, ZonedDateTime> next() {
+ public Range<ZonedDateTime> next() {
if (LOGD) Log.d(TAG, "Cycle " + i + " from " + cycleStart + " to " + cycleEnd);
- Pair<ZonedDateTime, ZonedDateTime> p = new Pair<>(cycleStart, cycleEnd);
+ Range<ZonedDateTime> r = new Range<>(cycleStart, cycleEnd);
i--;
updateCycle();
- return p;
+ return r;
}
}
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index b147928..db01cea 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -77,6 +77,55 @@
public static final int TEXT_HANDLE_MOVE = 9;
/**
+ * The user unlocked the device
+ * @hide
+ */
+ public static final int ENTRY_BUMP = 10;
+
+ /**
+ * The user has moved the dragged object within a droppable area.
+ * @hide
+ */
+ public static final int DRAG_CROSSING = 11;
+
+ /**
+ * The user has started a gesture (e.g. on the soft keyboard).
+ * @hide
+ */
+ public static final int GESTURE_START = 12;
+
+ /**
+ * The user has finished a gesture (e.g. on the soft keyboard).
+ * @hide
+ */
+ public static final int GESTURE_END = 13;
+
+ /**
+ * The user's squeeze crossed the gesture's initiation threshold.
+ * @hide
+ */
+ public static final int EDGE_SQUEEZE = 14;
+
+ /**
+ * The user's squeeze crossed the gesture's release threshold.
+ * @hide
+ */
+ public static final int EDGE_RELEASE = 15;
+
+ /**
+ * A haptic effect to signal the confirmation or successful completion of a user
+ * interaction.
+ * @hide
+ */
+ public static final int CONFIRM = 16;
+
+ /**
+ * A haptic effect to signal the rejection or failure of a user interaction.
+ * @hide
+ */
+ public static final int REJECT = 17;
+
+ /**
* The phone has booted with safe mode enabled.
* This is a private constant. Feel free to renumber as desired.
* @hide
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d4610a5..5deee11 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -87,6 +87,7 @@
private static native void nativeMergeTransaction(long transactionObj,
long otherTransactionObj);
private static native void nativeSetAnimationTransaction(long transactionObj);
+ private static native void nativeSetEarlyWakeup(long transactionObj);
private static native void nativeSetLayer(long transactionObj, long nativeObject, int zorder);
private static native void nativeSetRelativeLayer(long transactionObj, long nativeObject,
@@ -1642,6 +1643,19 @@
}
/**
+ * Indicate that SurfaceFlinger should wake up earlier than usual as a result of this
+ * transaction. This should be used when the caller thinks that the scene is complex enough
+ * that it's likely to hit GL composition, and thus, SurfaceFlinger needs to more time in
+ * order not to miss frame deadlines.
+ * <p>
+ * Corresponds to setting ISurfaceComposer::eEarlyWakeup
+ */
+ public Transaction setEarlyWakeup() {
+ nativeSetEarlyWakeup(mNativeObject);
+ return this;
+ }
+
+ /**
* Merge the other transaction into this transaction, clearing the
* other transaction as if it had been applied.
*/
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 5eb7e9c..e03f5fa 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -190,6 +190,10 @@
*/
public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor";
+ public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
+ public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
+ public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
+
static {
// Try to check OpenGL support early if possible.
isAvailable();
@@ -1140,6 +1144,16 @@
nHackySetRTAnimationsEnabled(divisor <= 1);
}
+ /**
+ * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
+ * called before any OpenGL context is created.
+ *
+ * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
+ */
+ public static void setContextPriority(int priority) {
+ nSetContextPriority(priority);
+ }
+
/** Not actually public - internal use only. This doc to make lint happy */
public static native void disableVsync();
@@ -1213,4 +1227,5 @@
private static native void nHackySetRTAnimationsEnabled(boolean enabled);
private static native void nSetDebuggingEnabled(boolean enabled);
private static native void nSetIsolatedProcess(boolean enabled);
+ private static native void nSetContextPriority(int priority);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 97e11b1..dc58f11 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10398,7 +10398,21 @@
*
* @param willNotCacheDrawing true if this view does not cache its
* drawing, false otherwise
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
}
@@ -10407,8 +10421,22 @@
* Returns whether or not this View can cache its drawing or not.
*
* @return true if this view does not cache its drawing, false otherwise
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
@ViewDebug.ExportedProperty(category = "drawing")
+ @Deprecated
public boolean willNotCacheDrawing() {
return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
}
diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java
index 9b49248..a6495d1 100644
--- a/core/java/android/view/autofill/AutofillPopupWindow.java
+++ b/core/java/android/view/autofill/AutofillPopupWindow.java
@@ -79,9 +79,8 @@
public AutofillPopupWindow(@NonNull IAutofillWindowPresenter presenter) {
mWindowPresenter = new WindowPresenter(presenter);
- // Here is a bit of voodoo - we want to show the window as system
- // controlled one so it covers app windows, but at the same time it has to be
- // an application type (so it's contained inside the application area).
+ // We want to show the window as system controlled one so it covers app windows, but it has
+ // to be an application type (so it's contained inside the application area).
// Hence, we set it to the application type with the highest z-order, which currently
// is TYPE_APPLICATION_ABOVE_SUB_PANEL.
setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 5f7a0f7..090e19f 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -522,7 +522,7 @@
b = tmp;
}
- if (a == b) return null;
+ if (a == b || a < 0) return null;
if ((flags&GET_TEXT_WITH_STYLES) != 0) {
return content.subSequence(a, b);
diff --git a/core/java/android/view/textclassifier/GenerateLinksLogger.java b/core/java/android/view/textclassifier/GenerateLinksLogger.java
index 73cf43b..067513f 100644
--- a/core/java/android/view/textclassifier/GenerateLinksLogger.java
+++ b/core/java/android/view/textclassifier/GenerateLinksLogger.java
@@ -19,13 +19,13 @@
import android.annotation.Nullable;
import android.metrics.LogMaker;
import android.util.ArrayMap;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
@@ -39,6 +39,7 @@
public final class GenerateLinksLogger {
private static final String LOG_TAG = "GenerateLinksLogger";
+ private static final boolean DEBUG_LOG_ENABLED = false;
private static final String ZERO = "0";
private final MetricsLogger mMetricsLogger;
@@ -127,7 +128,7 @@
}
private static void debugLog(LogMaker log) {
- if (!Logger.DEBUG_LOG_ENABLED) return;
+ if (!DEBUG_LOG_ENABLED) return;
final String callId = Objects.toString(
log.getTaggedData(MetricsEvent.FIELD_LINKIFY_CALL_ID), "");
@@ -142,8 +143,9 @@
final int latencyMs = Integer.parseInt(
Objects.toString(log.getTaggedData(MetricsEvent.FIELD_LINKIFY_LATENCY), ZERO));
- Log.d(LOG_TAG, String.format("%s:%s %d links (%d/%d chars) %dms %s", callId, entityType,
- numLinks, linkLength, textLength, latencyMs, log.getPackageName()));
+ Log.d(LOG_TAG,
+ String.format(Locale.US, "%s:%s %d links (%d/%d chars) %dms %s", callId, entityType,
+ numLinks, linkLength, textLength, latencyMs, log.getPackageName()));
}
/** Helper class for storing per-entity type statistics. */
diff --git a/core/java/android/view/textclassifier/Logger.java b/core/java/android/view/textclassifier/Logger.java
deleted file mode 100644
index f03906a..0000000
--- a/core/java/android/view/textclassifier/Logger.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.textclassifier;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-
-import com.android.internal.util.Preconditions;
-
-import java.text.BreakIterator;
-import java.util.Locale;
-import java.util.Objects;
-
-/**
- * A helper for logging TextClassifier related events.
- * @hide
- */
-public abstract class Logger {
-
- private static final String LOG_TAG = "Logger";
- /* package */ static final boolean DEBUG_LOG_ENABLED = true;
-
- private @SelectionEvent.InvocationMethod int mInvocationMethod;
- private SelectionEvent mPrevEvent;
- private SelectionEvent mSmartEvent;
- private SelectionEvent mStartEvent;
-
- /**
- * Logger that does not log anything.
- * @hide
- */
- public static final Logger DISABLED = new Logger() {
- @Override
- public void writeEvent(SelectionEvent event) {}
- };
-
- @Nullable
- private final Config mConfig;
-
- public Logger(Config config) {
- mConfig = Preconditions.checkNotNull(config);
- }
-
- private Logger() {
- mConfig = null;
- }
-
- /**
- * Writes the selection event to a log.
- */
- public abstract void writeEvent(@NonNull SelectionEvent event);
-
- /**
- * Returns true if the resultId matches that of a smart selection event (i.e.
- * {@link SelectionEvent#EVENT_SMART_SELECTION_SINGLE} or
- * {@link SelectionEvent#EVENT_SMART_SELECTION_MULTI}).
- * Returns false otherwise.
- */
- public boolean isSmartSelection(@NonNull String resultId) {
- return false;
- }
-
- /**
- * Returns a token iterator for tokenizing text for logging purposes.
- */
- public BreakIterator getTokenIterator(@NonNull Locale locale) {
- return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale));
- }
-
- /**
- * Logs a "selection started" event.
- *
- * @param invocationMethod the way the selection was triggered
- * @param start the token index of the selected token
- */
- public final void logSelectionStartedEvent(
- @SelectionEvent.InvocationMethod int invocationMethod, int start) {
- if (mConfig == null) {
- return;
- }
-
- mInvocationMethod = invocationMethod;
- logEvent(new SelectionEvent(
- start, start + 1, SelectionEvent.EVENT_SELECTION_STARTED,
- TextClassifier.TYPE_UNKNOWN, mInvocationMethod, null, mConfig));
- }
-
- /**
- * Logs a "selection modified" event.
- * Use when the user modifies the selection.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- */
- public final void logSelectionModifiedEvent(int start, int end) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
-
- if (mConfig == null) {
- return;
- }
-
- logEvent(new SelectionEvent(
- start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
- TextClassifier.TYPE_UNKNOWN, mInvocationMethod, null, mConfig));
- }
-
- /**
- * Logs a "selection modified" event.
- * Use when the user modifies the selection and the selection's entity type is known.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- * @param classification the TextClassification object returned by the TextClassifier that
- * classified the selected text
- */
- public final void logSelectionModifiedEvent(
- int start, int end, @NonNull TextClassification classification) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(classification);
-
- if (mConfig == null) {
- return;
- }
-
- final String entityType = classification.getEntityCount() > 0
- ? classification.getEntity(0)
- : TextClassifier.TYPE_UNKNOWN;
- logEvent(new SelectionEvent(
- start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
- entityType, mInvocationMethod, classification.getId(), mConfig));
- }
-
- /**
- * Logs a "selection modified" event.
- * Use when a TextClassifier modifies the selection.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- * @param selection the TextSelection object returned by the TextClassifier for the
- * specified selection
- */
- public final void logSelectionModifiedEvent(
- int start, int end, @NonNull TextSelection selection) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(selection);
-
- if (mConfig == null) {
- return;
- }
-
- final int eventType;
- if (isSmartSelection(selection.getId())) {
- eventType = end - start > 1
- ? SelectionEvent.EVENT_SMART_SELECTION_MULTI
- : SelectionEvent.EVENT_SMART_SELECTION_SINGLE;
-
- } else {
- eventType = SelectionEvent.EVENT_AUTO_SELECTION;
- }
- final String entityType = selection.getEntityCount() > 0
- ? selection.getEntity(0)
- : TextClassifier.TYPE_UNKNOWN;
- logEvent(new SelectionEvent(start, end, eventType, entityType, mInvocationMethod,
- selection.getId(), mConfig));
- }
-
- /**
- * Logs an event specifying an action taken on a selection.
- * Use when the user clicks on an action to act on the selected text.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- * @param actionType the action that was performed on the selection
- */
- public final void logSelectionActionEvent(
- int start, int end, @SelectionEvent.ActionType int actionType) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
- checkActionType(actionType);
-
- if (mConfig == null) {
- return;
- }
-
- logEvent(new SelectionEvent(
- start, end, actionType, TextClassifier.TYPE_UNKNOWN, mInvocationMethod,
- null, mConfig));
- }
-
- /**
- * Logs an event specifying an action taken on a selection.
- * Use when the user clicks on an action to act on the selected text and the selection's
- * entity type is known.
- *
- * @param start the start token (inclusive) index of the selection
- * @param end the end token (exclusive) index of the selection
- * @param actionType the action that was performed on the selection
- * @param classification the TextClassification object returned by the TextClassifier that
- * classified the selected text
- *
- * @throws IllegalArgumentException If actionType is not a valid SelectionEvent actionType
- */
- public final void logSelectionActionEvent(
- int start, int end, @SelectionEvent.ActionType int actionType,
- @NonNull TextClassification classification) {
- Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(classification);
- checkActionType(actionType);
-
- if (mConfig == null) {
- return;
- }
-
- final String entityType = classification.getEntityCount() > 0
- ? classification.getEntity(0)
- : TextClassifier.TYPE_UNKNOWN;
- logEvent(new SelectionEvent(start, end, actionType, entityType, mInvocationMethod,
- classification.getId(), mConfig));
- }
-
- private void logEvent(@NonNull SelectionEvent event) {
- Preconditions.checkNotNull(event);
-
- if (event.getEventType() != SelectionEvent.EVENT_SELECTION_STARTED
- && mStartEvent == null) {
- if (DEBUG_LOG_ENABLED) {
- Log.d(LOG_TAG, "Selection session not yet started. Ignoring event");
- }
- return;
- }
-
- final long now = System.currentTimeMillis();
- switch (event.getEventType()) {
- case SelectionEvent.EVENT_SELECTION_STARTED:
- Preconditions.checkArgument(event.getAbsoluteEnd() == event.getAbsoluteStart() + 1);
- event.setSessionId(startNewSession());
- mStartEvent = event;
- break;
- case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: // fall through
- case SelectionEvent.EVENT_SMART_SELECTION_MULTI:
- mSmartEvent = event;
- break;
- case SelectionEvent.EVENT_SELECTION_MODIFIED: // fall through
- case SelectionEvent.EVENT_AUTO_SELECTION:
- if (mPrevEvent != null
- && mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart()
- && mPrevEvent.getAbsoluteEnd() == event.getAbsoluteEnd()) {
- // Selection did not change. Ignore event.
- return;
- }
- break;
- default:
- // do nothing.
- }
-
- event.setEventTime(now);
- if (mStartEvent != null) {
- event.setSessionId(mStartEvent.getSessionId())
- .setDurationSinceSessionStart(now - mStartEvent.getEventTime())
- .setStart(event.getAbsoluteStart() - mStartEvent.getAbsoluteStart())
- .setEnd(event.getAbsoluteEnd() - mStartEvent.getAbsoluteStart());
- }
- if (mSmartEvent != null) {
- event.setResultId(mSmartEvent.getResultId())
- .setSmartStart(mSmartEvent.getAbsoluteStart() - mStartEvent.getAbsoluteStart())
- .setSmartEnd(mSmartEvent.getAbsoluteEnd() - mStartEvent.getAbsoluteStart());
- }
- if (mPrevEvent != null) {
- event.setDurationSincePreviousEvent(now - mPrevEvent.getEventTime())
- .setEventIndex(mPrevEvent.getEventIndex() + 1);
- }
- writeEvent(event);
- mPrevEvent = event;
-
- if (event.isTerminal()) {
- endSession();
- }
- }
-
- private TextClassificationSessionId startNewSession() {
- endSession();
- return new TextClassificationSessionId();
- }
-
- private void endSession() {
- mPrevEvent = null;
- mSmartEvent = null;
- mStartEvent = null;
- }
-
- /**
- * @throws IllegalArgumentException If eventType is not an {@link SelectionEvent.ActionType}
- */
- private static void checkActionType(@SelectionEvent.EventType int eventType)
- throws IllegalArgumentException {
- switch (eventType) {
- case SelectionEvent.ACTION_OVERTYPE: // fall through
- case SelectionEvent.ACTION_COPY: // fall through
- case SelectionEvent.ACTION_PASTE: // fall through
- case SelectionEvent.ACTION_CUT: // fall through
- case SelectionEvent.ACTION_SHARE: // fall through
- case SelectionEvent.ACTION_SMART_SHARE: // fall through
- case SelectionEvent.ACTION_DRAG: // fall through
- case SelectionEvent.ACTION_ABANDON: // fall through
- case SelectionEvent.ACTION_SELECT_ALL: // fall through
- case SelectionEvent.ACTION_RESET: // fall through
- return;
- default:
- throw new IllegalArgumentException(
- String.format(Locale.US, "%d is not an eventType", eventType));
- }
- }
-
-
- /**
- * A Logger config.
- */
- public static final class Config {
-
- private final String mPackageName;
- private final String mWidgetType;
- @Nullable private final String mWidgetVersion;
-
- /**
- * @param context Context of the widget the logger logs for
- * @param widgetType a name for the widget being logged for. e.g.
- * {@link TextClassifier#WIDGET_TYPE_TEXTVIEW}
- * @param widgetVersion a string version info for the widget the logger logs for
- */
- public Config(
- @NonNull Context context,
- @TextClassifier.WidgetType String widgetType,
- @Nullable String widgetVersion) {
- mPackageName = Preconditions.checkNotNull(context).getPackageName();
- mWidgetType = widgetType;
- mWidgetVersion = widgetVersion;
- }
-
- /**
- * Returns the package name of the application the logger logs for.
- */
- public String getPackageName() {
- return mPackageName;
- }
-
- /**
- * Returns the name for the widget being logged for. e.g.
- * {@link TextClassifier#WIDGET_TYPE_TEXTVIEW}.
- */
- public String getWidgetType() {
- return mWidgetType;
- }
-
- /**
- * Returns string version info for the logger. This is specific to the text classifier.
- */
- @Nullable
- public String getWidgetVersion() {
- return mWidgetVersion;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mPackageName, mWidgetType, mWidgetVersion);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (!(obj instanceof Config)) {
- return false;
- }
-
- final Config other = (Config) obj;
- return Objects.equals(mPackageName, other.mPackageName)
- && Objects.equals(mWidgetType, other.mWidgetType)
- && Objects.equals(mWidgetVersion, other.mWidgetType);
- }
- }
-}
diff --git a/core/java/android/view/textclassifier/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
index 1e978cc..b073596 100644
--- a/core/java/android/view/textclassifier/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -150,20 +150,6 @@
mInvocationMethod = invocationMethod;
}
- SelectionEvent(
- int start, int end,
- @EventType int eventType, @EntityType String entityType,
- @InvocationMethod int invocationMethod, @Nullable String resultId,
- Logger.Config config) {
- this(start, end, eventType, entityType, invocationMethod, resultId);
- Preconditions.checkNotNull(config);
- setTextClassificationSessionContext(
- new TextClassificationContext.Builder(
- config.getPackageName(), config.getWidgetType())
- .setWidgetVersion(config.getWidgetVersion())
- .build());
- }
-
private SelectionEvent(Parcel in) {
mAbsoluteStart = in.readInt();
mAbsoluteEnd = in.readInt();
@@ -362,6 +348,7 @@
case SelectionEvent.ACTION_ABANDON: // fall through
case SelectionEvent.ACTION_SELECT_ALL: // fall through
case SelectionEvent.ACTION_RESET: // fall through
+ case SelectionEvent.ACTION_OTHER: // fall through
return;
default:
throw new IllegalArgumentException(
@@ -667,4 +654,4 @@
return new SelectionEvent[size];
}
};
-}
\ No newline at end of file
+}
diff --git a/core/java/android/view/textclassifier/DefaultLogger.java b/core/java/android/view/textclassifier/SelectionSessionLogger.java
similarity index 88%
rename from core/java/android/view/textclassifier/DefaultLogger.java
rename to core/java/android/view/textclassifier/SelectionSessionLogger.java
index 203ca56..f2fb63e 100644
--- a/core/java/android/view/textclassifier/DefaultLogger.java
+++ b/core/java/android/view/textclassifier/SelectionSessionLogger.java
@@ -17,28 +17,29 @@
package android.view.textclassifier;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.metrics.LogMaker;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
+import java.text.BreakIterator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.StringJoiner;
/**
- * Default Logger.
- * Used internally by TextClassifierImpl.
+ * A helper for logging selection session events.
* @hide
*/
-public final class DefaultLogger extends Logger {
+public final class SelectionSessionLogger {
- private static final String LOG_TAG = "DefaultLogger";
+ private static final String LOG_TAG = "SelectionSessionLogger";
+ private static final boolean DEBUG_LOG_ENABLED = false;
static final String CLASSIFIER_ID = "androidtc";
private static final int START_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_START;
@@ -59,23 +60,16 @@
private final MetricsLogger mMetricsLogger;
- public DefaultLogger(@NonNull Config config) {
- super(config);
+ public SelectionSessionLogger() {
mMetricsLogger = new MetricsLogger();
}
@VisibleForTesting
- public DefaultLogger(@NonNull Config config, @NonNull MetricsLogger metricsLogger) {
- super(config);
+ public SelectionSessionLogger(@NonNull MetricsLogger metricsLogger) {
mMetricsLogger = Preconditions.checkNotNull(metricsLogger);
}
- @Override
- public boolean isSmartSelection(@NonNull String signature) {
- return CLASSIFIER_ID.equals(SignatureParser.getClassifierId(signature));
- }
-
- @Override
+ /** Emits a selection event to the logs. */
public void writeEvent(@NonNull SelectionEvent event) {
Preconditions.checkNotNull(event);
final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION)
@@ -93,7 +87,7 @@
.addTaggedData(SMART_END, event.getSmartEnd())
.addTaggedData(EVENT_START, event.getStart())
.addTaggedData(EVENT_END, event.getEnd())
- .addTaggedData(SESSION_ID, event.getSessionId());
+ .addTaggedData(SESSION_ID, event.getSessionId().flattenToString());
mMetricsLogger.write(log);
debugLog(log);
}
@@ -225,9 +219,17 @@
final int eventEnd = Integer.parseInt(
Objects.toString(log.getTaggedData(EVENT_END), ZERO));
- Log.d(LOG_TAG, String.format("%2d: %s/%s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)",
- index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd, widget,
- model));
+ Log.d(LOG_TAG,
+ String.format(Locale.US, "%2d: %s/%s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)",
+ index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd,
+ widget, model));
+ }
+
+ /**
+ * Returns a token iterator for tokenizing text for logging purposes.
+ */
+ public static BreakIterator getTokenIterator(@NonNull Locale locale) {
+ return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale));
}
/**
@@ -260,8 +262,10 @@
return String.format(Locale.US, "%s|%s|%d", classifierId, modelName, hash);
}
- static String getClassifierId(String signature) {
- Preconditions.checkNotNull(signature);
+ static String getClassifierId(@Nullable String signature) {
+ if (signature == null) {
+ return "";
+ }
final int end = signature.indexOf("|");
if (end >= 0) {
return signature.substring(0, end);
@@ -269,8 +273,10 @@
return "";
}
- static String getModelName(String signature) {
- Preconditions.checkNotNull(signature);
+ static String getModelName(@Nullable String signature) {
+ if (signature == null) {
+ return "";
+ }
final int start = signature.indexOf("|") + 1;
final int end = signature.indexOf("|", start);
if (start >= 1 && end >= start) {
@@ -279,8 +285,10 @@
return "";
}
- static int getHash(String signature) {
- Preconditions.checkNotNull(signature);
+ static int getHash(@Nullable String signature) {
+ if (signature == null) {
+ return 0;
+ }
final int index1 = signature.indexOf("|");
final int index2 = signature.indexOf("|", index1);
if (index2 > 0) {
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
index 45fd6bf..490c389 100644
--- a/core/java/android/view/textclassifier/SystemTextClassifier.java
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -28,7 +28,6 @@
import android.service.textclassifier.ITextLinksCallback;
import android.service.textclassifier.ITextSelectionCallback;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.internal.util.Preconditions;
@@ -49,13 +48,6 @@
private final TextClassificationConstants mSettings;
private final TextClassifier mFallback;
private final String mPackageName;
-
- private final Object mLoggerLock = new Object();
- @GuardedBy("mLoggerLock")
- private Logger.Config mLoggerConfig;
- @GuardedBy("mLoggerLock")
- private Logger mLogger;
- @GuardedBy("mLoggerLock")
private TextClassificationSessionId mSessionId;
public SystemTextClassifier(Context context, TextClassificationConstants settings)
@@ -147,27 +139,6 @@
}
@Override
- public Logger getLogger(@NonNull Logger.Config config) {
- Preconditions.checkNotNull(config);
- synchronized (mLoggerLock) {
- if (mLogger == null || !config.equals(mLoggerConfig)) {
- mLoggerConfig = config;
- mLogger = new Logger(config) {
- @Override
- public void writeEvent(SelectionEvent event) {
- try {
- mManagerService.onSelectionEvent(mSessionId, event);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Error reporting selection event.", e);
- }
- }
- };
- }
- }
- return mLogger;
- }
-
- @Override
public void destroy() {
try {
if (mSessionId != null) {
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index e8e300a..4c64198 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -17,7 +17,6 @@
package android.view.textclassifier;
import android.annotation.WorkerThread;
-import android.view.textclassifier.DefaultLogger.SignatureParser;
import android.view.textclassifier.SelectionEvent.InvocationMethod;
import com.android.internal.util.Preconditions;
@@ -222,7 +221,8 @@
}
private static boolean isPlatformLocalTextClassifierSmartSelection(String signature) {
- return DefaultLogger.CLASSIFIER_ID.equals(SignatureParser.getClassifierId(signature));
+ return SelectionSessionLogger.CLASSIFIER_ID.equals(
+ SelectionSessionLogger.SignatureParser.getClassifierId(signature));
}
}
}
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index f048d29..da47bcb 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -359,18 +359,6 @@
}
/**
- * Returns a helper for logging TextClassifier related events.
- *
- * @param config logger configuration
- * @hide
- */
- @WorkerThread
- default Logger getLogger(@NonNull Logger.Config config) {
- Preconditions.checkNotNull(config);
- return Logger.DISABLED;
- }
-
- /**
* Reports a selection event.
*
* <strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 7e3748a..2213355 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -94,11 +94,7 @@
private final Object mLoggerLock = new Object();
@GuardedBy("mLoggerLock") // Do not access outside this lock.
- private Logger.Config mLoggerConfig;
- @GuardedBy("mLoggerLock") // Do not access outside this lock.
- private Logger mLogger;
- @GuardedBy("mLoggerLock") // Do not access outside this lock.
- private Logger mLogger2; // This is the new logger. Will replace mLogger.
+ private SelectionSessionLogger mSessionLogger;
private final TextClassificationConstants mSettings;
@@ -283,28 +279,14 @@
}
}
- /** @inheritDoc */
- @Override
- public Logger getLogger(@NonNull Logger.Config config) {
- Preconditions.checkNotNull(config);
- synchronized (mLoggerLock) {
- if (mLogger == null || !config.equals(mLoggerConfig)) {
- mLoggerConfig = config;
- mLogger = new DefaultLogger(config);
- }
- }
- return mLogger;
- }
-
@Override
public void onSelectionEvent(SelectionEvent event) {
Preconditions.checkNotNull(event);
synchronized (mLoggerLock) {
- if (mLogger2 == null) {
- mLogger2 = new DefaultLogger(
- new Logger.Config(mContext, WIDGET_TYPE_UNKNOWN, null));
+ if (mSessionLogger == null) {
+ mSessionLogger = new SelectionSessionLogger();
}
- mLogger2.writeEvent(event);
+ mSessionLogger.writeEvent(event);
}
}
@@ -331,7 +313,7 @@
private String createId(String text, int start, int end) {
synchronized (mLock) {
- return DefaultLogger.createId(text, start, end, mContext, mModel.getVersion(),
+ return SelectionSessionLogger.createId(text, start, end, mContext, mModel.getVersion(),
mModel.getSupportedLocales());
}
}
diff --git a/core/java/android/webkit/FindAddress.java b/core/java/android/webkit/FindAddress.java
index 31b2427..9183227 100644
--- a/core/java/android/webkit/FindAddress.java
+++ b/core/java/android/webkit/FindAddress.java
@@ -429,20 +429,21 @@
// At this point we've matched a state; try to match a zip code after it.
Matcher zipMatcher = sWordRe.matcher(content);
- if (zipMatcher.find(stateMatch.end())
- && isValidZipCode(zipMatcher.group(0), stateMatch)) {
- return zipMatcher.end();
+ if (zipMatcher.find(stateMatch.end())) {
+ if (isValidZipCode(zipMatcher.group(0), stateMatch)) {
+ return zipMatcher.end();
+ }
+ } else {
+ // The content ends with a state but no zip
+ // code. This is a legal match according to the
+ // documentation. N.B. This is equivalent to the
+ // original c++ implementation, which only allowed
+ // the zip code to be optional at the end of the
+ // string, which presumably is a bug. We tried
+ // relaxing this to work in other places but it
+ // caused too many false positives.
+ nonZipMatch = stateMatch.end();
}
- // The content ends with a state but no zip
- // code. This is a legal match according to the
- // documentation. N.B. This differs from the
- // original c++ implementation, which only allowed
- // the zip code to be optional at the end of the
- // string, which presumably is a bug. Now we
- // prefer to find a match with a zip code, but
- // remember non-zip matches and return them if
- // necessary.
- nonZipMatch = stateMatch.end();
}
}
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index fc94b1f..10748ac 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1837,8 +1837,12 @@
*
* @param addr the string to search for addresses
* @return the address, or if no address is found, {@code null}
+ * @deprecated this method is superseded by {@link TextClassifier#generateLinks(
+ * android.view.textclassifier.TextLinks.Request)}. Avoid using this method even when targeting
+ * API levels where no alternative is available.
*/
@Nullable
+ @Deprecated
public static String findAddress(String addr) {
if (addr == null) {
throw new NullPointerException("addr is null");
@@ -2455,14 +2459,6 @@
return mWebViewThread;
}
- /**
- * Returns the {@link Looper} corresponding to the thread on which WebView calls must be made.
- */
- @NonNull
- public Looper getLooper() {
- return mWebViewThread;
- }
-
//-------------------------------------------------------------------------
// Interface for WebView providers
//-------------------------------------------------------------------------
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 9946726..6af678b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -6031,7 +6031,9 @@
mSwitchedLines = false;
final int selectionStart = mTextView.getSelectionStart();
final int selectionEnd = mTextView.getSelectionEnd();
- if (selectionStart > selectionEnd) {
+ if (selectionStart < 0 || selectionEnd < 0) {
+ Selection.removeSelection((Spannable) mTextView.getText());
+ } else if (selectionStart > selectionEnd) {
Selection.setSelection((Spannable) mTextView.getText(),
selectionEnd, selectionStart);
}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 4b951fa..1372987 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -817,8 +817,6 @@
if (mScaleType != scaleType) {
mScaleType = scaleType;
- setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);
-
requestLayout();
invalidate();
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index b3327a7..468abdc 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -33,9 +33,9 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.ActionMode;
-import android.view.textclassifier.Logger;
import android.view.textclassifier.SelectionEvent;
import android.view.textclassifier.SelectionEvent.InvocationMethod;
+import android.view.textclassifier.SelectionSessionLogger;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationConstants;
import android.view.textclassifier.TextClassificationManager;
@@ -663,7 +663,6 @@
private static final String LOG_TAG = "SelectionMetricsLogger";
private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
- private final Logger mLogger;
private final boolean mEditTextLogger;
private final BreakIterator mTokenIterator;
@@ -673,10 +672,8 @@
SelectionMetricsLogger(TextView textView) {
Preconditions.checkNotNull(textView);
- mLogger = textView.getTextClassifier().getLogger(
- new Logger.Config(textView.getContext(), getWidetType(textView), null));
mEditTextLogger = textView.isTextEditable();
- mTokenIterator = mLogger.getTokenIterator(textView.getTextLocale());
+ mTokenIterator = SelectionSessionLogger.getTokenIterator(textView.getTextLocale());
}
@TextClassifier.WidgetType
@@ -702,8 +699,6 @@
}
mTokenIterator.setText(mText);
mStartIndex = index;
- mLogger.logSelectionStartedEvent(invocationMethod, 0);
- // TODO: Remove the above legacy logging.
mClassificationSession = classificationSession;
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionStartedEvent(invocationMethod, 0));
@@ -720,27 +715,18 @@
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
int[] wordIndices = getWordDelta(start, end);
if (selection != null) {
- mLogger.logSelectionModifiedEvent(
- wordIndices[0], wordIndices[1], selection);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionModifiedEvent(
wordIndices[0], wordIndices[1], selection));
}
} else if (classification != null) {
- mLogger.logSelectionModifiedEvent(
- wordIndices[0], wordIndices[1], classification);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionModifiedEvent(
wordIndices[0], wordIndices[1], classification));
}
} else {
- mLogger.logSelectionModifiedEvent(
- wordIndices[0], wordIndices[1]);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionModifiedEvent(
@@ -762,18 +748,12 @@
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
int[] wordIndices = getWordDelta(start, end);
if (classification != null) {
- mLogger.logSelectionActionEvent(
- wordIndices[0], wordIndices[1], action, classification);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionActionEvent(
wordIndices[0], wordIndices[1], action, classification));
}
} else {
- mLogger.logSelectionActionEvent(
- wordIndices[0], wordIndices[1], action);
- // TODO: Remove the above legacy logging.
if (mClassificationSession != null) {
mClassificationSession.onSelectionEvent(
SelectionEvent.createSelectionActionEvent(
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index 53318c9..d8a9cca 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -408,6 +408,15 @@
}
/**
+ * Update the displayed time if necessary and invalidate the view.
+ * @hide
+ */
+ public void refresh() {
+ onTimeChanged();
+ invalidate();
+ }
+
+ /**
* Indicates whether the system is currently using the 24-hour mode.
*
* When the system is in 24-hour mode, this view will use the pattern
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 11db6b6..fae6db5d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9380,7 +9380,7 @@
final int selectionStart = getSelectionStart();
final int selectionEnd = getSelectionEnd();
- return selectionStart >= 0 && selectionStart != selectionEnd;
+ return selectionStart >= 0 && selectionEnd > 0 && selectionStart != selectionEnd;
}
String getSelectedText() {
diff --git a/core/java/com/android/internal/app/ColorDisplayController.java b/core/java/com/android/internal/app/ColorDisplayController.java
index 278d31a..f1539ee 100644
--- a/core/java/com/android/internal/app/ColorDisplayController.java
+++ b/core/java/com/android/internal/app/ColorDisplayController.java
@@ -365,6 +365,10 @@
* Get the current color mode.
*/
public int getColorMode() {
+ if (getAccessibilityTransformActivated()) {
+ return COLOR_MODE_SATURATED;
+ }
+
final int colorMode = System.getIntForUser(mContext.getContentResolver(),
System.DISPLAY_COLOR_MODE, -1, mUserId);
if (colorMode < COLOR_MODE_NATURAL || colorMode > COLOR_MODE_SATURATED) {
@@ -416,6 +420,18 @@
R.integer.config_nightDisplayColorTemperatureDefault);
}
+ /**
+ * Returns true if any Accessibility color transforms are enabled.
+ */
+ public boolean getAccessibilityTransformActivated() {
+ final ContentResolver cr = mContext.getContentResolver();
+ return
+ Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
+ 0, mUserId) == 1
+ || Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
+ 0, mUserId) == 1;
+ }
+
private void onSettingChanged(@NonNull String setting) {
if (DEBUG) {
Slog.d(TAG, "onSettingChanged: " + setting);
@@ -441,6 +457,10 @@
case System.DISPLAY_COLOR_MODE:
mCallback.onDisplayColorModeChanged(getColorMode());
break;
+ case Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED:
+ case Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED:
+ mCallback.onAccessibilityTransformChanged(getAccessibilityTransformActivated());
+ break;
}
}
}
@@ -471,6 +491,12 @@
false /* notifyForDescendants */, mContentObserver, mUserId);
cr.registerContentObserver(System.getUriFor(System.DISPLAY_COLOR_MODE),
false /* notifyForDecendants */, mContentObserver, mUserId);
+ cr.registerContentObserver(
+ Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
+ false /* notifyForDecendants */, mContentObserver, mUserId);
+ cr.registerContentObserver(
+ Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
+ false /* notifyForDecendants */, mContentObserver, mUserId);
}
}
}
@@ -531,5 +557,12 @@
* @param displayColorMode the color mode
*/
default void onDisplayColorModeChanged(int displayColorMode) {}
+
+ /**
+ * Callback invoked when Accessibility color transforms change.
+ *
+ * @param state the state Accessibility color transforms (true of active)
+ */
+ default void onAccessibilityTransformChanged(boolean state) {}
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 1e5bd18..b49aace 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -657,7 +657,7 @@
* {@link #removeHiddenBatterySippers(List)}.
*/
private void addAmbientDisplayUsage() {
- long ambientDisplayMs = mStats.getScreenDozeTime(mRawRealtimeUs, mStatsType);
+ long ambientDisplayMs = mStats.getScreenDozeTime(mRawRealtimeUs, mStatsType) / 1000;
double power = mPowerProfile.getAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY)
* ambientDisplayMs / (60 * 60 * 1000);
if (power > 0) {
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index f73b607..07d78fe 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.app.Notification;
+import android.app.Person;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
@@ -63,7 +63,7 @@
private boolean mFirstLayout;
private boolean mIsHidingAnimated;
private boolean mNeedsGeneratedAvatar;
- private Notification.Person mSender;
+ private Person mSender;
private boolean mImagesAtEnd;
private ViewGroup mImageContainer;
private MessagingImageMessage mIsolatedMessage;
@@ -126,7 +126,7 @@
return position;
}
- public void setSender(Notification.Person sender, CharSequence nameOverride) {
+ public void setSender(Person sender, CharSequence nameOverride) {
mSender = sender;
if (nameOverride == null) {
nameOverride = sender.getName();
@@ -466,7 +466,7 @@
return mNeedsGeneratedAvatar;
}
- public Notification.Person getSender() {
+ public Person getSender() {
return mSender;
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 292df60..f8236c7 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.app.Notification;
+import android.app.Person;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -79,7 +80,7 @@
private Icon mLargeIcon;
private boolean mIsOneToOne;
private ArrayList<MessagingGroup> mAddedGroups = new ArrayList<>();
- private Notification.Person mUser;
+ private Person mUser;
private CharSequence mNameReplacement;
private boolean mDisplayImagesAtEnd;
@@ -160,7 +161,7 @@
for (int i = remoteInputHistory.length - 1; i >= 0; i--) {
CharSequence message = remoteInputHistory[i];
newMessages.add(new Notification.MessagingStyle.Message(
- message, 0, (Notification.Person) null));
+ message, 0, (Person) null));
}
}
@@ -296,13 +297,13 @@
mIsOneToOne = oneToOne;
}
- public void setUser(Notification.Person user) {
+ public void setUser(Person user) {
mUser = user;
if (mUser.getIcon() == null) {
Icon userIcon = Icon.createWithResource(getContext(),
com.android.internal.R.drawable.messaging_user);
userIcon.setTint(mLayoutColor);
- mUser.setIcon(userIcon);
+ mUser = mUser.toBuilder().setIcon(userIcon).build();
}
}
@@ -310,7 +311,7 @@
List<MessagingMessage> messages) {
// Let's first find our groups!
List<List<MessagingMessage>> groups = new ArrayList<>();
- List<Notification.Person> senders = new ArrayList<>();
+ List<Person> senders = new ArrayList<>();
// Lets first find the groups
findGroups(historicMessages, messages, groups, senders);
@@ -320,7 +321,7 @@
}
private void createGroupViews(List<List<MessagingMessage>> groups,
- List<Notification.Person> senders) {
+ List<Person> senders) {
mGroups.clear();
for (int groupIndex = 0; groupIndex < groups.size(); groupIndex++) {
List<MessagingMessage> group = groups.get(groupIndex);
@@ -339,7 +340,7 @@
}
newGroup.setDisplayImagesAtEnd(mDisplayImagesAtEnd);
newGroup.setLayoutColor(mLayoutColor);
- Notification.Person sender = senders.get(groupIndex);
+ Person sender = senders.get(groupIndex);
CharSequence nameOverride = null;
if (sender != mUser && mNameReplacement != null) {
nameOverride = mNameReplacement;
@@ -357,7 +358,7 @@
private void findGroups(List<MessagingMessage> historicMessages,
List<MessagingMessage> messages, List<List<MessagingMessage>> groups,
- List<Notification.Person> senders) {
+ List<Person> senders) {
CharSequence currentSenderKey = null;
List<MessagingMessage> currentGroup = null;
int histSize = historicMessages.size();
@@ -369,7 +370,7 @@
message = messages.get(i - histSize);
}
boolean isNewGroup = currentGroup == null;
- Notification.Person sender = message.getMessage().getSenderPerson();
+ Person sender = message.getMessage().getSenderPerson();
CharSequence key = sender == null ? null
: sender.getKey() == null ? sender.getName() : sender.getKey();
isNewGroup |= !TextUtils.equals(key, currentSenderKey);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index b0f68cd..3f58afa 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -327,6 +327,11 @@
transaction->setAnimationTransaction();
}
+static void nativeSetEarlyWakeup(JNIEnv* env, jclass clazz, jlong transactionObj) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setEarlyWakeup();
+}
+
static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint zorder) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -934,6 +939,8 @@
(void*)nativeMergeTransaction },
{"nativeSetAnimationTransaction", "(J)V",
(void*)nativeSetAnimationTransaction },
+ {"nativeSetEarlyWakeup", "(J)V",
+ (void*)nativeSetEarlyWakeup },
{"nativeSetLayer", "(JJI)V",
(void*)nativeSetLayer },
{"nativeSetRelativeLayer", "(JJLandroid/os/IBinder;I)V",
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 451f278..7481f1c 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -992,6 +992,10 @@
Properties::isolatedProcess = isolated;
}
+static void android_view_ThreadedRenderer_setContextPriority(JNIEnv*, jclass,
+ jint contextPriority) {
+ Properties::contextPriority = contextPriority;
+}
// ----------------------------------------------------------------------------
// FrameMetricsObserver
@@ -1103,6 +1107,7 @@
(void*)android_view_ThreadedRenderer_hackySetRTAnimationsEnabled },
{ "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
{ "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
+ { "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
};
static JavaVM* mJvm = nullptr;
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 2a7c256..ab15d4f 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -118,17 +118,17 @@
// Stack dumps
optional android.os.BackTraceProto native_traces = 1200 [
- (section).type = SECTION_NONE,
+ (section).type = SECTION_TOMBSTONE,
(section).args = "native"
];
optional android.os.BackTraceProto hal_traces = 1201 [
- (section).type = SECTION_NONE,
+ (section).type = SECTION_TOMBSTONE,
(section).args = "hal"
];
optional android.os.BackTraceProto java_traces = 1202 [
- (section).type = SECTION_NONE,
+ (section).type = SECTION_TOMBSTONE,
(section).args = "java"
];
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 3de8c39..237efd8 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -213,6 +213,13 @@
optional SettingProto keyguard_slice_uri = 29;
optional SettingProto last_setup_shown = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ message Launcher {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto swipe_up_to_switch_apps_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Launcher launcher = 70;
+
message Location {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -479,5 +486,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 70;
+ // Next tag = 71;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index da15506..c5ab2e6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -487,6 +487,7 @@
<protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" />
<protected-broadcast android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" />
<protected-broadcast android:name="android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION" />
+ <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_PLANS_CHANGED" />
<protected-broadcast android:name="com.android.bluetooth.btservice.action.ALARM_WAKEUP" />
<protected-broadcast android:name="com.android.server.action.NETWORK_STATS_POLL" />
diff --git a/core/res/res/anim/activity_translucent_close_exit.xml b/core/res/res/anim/activity_translucent_close_exit.xml
index 04c5dea..02df0ff 100644
--- a/core/res/res/anim/activity_translucent_close_exit.xml
+++ b/core/res/res/anim/activity_translucent_close_exit.xml
@@ -20,6 +20,6 @@
<translate
android:fromYDelta="0%"
android:toYDelta="100%"
- android:interpolator="@interpolator/fast_out_linear_in"
- android:duration="300"/>
+ android:interpolator="@interpolator/accelerate_quad"
+ android:duration="250"/>
</set>
diff --git a/core/res/res/drawable/ic_zen_24dp.xml b/core/res/res/drawable/ic_zen_24dp.xml
new file mode 100644
index 0000000..790bfb9
--- /dev/null
+++ b/core/res/res/drawable/ic_zen_24dp.xml
@@ -0,0 +1,26 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:height="24dp"
+ android:width="24dp" >
+
+ <path
+ android:fillColor="?android:attr/colorControlActivated"
+ android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4 11H8c-.55 0-1-.45-1-1s.45-1 1-1h8c.55 0 1 .45 1 1s-.45 1-1 1z" />
+
+</vector>
\ No newline at end of file
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index ff26222..dc28e01 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"কোনো ভইচ সেৱা নাই"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"ধ্বনি সেৱা বা জৰুৰীকালীন কলৰ সেৱা উপলব্ধ নহয়"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"আপোনাৰ বাহকে সাময়িকভাৱে অফ কৰি থৈছে"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"আপোনাৰ বাহকে <xliff:g id="SIMNUMBER">%d</xliff:g> ছিমৰ বাবে সাময়িকভাৱে অফ কৰিছে"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"ম\'বাইল নেটৱৰ্কৰ লগত সংযোগ কৰিব পৰা নাই"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"পচন্দৰ নেটৱৰ্ক সলনি কৰি চেষ্টা কৰি চাওক। সলনি কৰিবলৈ টিপক।"</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"জৰুৰীকালীন কল কৰাৰ সুবিধা উপলব্ধ নহয়"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"চিনাক্ত কৰিবপৰা নগ\'ল"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"ফিংগাৰপ্ৰিণ্টৰ সত্যাপন কৰা হ’ল"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ নাই।"</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"ফিংগাৰপ্ৰিণ্ট সঞ্চয় কৰিব পৰা নগ\'ল। পূর্বে সঞ্চিত ফিংগাৰপ্ৰিণ্ট এটা আঁতৰাওক।"</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ফিংগাৰপ্ৰিণ্ট গ্ৰহণৰ সময়সীমা উকলি গৈছে। আকৌ চেষ্টা কৰক।"</string>
@@ -1275,49 +1273,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>এ অইন এপবোৰৰ ওপৰত প্ৰদৰ্শিত হৈ আছে"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g>এ এই সুবিধাটো ব্যৱহাৰ কৰাটো নিবিচাৰে তেন্তে টিপি ছেটিংসমূহ খোলক আৰু ইয়াক অফ কৰক।"</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"অফ কৰক"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> পৰীক্ষা কৰি থকা হৈছে…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"বৰ্তমানৰ সমলৰ সমীক্ষা কৰি থকা হৈছে"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"নতুন <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"ছেট আপ কৰিবলৈ টিপক"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ফট\' আৰু মিডিয়া স্থানান্তৰণৰ বাবে"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g>ত কিবা সমস্যা আছে"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"সমাধান কৰিবলৈ টিপক"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> ব্যৱহাৰযোগ্য হৈ থকা নাই। ঠিক কৰিবলৈ বাছনি কৰক।"</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g>ক ব্যৱহাৰ কৰিব নোৱাৰি"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"এই ডিভাইচটোৱে <xliff:g id="NAME">%s</xliff:g>ক ব্যৱহাৰ কৰিব নোৱাৰে। ব্যৱহাৰ কৰিব পৰা ফৰ্মেটত ছেট আপ কৰিবলৈ টিপক।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"এই ডিভাইচটোৱে <xliff:g id="NAME">%s</xliff:g>ক চলাব নোৱাৰে। চলাব পৰা কোনো ফৰ্মেটত ছেট আপ কৰিবলৈ বাছনি কৰক।"</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> অপ্ৰত্য়াশিতভাৱে আঁতৰোৱা হ\'ল"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"সমল হেৰুওৱাৰ পৰা হাত সাৰিবলৈ আঁতৰোৱাৰ আগতে মিডিয়া বাহিৰ কৰক"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> আঁতৰোৱা হ\'ল"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"কিছুমান কাৰ্যক্ষমতাই সঠিকভাৱে কাম নকৰিব পাৰে। নতুন সঞ্চয়াগাৰ ভৰাওক।"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> বাহিৰ কৰি থকা হৈছে"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"আঁতৰাই নিদিব"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"ছেট আপ কৰক"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"বাহিৰ কৰক"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"অন্বেষণ কৰক"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> উপলব্ধ নহয়"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"ডিভাইচ আকৌ ভৰাওক"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g>ক স্থানান্তৰ কৰি থকা হৈছে"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"ডেটা স্থানান্তৰ কৰি থকা হৈছে"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"সমলৰ স্থানান্তৰণ সমাপ্ত হ\'ল"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"<xliff:g id="NAME">%s</xliff:g>লৈ সমল স্থানান্তৰ কৰা হ\'ল"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"সমল স্থানান্তৰ কৰিব পৰা নগ\'ল"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"সমল আকৌ স্থানান্তৰ কৰিবলৈ চেষ্টা কৰক"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"আঁতৰোৱা হ\'ল"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"বাহিৰলৈ উলিওৱা হ\'ল"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"পৰীক্ষা কৰি থকা হৈছে…"</string>
@@ -1865,14 +1848,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"ভইচৰ বাবে ছিমৰ প্ৰ\'ভিজন কৰা হোৱা নাই"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"ভইচৰ বাবে ছিম ব্যৱহাৰৰ অনুমতি নাই"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"ভইচৰ বাবে ফ\'ন ব্যৱহাৰৰ অনুমতি নাই"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"ছিম <xliff:g id="SIMNUMBER">%d</xliff:g> অনুমোদিত নহয়"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"ছিম <xliff:g id="SIMNUMBER">%d</xliff:g>ৰ প্ৰ\'ভিজন কৰা হোৱা নাই"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"ছিম <xliff:g id="SIMNUMBER">%d</xliff:g> অনুমোদিত নহয়"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"ছিম <xliff:g id="SIMNUMBER">%d</xliff:g> অনুমোদিত নহয়"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"পপআপ ৱিণ্ড\'"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"এপৰ সংস্কৰণ অৱনমিত কৰা হৈছে, বা ই এই শ্বৰ্টকাটটোৰ লগত খাপ নাখায়"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 7808138..83bb71c 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -84,7 +84,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Няма сэрвісу галасавых выклікаў"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"Галасавыя або экстранныя выклікі недаступныя"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"Часова выключана аператарам сувязі"</string>
- <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Часова адключаны для SIM <xliff:g id="SIMNUMBER">%d</xliff:g> аператарам сувязі"</string>
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Часова адключана для SIM <xliff:g id="SIMNUMBER">%d</xliff:g> аператарам сувязі"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"Сетка мабільнай сувязі недаступная"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Націсніце, каб выбраць іншую сетку."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Экстранныя выклікі недаступныя"</string>
@@ -1321,7 +1321,7 @@
<string name="ext_media_new_notification_title" msgid="1621805083736634077">"Знойдзена новая прылада: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_new_notification_message" msgid="3673685270558405087">"Дакраніцеся, каб наладзіць"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Для перадачы фатаграфій і медыяфайлаў"</string>
- <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Праблема з носьбітам <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Праблема з носьбітам (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"Націсніце, каб выправіць"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"Носьбіт <xliff:g id="NAME">%s</xliff:g> пашкоджаны. Выберыце, каб выправіць."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> не падтрымліваецца"</string>
@@ -1329,8 +1329,8 @@
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Гэта прылада не падтрымлівае носьбіт <xliff:g id="NAME">%s</xliff:g>. Выберыце, каб наладзіць яго ў фармаце, які падтрымліваецца."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"Носьбіт <xliff:g id="NAME">%s</xliff:g> нечакана выняты"</string>
<string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Адключыце носьбіт перад тым, як дастаць яго, каб не страціць змесціва"</string>
- <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"Носьбіт <xliff:g id="NAME">%s</xliff:g> прыбралі"</string>
- <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Некаторыя функцыі могуць кепска працаваць. Устаўце новае сховішча."</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"Носьбіт (<xliff:g id="NAME">%s</xliff:g>) выняты"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Некаторыя функцыі могуць кепска працаваць. Устаўце новы носьбіт."</string>
<string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> адключаецца"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Не даставайце носьбіт"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Наладзіць"</string>
@@ -1341,7 +1341,7 @@
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"Перамяшчэнне <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"Перамяшчэнне даных"</string>
<string name="ext_media_move_success_title" msgid="7863652232242276066">"Перадача змесціва завершана"</string>
- <string name="ext_media_move_success_message" msgid="8939137931961728009">"Змесціва перанесена на сховішча <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"Змесціва перанесена на носьбіт: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_failure_title" msgid="1604422634177382092">"Не ўдалося перамясціць змесціва"</string>
<string name="ext_media_move_failure_message" msgid="7388950499623016135">"Паспрабуйце перамясціць змесціва яшчэ раз"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"Носьбіт выдалены"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 2b184a3..198e67b 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"ভয়েস পরিষেবা নেই"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"ভয়েস পরিষেবা অথবা জরুরি কলের সুবিধা নেই"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"পরিষেবা প্রদানকারী এই সুবিধা সাময়িকভাবে বন্ধ রেখেছে"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"আপনার পরিষেবা প্রদানকারী <xliff:g id="SIMNUMBER">%d</xliff:g> সিমটি অস্থায়ীভাবে বন্ধ করেছে"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"মোবাইল নেটওয়ার্কে কানেক্ট করা যাচ্ছে না"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"পছন্দের নেটওয়ার্ক পরিবর্তন করে দেখুন। অন্য নেটওয়ার্ক বেছে নিতে ট্যাপ করুন।"</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"জরুরি কল করা যাবে না"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"স্বীকৃত নয়"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"আঙ্গুলের ছাপ যাচাই করা হয়েছে"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার অনুপলব্ধ৷"</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"আঙ্গুলের ছাপ সংরক্ষণ করা যাবে না৷ অনুগ্রহ করে একটি বিদ্যমান আঙ্গুলের ছাপ সরান৷"</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string>
@@ -1275,49 +1273,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> অন্যান্য অ্যাপের ওপর প্রদর্শিত হচ্ছে"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> কে এই বৈশিষ্ট্যটি ব্যবহার করতে দিতে না চাইলে, ট্যাপ করে সেটিংসে যান ও বৈশিষ্ট্যটি বন্ধ করে দিন।"</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"বন্ধ করুন"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> পরীক্ষা করা হচ্ছে…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"বর্তমান কন্টেন্টটি পর্যালোচনা করা হচ্ছে"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"নতুন <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"সেট-আপ করতে ট্যাপ করুন"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ফটো এবং মিডিয়া ট্রান্সফার"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> নিয়ে সমস্যা আছে"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"ঠিক করতে ট্যাপ করুন"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> ত্রুটিপূর্ণ। মেরামত করতে বেছে নিন।"</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> অসমর্থিত"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"এই ডিভাইসটি <xliff:g id="NAME">%s</xliff:g> সমর্থন করে না। কোনো সমর্থিত ফর্ম্যাটে সেট আপ করতে আলতো চাপুন।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"এই ডিভাইসটি <xliff:g id="NAME">%s</xliff:g> সমর্থন করে না। কোনো সমর্থিত ফর্ম্যাটে সেট আপ করতে চাইলে বেছে নিন।"</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> অপ্রত্যাশিতভাবে মুছে ফেলা হয়েছে"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"মিডিয়া সরিয়ে নেওয়ার আগে সেটি সিস্টেম থেকে ইজেক্ট করুন, নাহলে কন্টেন্ট সেভ নাও হতে পারে"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> সরানো হয়েছে"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"কিছু ক্রিয়াকলাপ সঠিকভাবে কাজ নাও করতে পারে। নতুন স্টোরেজ লাগান।"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> ইজেক্ট করা হচ্ছে"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"সরাবেন না"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"সেট আপ করুন"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"বের করে নিন"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"ঘুরে দেখুন"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> অনুপস্থিত"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"ডিভাইসটি আবার ঢোকান"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> সরানো হচ্ছে"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"ডেটা সরানো হচ্ছে"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"কন্টেন্ট ট্রান্সফার করা হয়েছে"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"কন্টেন্ট <xliff:g id="NAME">%s</xliff:g>-তে সরানো হয়েছে"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"কন্টেন্ট সরানো যাচ্ছে না"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"আবার কন্টেন্ট সরানোর চেষ্টা করুন"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"সরানো হয়েছে"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"সরিয়ে দেওয়া হয়েছে"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"পরীক্ষা করা হচ্ছে..."</string>
@@ -1865,14 +1848,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"সিমটি ভয়েস কলের জন্য প্রস্তুত নয়"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"এই সিম দিয়ে ভয়েস কল করা যাবে না"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"এই ফোন দিয়ে ভয়েস কল করা যাবে না"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"<xliff:g id="SIMNUMBER">%d</xliff:g> সিমটি অনুমোদিত নয়"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"<xliff:g id="SIMNUMBER">%d</xliff:g> সিমটি প্রস্তুত নয়"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"<xliff:g id="SIMNUMBER">%d</xliff:g> সিমটি অনুমোদিত নয়"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"<xliff:g id="SIMNUMBER">%d</xliff:g> সিমটি অনুমোদিত নয়"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"পপ-আপ উইন্ডো"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>টি"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"অ্যাপের ভার্সন ডাউনগ্রেড করা হয়েছে অথবা এই শর্টকাটের জন্য উপযুক্ত নয়"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 81b3f35..686e35e 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -316,8 +316,8 @@
<string name="permdesc_statusBar" msgid="8434669549504290975">"Dozvoljava aplikaciji onemogućavanje statusne trake ili dodavanje i uklanjanje sistemskih ikona."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"funkcioniranje u vidu statusne trake"</string>
<string name="permdesc_statusBarService" msgid="716113660795976060">"Dozvoljava aplikaciji da postane statusna traka."</string>
- <string name="permlab_expandStatusBar" msgid="1148198785937489264">"otvaranje/zatvaranje statusne trake"</string>
- <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Dozvoljava aplikaciji otvaranje ili zatvaranje statusne trake."</string>
+ <string name="permlab_expandStatusBar" msgid="1148198785937489264">"proširivanje/sužavanje statusne trake"</string>
+ <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Dozvoljava aplikaciji proširivanje ili sužavanje statusne trake."</string>
<string name="permlab_install_shortcut" msgid="4279070216371564234">"instaliranje prečica"</string>
<string name="permdesc_install_shortcut" msgid="8341295916286736996">"Omogućava aplikaciji dodavanje prečice za početni ekran bez intervencije korisnika."</string>
<string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"uklanjanje prečica"</string>
@@ -1767,7 +1767,7 @@
<string name="zen_mode_forever" msgid="931849471004038757">"Dok ne isključite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dok ne isključite način rada Ne ometaj"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
- <string name="toolbar_collapse_description" msgid="2821479483960330739">"Skupi"</string>
+ <string name="toolbar_collapse_description" msgid="2821479483960330739">"Suzi"</string>
<string name="zen_mode_feature_name" msgid="5254089399895895004">"Ne ometaj"</string>
<string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"Prestanak rada"</string>
<string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"Radni dan uvečer"</string>
@@ -1787,7 +1787,7 @@
<string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Promijenjeno u novi SS zahtjev"</string>
<string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil za posao"</string>
<string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Proširi"</string>
- <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Skupi"</string>
+ <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Suzi"</string>
<string name="expand_action_accessibility" msgid="5307730695723718254">"aktiviraj/deaktiviraj proširenje"</string>
<string name="usb_midi_peripheral_name" msgid="7221113987741003817">"Android USB ulaz za periferijske uređaje"</string>
<string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index ce52f1b..2d1b37f 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Sense servei de veu"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"No hi ha servei de veu ni trucades d\'emergència"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"L\'operador de telefonia mòbil ho ha desactivat temporalment"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"L\'operador de telefonia mòbil ho ha desactivat temporalment per a la SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"No es pot accedir a la xarxa mòbil"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Prova de canviar de xarxa preferida. Toca per canviar-la."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Les trucades d\'emergència no estan disponibles"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"No s\'ha reconegut"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"L\'empremta digital s\'ha autenticat"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El maquinari per a empremtes digitals no està disponible."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
@@ -1274,49 +1272,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> s\'està superposant a altres apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Desactiva"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"S\'està comprovant el suport (<xliff:g id="NAME">%s</xliff:g>)…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"S\'està revisant el contingut actual"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Suport extern nou (<xliff:g id="NAME">%s</xliff:g>)"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"Toca per configurar"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Per transferir fotos i fitxers multimèdia"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Problema amb el suport (<xliff:g id="NAME">%s</xliff:g>)"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"Toca per solucionar el problema"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"La unitat següent està malmesa: <xliff:g id="NAME">%s</xliff:g>. Selecciona-la per solucionar-ho."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> no és compatible"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"El dispositiu no admet la unitat <xliff:g id="NAME">%s</xliff:g>. Toca per configurar-la amb un format compatible."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Aquest dispositiu no admet la unitat següent: <xliff:g id="NAME">%s</xliff:g>. Selecciona-la per configurar-la en un format compatible."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"S\'ha extret <xliff:g id="NAME">%s</xliff:g> de manera inesperada"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Expulsa el suport extern abans d\'extreure\'l per evitar perdre\'n el contingut"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"S\'ha suprimit el suport (<xliff:g id="NAME">%s</xliff:g>)"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Pot ser que algunes funcions no funcionin correctament. Insereix un altre dispositiu d\'emmagatzematge."</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"S\'està expulsant el suport (<xliff:g id="NAME">%s</xliff:g>)"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"No extreguis el suport extern"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Configura"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Expulsa"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"Explora"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"No es detecta <xliff:g id="NAME">%s</xliff:g>"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"Torna a inserir el dispositiu"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"S\'està desplaçant l\'aplicació <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"S\'estan desplaçant dades"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"S\'ha transferit el contingut"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"El contingut s\'ha transferit al suport extern (<xliff:g id="NAME">%s</xliff:g>)"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"No s\'ha pogut transferir"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"Torna a provar de transferir el contingut"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"S\'ha retirat"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"S\'ha expulsat"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"S\'està comprovant..."</string>
@@ -1864,14 +1847,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"La SIM no està proporcionada per a la veu"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"La SIM no és compatible per a la veu"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"El telèfon no és compatible per a la veu"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"No s\'admet la SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"La SIM <xliff:g id="SIMNUMBER">%d</xliff:g> no s\'ha proporcionat"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"No s\'admet la SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"No s\'admet la SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Finestra emergent"</string>
<string name="slice_more_content" msgid="8504342889413274608">"<xliff:g id="NUMBER">%1$d</xliff:g> més"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"S\'ha canviat a una versió anterior de l\'aplicació o la versió actual no és compatible amb aquesta drecera"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 38f8cde..deedfe5 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1284,7 +1284,7 @@
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Denne enhed understøtter ikke dette <xliff:g id="NAME">%s</xliff:g>. Tryk for at konfigurere det til et understøttet format."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Denne enhed understøtter ikke dette <xliff:g id="NAME">%s</xliff:g>. Vælg for at konfigurere mediet i et understøttet format."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> blev fjernet uventet"</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Skub mediet ud, inden du fjerner det, så du ikke mister dit indhold"</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Demonter mediet, inden du fjerner det, så du ikke mister dit indhold"</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> er fjernet"</string>
<string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Nogle funktioner virker muligvis ikke som de skal. Indsæt en ny lagerenhed."</string>
<string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Skubber <xliff:g id="NAME">%s</xliff:g> ud"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 0bb17eb..935f9e1 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -82,7 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Keine Anrufe"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"Keine Anrufe oder Notrufe"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"Vorübergehend von deinem Mobilfunkanbieter deaktiviert"</string>
- <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Vorübergehend von deinem Mobilfunkanbieter für SIM <xliff:g id="SIMNUMBER">%d</xliff:g> deaktiviert"</string>
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Von deinem Mobilfunkanbieter für SIM <xliff:g id="SIMNUMBER">%d</xliff:g> vorübergehend deaktiviert"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"Mobilfunknetz nicht erreichbar"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Versuche, das bevorzugte Netzwerk zu ändern. Tippe, um ein anderes auszuwählen."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Notrufe nicht möglich"</string>
@@ -1274,7 +1274,7 @@
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Deaktivieren"</string>
<string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> wird geprüft…"</string>
<string name="ext_media_checking_notification_message" msgid="410185170877285434">"Aktuelle Inhalte werden geprüft"</string>
- <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Neues Medium (<xliff:g id="NAME">%s</xliff:g>)"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Neues Speichergerät (<xliff:g id="NAME">%s</xliff:g>)"</string>
<string name="ext_media_new_notification_message" msgid="3673685270558405087">"Zum Einrichten tippen"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Zum Übertragen von Fotos und Medien"</string>
<string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Problem mit <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1284,9 +1284,9 @@
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"<xliff:g id="NAME">%s</xliff:g> wird von diesem Gerät nicht unterstützt. Zum Einrichten in einem unterstützten Format tippen."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"<xliff:g id="NAME">%s</xliff:g> wird von diesem Gerät nicht unterstützt. Zur Einrichtung eines unterstützten Formats auswählen."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> wurde unerwartet entfernt"</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Trenne die Medien vor dem Entfernen, um Inhaltsverluste zu vermeiden"</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Lass das Speichergerät vor dem Entfernen auswerfen, damit keine Daten verloren gehen"</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> wurde entfernt"</string>
- <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Möglicherweise sind einige Funktionen fehlerhaft. Setze einen neuen Speicher ein."</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Einige Funktionen können möglicherweise nicht richtig genutzt werden. Sorge dafür, dass ein neues Speichergerät genutzt werden kann."</string>
<string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> wird ausgeworfen"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Nicht entfernen"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Einrichten"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index e00e175..462fd4b 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1013,10 +1013,8 @@
<string name="email_desc" msgid="3638665569546416795">"Email selected address"</string>
<string name="dial" msgid="1253998302767701559">"Call"</string>
<string name="dial_desc" msgid="6573723404985517250">"Call selected phone number"</string>
- <!-- no translation found for map (5441053548030107189) -->
- <skip />
- <!-- no translation found for map_desc (1836995341943772348) -->
- <skip />
+ <string name="map" msgid="5441053548030107189">"Map"</string>
+ <string name="map_desc" msgid="1836995341943772348">"Locate selected address"</string>
<string name="browse" msgid="1245903488306147205">"Open"</string>
<string name="browse_desc" msgid="8220976549618935044">"Open selected URL"</string>
<string name="sms" msgid="4560537514610063430">"Message"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 510bcb3..27bfedf 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1287,7 +1287,7 @@
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> ustekabean kendu da"</string>
<string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Kendu aurretik, kanporatu euskarria edukirik ez galtzeko"</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"Kendu egin da <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Funtzio batzuk agian ez dira behar bezala ibiliko. Sartu memoria-gailu berria."</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Funtzio batzuek agian ez dute behar bezala funtzionatuko. Sartu biltegiratze-gailu berria."</string>
<string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> kanporatzen"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Ez kendu"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Konfiguratu"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index cf0a734..bffe248 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -82,7 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Aucun service vocal"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"Aucun de service vocal ni d\'appel d\'urgence"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"Temporairement désactivé par votre fournisseur de services"</string>
- <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Temporairement désactivé par votre fournisseur de services pour la carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Temporairement désactivé par votre fournisseur de services pour la carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"Impossible de joindre le réseau cellulaire"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Essayez de changer de réseau préféré. Touchez l\'écran pour changer."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Le service d\'appel d\'urgence n\'est pas accessible"</string>
@@ -1274,7 +1274,7 @@
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Désactiver"</string>
<string name="ext_media_checking_notification_title" msgid="4411133692439308924">"Vérification de <xliff:g id="NAME">%s</xliff:g> en cours…"</string>
<string name="ext_media_checking_notification_message" msgid="410185170877285434">"Vérification du contenu actuel"</string>
- <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Nouveau/nouvelle <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Nouveau périphérique <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_new_notification_message" msgid="3673685270558405087">"Toucher pour configurer"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Pour transférer des photos et d\'autres fichiers"</string>
<string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Il y a un problème avec <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1298,7 +1298,7 @@
<string name="ext_media_move_title" msgid="1022809140035962662">"Déplacement des données..."</string>
<string name="ext_media_move_success_title" msgid="7863652232242276066">"Transfert de contenu terminé"</string>
<string name="ext_media_move_success_message" msgid="8939137931961728009">"Contenu déplacé vers <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="ext_media_move_failure_title" msgid="1604422634177382092">"Impossible de déplacer contenu"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"Impossible de déplacer le contenu"</string>
<string name="ext_media_move_failure_message" msgid="7388950499623016135">"Essayez de déplacer le contenu de nouveau"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"Supprimée"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"Éjectée"</string>
@@ -1847,10 +1847,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"Cette carte SIM n\'est pas autorisée pour la voix"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"Cette carte SIM n\'est pas autorisée pour la voix"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"Ce téléphone n\'est pas autorisé pour la voix"</string>
- <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"La carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> n\'est pas autorisée"</string>
- <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"Carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> non configurée"</string>
- <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"La carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> n\'est pas autorisée"</string>
- <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"La carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> n\'est pas autorisée"</string>
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"La carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> n\'est pas autorisée"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"La carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> n\'est pas configurée"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"La carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> n\'est pas autorisée"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"La carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> n\'est pas autorisée"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Fenêtre contextuelle"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"La version de l\'application a été rétrogradée ou n\'est pas compatible avec ce raccourci"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 991e3ce..8a19b4f 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1274,7 +1274,7 @@
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Désactiver"</string>
<string name="ext_media_checking_notification_title" msgid="4411133692439308924">"Vérification de \"<xliff:g id="NAME">%s</xliff:g>\"…"</string>
<string name="ext_media_checking_notification_message" msgid="410185170877285434">"Vérification du contenu actuel"</string>
- <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Nouvelle <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Nouveau périphérique : <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_new_notification_message" msgid="3673685270558405087">"Appuyer pour configurer"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Pour transférer photos et fichiers"</string>
<string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Problème avec : <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1284,16 +1284,16 @@
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Cet appareil n\'est pas compatible avec la mémoire de stockage \"<xliff:g id="NAME">%s</xliff:g>\". Appuyez ici pour le configurer dans un format accepté."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Cet appareil n\'est pas compatible avec cette <xliff:g id="NAME">%s</xliff:g>. Sélectionnez cette option pour la configurer dans un format accepté."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"Retrait inattendu de mémoire \"<xliff:g id="NAME">%s</xliff:g>\""</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Éjectez la mémoire de stockage externe avant de la retirer pour éviter toute perte de contenu"</string>
- <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> supprimée"</string>
- <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Certaines fonctionnalités risquent de ne pas s\'exécuter correctement. Insérez une nouvelle mémoire de stockage externe."</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Éjectez le périphérique externe avant de le retirer pour éviter toute perte de contenu"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> supprimé"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Certaines fonctionnalités risquent de ne pas s\'exécuter correctement. Insérez un nouveau périphérique de stockage externe."</string>
<string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Éjection de \"<xliff:g id="NAME">%s</xliff:g>\""</string>
- <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Ne retirez pas la mémoire de stockage"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Ne retirez pas le périphérique"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Configurer"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Éjecter"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"Parcourir"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"Mémoire de stockage \"<xliff:g id="NAME">%s</xliff:g>\" manquante"</string>
- <string name="ext_media_missing_message" msgid="4012389235250987930">"Insérez de nouveau la mémoire"</string>
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"Insérez le périphérique"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"Transfert de l\'application <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"Déplacement des données en cours"</string>
<string name="ext_media_move_success_title" msgid="7863652232242276066">"Le contenu a bien été déplacé"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index b92d702..8690318 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"કોઈ વૉઇસ સેવા નથી"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"કોઈ વૉઇસ સેવા અથવા કટોકટીની કૉલિંગ સેવા નથી"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"તમારા કૅરિઅરે હંગામી રૂપે બંધ કરી છે"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"તમારા કૅરિઅર દ્વારા સિમ <xliff:g id="SIMNUMBER">%d</xliff:g> માટે હંગામી રૂપે બંધ કરેલ છે"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"મોબાઇલ નેટવર્ક સુધી પહોંચી શકાતું નથી"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"પસંદગીનું નેટવર્ક બદલવાનો પ્રયાસ કરો. બદલવા માટે ટૅપ કરો."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"કટોકટીની કૉલિંગ સેવા અનુપલબ્ધ"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"ઓળખાયેલ નથી"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"ફિંગરપ્રિન્ટ પ્રમાણિત કરી"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ફિંગરપ્રિન્ટ હાર્ડવેર ઉપલબ્ધ નથી."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"ફિંગરપ્રિન્ટ સંગ્રહિત કરી શકાતી નથી. કૃપા કરીને અસ્તિત્વમાંની ફિંગરપ્રિન્ટ દૂર કરો."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ફિંગરપ્રિન્ટનો સમય બાહ્ય થયો. ફરી પ્રયાસ કરો."</string>
@@ -1275,49 +1273,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનો પર દેખાઈ છે"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"જો તમે નથી ઇચ્છતા કે <xliff:g id="NAME">%s</xliff:g> આ સુવિધાનો ઉપયોગ કરે, તો સેટિંગ્સ ખોલવા માટે ટૅપ કરો અને તેને બંધ કરો."</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"બંધ કરો"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> તપાસી રહ્યાં છીએ…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"હાલના કન્ટેન્ટને રિવ્યૂ કરવું"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"નવું <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"સેટ કરવા માટે ટૅપ કરો"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ફોટો અને મીડિયા ટ્રાન્સફર કરવા માટે"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g>ની સમસ્યા"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"ઠીક કરવા માટે ટૅપ કરો"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> દૂષિત છે. સુધારવા માટે પસંદ કરો."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"અસમર્થિત <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"આ ઉપકરણ આ <xliff:g id="NAME">%s</xliff:g> નું સમર્થન કરતું નથી. સમર્થિત ફોર્મેટમાં સેટ કરવા માટે ટૅપ કરો."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"આ ઉપકરણ આ <xliff:g id="NAME">%s</xliff:g> નું સમર્થન કરતું નથી. સમર્થિત ફૉર્મેટમાં સેટ કરવા માટે પસંદ કરો."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> અનપેક્ષિત રીતે દૂર કર્યું"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"કન્ટેન્ટ ગુમાવવાનું ટાળવા માટે મીડિયાને દૂર કરતા પહેલાં બહાર કાઢો"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> કાઢી નાખ્યું"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"કેટલીક કાર્યક્ષમતા કદાચ યોગ્ય રીતે કામ ન કરી શકે. નવું સ્ટોરેજ દાખલ કરો."</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g>ને બહાર કાઢી રહ્યાં છીએ"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"કાઢી નાખશો નહીં"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"સેટ કરો"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"બહાર કાઢો"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"અન્વેષણ કરો"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> ખૂટે છે"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"ફરીથી ઉપકરણ દાખલ કરો"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> ખસેડી રહ્યાં છીએ"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"ડેટાને ખસેડી રહ્યાં છીએ"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"કન્ટેન્ટ ટ્રાન્સફર કરવાનું પૂર્ણ થયું"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"કન્ટેન્ટ <xliff:g id="NAME">%s</xliff:g>માં ખસેડ્યું"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"કન્ટેન્ટ ખસેડી શક્યાં નથી"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"ફરીથી કન્ટેન્ટ ખસેડવાનો પ્રયાસ કરો"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"દૂર કર્યું"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"બહાર કાઢ્યું"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"તપાસી રહ્યું છે..."</string>
@@ -1865,14 +1848,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"આ સિમમાં વૉઇસ માટે કોઈ જોગવાઈ નથી"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"વૉઇસ માટે આ સિમને મંજૂરી નથી"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"વૉઇસ માટે આ ફોનને મંજૂરી નથી"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"સિમ <xliff:g id="SIMNUMBER">%d</xliff:g>ને મંજૂરી નથી"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"સિમ <xliff:g id="SIMNUMBER">%d</xliff:g>ની જોગવાઈ કરી નથી"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"સિમ <xliff:g id="SIMNUMBER">%d</xliff:g>ને મંજૂરી નથી"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"સિમ <xliff:g id="SIMNUMBER">%d</xliff:g>ને મંજૂરી નથી"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"પૉપઅપ વિંડો"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"આ ઍપનું વર્ઝન ડાઉનગ્રેડ કરવામાં આવ્યું છે અથવા આ શૉર્ટકટ સાથે સુસંગત નથી"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index e154a07..b0586fd 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"कोई वॉइस सेवा नहीं है"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"सामान्य (वॉइस) कॉल या आपातकालीन कॉल पर रोक लगा दी गई है"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"आपकी मोबाइल और इंटरनेट सेवा देने वाली कंपनी ने सेवा पर कुछ समय के लिए रोक लगा दी है"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"सिम <xliff:g id="SIMNUMBER">%d</xliff:g> पर आपकी मोबाइल और इंटरनेट सेवा देने वाली कंपनी ने कुछ समय के लिए सेवा बंद कर दी है"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"मोबाइल नेटवर्क से कनेक्ट नहीं किया जा सका"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"पसंदीदा नेटवर्क बदलकर देखें. बदलने के लिए टैप करें."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"आपातकालीन कॉल करने की सुविधा उपलब्ध नहीं है"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"पहचाना नहीं गया"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"फ़िंगरप्रिंट की पुष्टि हो गई"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फ़िंगरप्रिंट हार्डवेयर उपलब्ध नहीं है."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को संग्रहित नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें."</string>
@@ -1021,7 +1019,7 @@
<string name="browse" msgid="1245903488306147205">"खोलें"</string>
<string name="browse_desc" msgid="8220976549618935044">"चुना गया यूआरएल खोलें"</string>
<string name="sms" msgid="4560537514610063430">"मैसेज"</string>
- <string name="sms_desc" msgid="7526588350969638809">"चुने गए फ़ोन नंबर को मैसेज (एसएमएस) करें"</string>
+ <string name="sms_desc" msgid="7526588350969638809">"चुने गए फ़ोन नंबर को मैसेज करें"</string>
<string name="add_contact" msgid="7867066569670597203">"जोड़ें"</string>
<string name="add_contact_desc" msgid="4830217847004590345">"संपर्क सूची में जोड़ें"</string>
<string name="view_calendar" msgid="979609872939597838">"देखें"</string>
@@ -1274,49 +1272,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य ऐप पर दिखाई दे रहा है"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"अगर आप नहीं चाहते कि <xliff:g id="NAME">%s</xliff:g> इस सुविधा का उपयोग करे, तो सेटिंग खोलने और उसे बंद करने के लिए टैप करें."</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"बंद करें"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> ढूंढा जा रहा है…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"मौजूदा सामग्री की जाँच की जा रही है"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"नया <xliff:g id="NAME">%s</xliff:g> लगाया गया"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"सेटअप करने के लिए टैप करें"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"फ़ोटो और मीडिया ट्रांसफर करने के लिए"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> में गड़बड़ी है"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"समस्या ठीक करने के लिए टैप करें"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> काम नहीं कर रहा है. ठीक करने के लिए चुनें."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"असमर्थित <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"यह डिवाइस इस <xliff:g id="NAME">%s</xliff:g> का समर्थन नहीं करता है. समर्थित प्रारूप में सेट करने के लिए टैप करें."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"इस डिवाइस पर <xliff:g id="NAME">%s</xliff:g> काम नहीं करता है. काम करने वाले प्रारूप में सेट अप करने के लिए चुनें."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> अप्रत्याशित रूप से निकाला गया"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"मीडिया डिवाइस निकालने से पहले, उसे निकालने का विकल्प चुनें ताकि आपकी सामग्री सुरक्षित रहे"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> निकाला गया."</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"हो सकता है कि कुछ सुविधाएं ठीक तरह से काम न करें. ज़्यादा जगह पाने के लिए नया एसडी कार्ड जोड़ें."</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> बाहर निकाला जा रहा है…"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"बाहर न निकालें"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"सेट करें"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"निकालें"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"एक्सप्लोर करें"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> गुम है"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"डिवाइस को दोबारा लगाएं"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> को ले जाया जा रहा है"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"डेटा ले जाया जा रहा है"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"सामग्री ट्रांसफ़र की गई"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"सामग्री <xliff:g id="NAME">%s</xliff:g> में ट्रांसफ़र की गई"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"सामग्री ट्रांसफ़र नहीं की जा सकी"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"सामग्री दोबारा ट्रांसफ़र करने की कोशिश करें"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"निकाल दिया गया"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"निकाला गया"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"जाँच की जा रही है..."</string>
@@ -1864,14 +1847,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"सिम से कॉल करने की इजाज़त नहीं है"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"सिम से कॉल करने की इजाज़त नहीं है"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"फ़ोन से कॉल करने की इजाज़त नहीं है"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"सिम <xliff:g id="SIMNUMBER">%d</xliff:g> को कॉल के लिए इस्तेमाल नहीं किया जा सकता"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"सिम <xliff:g id="SIMNUMBER">%d</xliff:g> काम नहीं कर रहा है"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"सिम <xliff:g id="SIMNUMBER">%d</xliff:g> को कॉल के लिए इस्तेमाल नहीं किया जा सकता"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"सिम <xliff:g id="SIMNUMBER">%d</xliff:g> को कॉल के लिए इस्तेमाल नहीं किया जा सकता"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"पॉपअप विंडो"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"ऐप्लिकेशन का वर्शन पुराना हो चुका है या यह इस शॉर्टकट के साथ काम नहीं करता"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 749dcba..9a235d4 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Símtöl eru ekki í boði"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"Engin raddþjónusta eða neyðarsímtöl"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"Símafyrirtækið slökkti tímabundið á þessu"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Símafyrirtækið slökkti tímabundið á þessu fyrir SIM-kort <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"Ekki næst samband við farsímakerfi"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Prófaðu að velja annað símkerfi. Ýttu til að breyta."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Neyðarsímtöl eru ekki í boði"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"Þekktist ekki"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingrafar staðfest"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingrafarsvélbúnaður ekki til staðar."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ekki er hægt að vista fingrafarið. Fjarlægðu eitthvert af fingraförunum sem fyrir eru."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
@@ -1275,49 +1273,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> birtist yfir öðrum forritum"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ef þú vilt ekki að <xliff:g id="NAME">%s</xliff:g> noti þennan eiginleika skaltu ýta til að opna stillingarnar og slökkva á því."</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Slökkva"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"Athugar <xliff:g id="NAME">%s</xliff:g>…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"Fer yfir núverandi efni"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Nýtt <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"Ýttu til að setja upp"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Til að flytja myndir og aðrar skrár"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Vandamál með <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"Ýttu til að lagfæra"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> er skemmt. Veldu til að lagfæra."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"Óstutt <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Þetta tæki styður ekki <xliff:g id="NAME">%s</xliff:g>. Ýttu til að setja upp með studdu sniði."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Þetta tæki styður ekki <xliff:g id="NAME">%s</xliff:g>. Veldu til að setja upp með studdu sniði."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> fjarlægt án fyrirvara"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Aftengdu geymslumiðil áður en þú tekur hann úr sambandi til að koma í veg fyrir að þú glatir efni"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> fjarlægt"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Ekki er víst að allt virki eðlilega. Tengdu nýjan geymslumiðil."</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Aftengir <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Ekki fjarlægja"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Setja upp"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Fjarlægja"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"Kanna"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> vantar"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"Tengdu tækið aftur"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"Flytur <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"Flytur gögn"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"Efni hefur verið flutt"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"Efni flutt yfir í <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"Ekki var hægt að flytja efni"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"Reyndu að flytja efni aftur"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"Fjarlægð"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"Aftengd"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"Athugar…"</string>
@@ -1865,14 +1848,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM-korti er ekki úthlutað fyrir rödd"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"SIM-kort er ekki heimilað fyrir rödd"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"Sími er ekki heimilaður fyrir rödd"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM-kort <xliff:g id="SIMNUMBER">%d</xliff:g> er ekki leyft"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> hefur ekki verið úthlutað"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"SIM-kort <xliff:g id="SIMNUMBER">%d</xliff:g> er ekki leyft"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"SIM-kort <xliff:g id="SIMNUMBER">%d</xliff:g> er ekki leyft"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Sprettigluggi"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"Útgáfa forritsins er of gömul eða er ekki samhæf þessari flýtileið"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index fafde5c..dcec074 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -272,31 +272,31 @@
<string name="managed_profile_label" msgid="8947929265267690522">"Passa a profilo di lavoro"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedere ai contatti"</string>
- <string name="permgrouprequest_contacts" msgid="6032805601881764300">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere ai tuoi contatti?"</string>
+ <string name="permgrouprequest_contacts" msgid="6032805601881764300">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere ai tuoi contatti?"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Geolocalizzazione"</string>
<string name="permgroupdesc_location" msgid="1346617465127855033">"accedere alla posizione di questo dispositivo"</string>
- <string name="permgrouprequest_location" msgid="3788275734953323491">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere alla posizione di questo dispositivo?"</string>
+ <string name="permgrouprequest_location" msgid="3788275734953323491">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere alla posizione di questo dispositivo?"</string>
<string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendario"</string>
<string name="permgroupdesc_calendar" msgid="3889615280211184106">"accedere al calendario"</string>
- <string name="permgrouprequest_calendar" msgid="289900767793189421">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere al tuo calendario?"</string>
+ <string name="permgrouprequest_calendar" msgid="289900767793189421">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere al tuo calendario?"</string>
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
<string name="permgroupdesc_sms" msgid="4656988620100940350">"inviare e visualizzare SMS"</string>
- <string name="permgrouprequest_sms" msgid="7168124215838204719">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di inviare e visualizzare SMS?"</string>
+ <string name="permgrouprequest_sms" msgid="7168124215838204719">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di inviare e visualizzare SMS?"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Archiviazione"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"accedere a foto, contenuti multimediali e file sul dispositivo"</string>
- <string name="permgrouprequest_storage" msgid="7885942926944299560">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere a foto, contenuti multimediali e file memorizzati sul dispositivo?"</string>
+ <string name="permgrouprequest_storage" msgid="7885942926944299560">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere a foto, contenuti multimediali e file memorizzati sul dispositivo?"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Microfono"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"registrare audio"</string>
- <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di registrare audio?"</string>
+ <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di registrare audio?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Fotocamera"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"scattare foto e registrare video"</string>
- <string name="permgrouprequest_camera" msgid="1299833592069671756">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di scattare foto e registrare video?"</string>
+ <string name="permgrouprequest_camera" msgid="1299833592069671756">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di scattare foto e registrare video?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telefono"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"eseguire e gestire le telefonate"</string>
- <string name="permgrouprequest_phone" msgid="9166979577750581037">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di effettuare e gestire telefonate?"</string>
+ <string name="permgrouprequest_phone" msgid="9166979577750581037">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di effettuare e gestire telefonate?"</string>
<string name="permgrouplab_sensors" msgid="416037179223226722">"Sensori per il corpo"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"accedere ai dati dei sensori relativi ai tuoi parametri vitali"</string>
- <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Vuoi consentire all\'app <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere ai dati dei sensori relativi ai parametri vitali?"</string>
+ <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Consentire a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere ai dati dei sensori relativi ai parametri vitali?"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperare contenuti della finestra"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Esaminare i contenuti di una finestra con cui interagisci."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Attivare Esplora al tocco"</string>
@@ -1272,12 +1272,12 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"App <xliff:g id="NAME">%s</xliff:g> mostrata sopra altre app"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Disattiva"</string>
- <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"Controllo della <xliff:g id="NAME">%s</xliff:g>…"</string>
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"Controllo del dispositivo <xliff:g id="NAME">%s</xliff:g>…"</string>
<string name="ext_media_checking_notification_message" msgid="410185170877285434">"Controllo dei contenuti correnti"</string>
- <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Nuova <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"Nuovo dispositivo <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_new_notification_message" msgid="3673685270558405087">"Tocca per configurare"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Per trasferire foto e altri file"</string>
- <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Problema con la <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"Problema con <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"Tocca per risolvere il problema"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"Il supporto esterno <xliff:g id="NAME">%s</xliff:g> è danneggiato. Seleziona per risolvere il problema."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> non supportata"</string>
@@ -1285,19 +1285,19 @@
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Il dispositivo non supporta questo tipo di <xliff:g id="NAME">%s</xliff:g>. Seleziona per eseguire la configurazione in un formato supportato."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"Rimozione imprevista della <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Espelli il supporto prima di rimuoverlo per evitare di perdere contenuti"</string>
- <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> rimossa"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"Dispositivo <xliff:g id="NAME">%s</xliff:g> rimosso"</string>
<string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Alcune funzionalità potrebbero non funzionare correttamente. Inserisci un nuovo supporto di archiviazione."</string>
- <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Espulsione della <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Espulsione di <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Non rimuovere"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Configura"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Espelli"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"Apri"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> mancante"</string>
- <string name="ext_media_missing_message" msgid="4012389235250987930">"Inserisci di nuovo dispositivo"</string>
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"Reinserisci il dispositivo"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"Spostamento di <xliff:g id="NAME">%s</xliff:g> in corso"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"Spostamento dei dati in corso"</string>
<string name="ext_media_move_success_title" msgid="7863652232242276066">"Trasferimento contenuti completo"</string>
- <string name="ext_media_move_success_message" msgid="8939137931961728009">"Contenuti spostati sulla <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"Contenuti spostati su <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_move_failure_title" msgid="1604422634177382092">"Impossibile spostare i contenuti"</string>
<string name="ext_media_move_failure_message" msgid="7388950499623016135">"Riprova a spostare i contenuti"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"Rimosso"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index f6d4e3a..6f7d40e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1284,7 +1284,7 @@
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"この端末はこの <xliff:g id="NAME">%s</xliff:g>に対応していません。タップして、対応している形式でセットアップしてください。"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"この端末はこの <xliff:g id="NAME">%s</xliff:g>に対応していません。サポートされるフォーマットで設定するには選択してください。"</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g>が不適切に取り外されました"</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"コンテンツを消去しないようメディアを取り出してから取り外してください"</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"コンテンツの喪失を防ぐため、メディアを取り出してから取り外してください"</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g>の取り外し"</string>
<string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"一部の機能が正しく動作しない可能性があります。新しいストレージを挿入してください。"</string>
<string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g>を取り出しています"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 5f4a4e6..0cf43e2 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1278,17 +1278,17 @@
<string name="ext_media_new_notification_title" msgid="1621805083736634077">"Жаңа <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_new_notification_message" msgid="3673685270558405087">"Реттеу үшін түртіңіз"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Фотосуреттер мен медиа файлдарын тасымалдау үшін"</string>
- <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> арқылы шығарыңыз"</string>
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> ақаулы"</string>
<string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"Түзету үшін түртіңіз"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> бүлінген. Түзету үшін оны түртіңіз."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"Қолданылмайтын <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Бұл құрылғы <xliff:g id="NAME">%s</xliff:g> картасына қолдау көрсетеді. Қолдау көрсетілетін пішімде орнату үшін түртіңіз."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Бұл құрылғыда <xliff:g id="NAME">%s</xliff:g> картасына қолдау көрсетілмейді. Қолдау көрсетілетін форматта реттеуді таңдаңыз."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> кенеттен шығарылды"</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Мазмұнды жоғалтып алмау үшін ақпарат тасығышты алдымен шығарыңыз, одан кейін алыңыз."</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Мазмұнды жоғалтып алмау үшін ақпарат тасығышты алдымен ажыратыңыз, содан кейін барып шығарыңыз."</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> жоқ"</string>
<string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Кейбір функциялар дұрыс жұмыс істемеуі мүмкін. Жаңа жад құрылғысын енгізіңіз."</string>
- <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> шығарылуда"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> ажыратылуда"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Шығармаңыз"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Реттеу"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Шығару"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f2af6e5..457db54 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1285,9 +1285,9 @@
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"이 기기는 이 <xliff:g id="NAME">%s</xliff:g>을(를) 지원하지 않습니다. 선택하여 지원되는 형식으로 설정하세요."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g>이(가) 예기치 않게 삭제됨"</string>
<string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"콘텐츠 손실을 피하려면 미디어를 제거하기 전에 마운트 해제하세요."</string>
- <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g>이(가) 제거됨"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> 제거됨"</string>
<string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"일부 기능이 제대로 작동하지 않을 수 있습니다. 새로운 저장소를 삽입하세요."</string>
- <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g>을(를) 마운트 해제하는 중"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> 마운트 해제 중"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"외부 미디어를 제거하지 마세요."</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"설정"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"마운트 해제"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 8d4d20b..c1fb9f8 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -82,7 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Аудио чалуу кызматы бөгөттөлгөн"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"Чалуу жана шашылыш чалуу кызматы бөгөттөлгөн"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"Байланыш оператору убактылуу бөгөттөп койгон"</string>
- <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"<xliff:g id="SIMNUMBER">%d</xliff:g> SIM-картасы үчүн байланыш оператору тарабынан убактылуу бөгөттөлгөн"</string>
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> үчүн байланыш оператору тарабынан убактылуу бөгөттөлгөн"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"Мобилдик тармакка туташпай жатат"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Тандалган тармакты өзгөртүп көрүңүз. Өзгөртүү үчүн таптаңыз."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Шашылыш чалуу жеткиликсиз"</string>
@@ -1286,10 +1286,10 @@
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Бул түзмөктө <xliff:g id="NAME">%s</xliff:g> колдоого алынбайт. Колдоого алынуучу форматта орнотуу үчүн таптап коюңуз."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Бул түзмөктө <xliff:g id="NAME">%s</xliff:g> колдоого алынбайт. Колдоого алынуучу форматта орнотуу үчүн тандаңыз."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> күтүүсүздөн алынып салынды"</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Мазмунду жоготуунун алдын алуу үчүн алып салуудан мурда медианы чыгарыңыз"</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Мазмунду жоготуп албаш үчүн алып салуудан мурда медианы өчүрүңүз"</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> чыгарылды"</string>
<string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Айрым функциялар талаптагыдай иштебей калышы мүмкүн. Жаңы сактагычты салыңыз."</string>
- <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> чыгарылууда"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> өчүрүлүүдө"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Чыгарбаңыз"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Орнотуу"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Чыгаруу"</string>
@@ -1299,7 +1299,7 @@
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> сактагычына ооштурулууда"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"Дайындар ооштурулууда…"</string>
<string name="ext_media_move_success_title" msgid="7863652232242276066">"Мазмунду өткөрүү аягына чыкты"</string>
- <string name="ext_media_move_success_message" msgid="8939137931961728009">"Мазмун <xliff:g id="NAME">%s</xliff:g> SD-картасына жылдырылды"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"Мазмун <xliff:g id="NAME">%s</xliff:g> сактагычына жылдырылды"</string>
<string name="ext_media_move_failure_title" msgid="1604422634177382092">"Мазмун жылдырылбай койду"</string>
<string name="ext_media_move_failure_message" msgid="7388950499623016135">"Мазмунду кайра жылдырып көрүңүз"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"Өчүрүлдү"</string>
@@ -1849,10 +1849,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM-карта сүйлөшүү үчүн таанылган жок"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"SIM-картаны сүйлөшүү үчүн колдонууга тыюу салынган"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"Телефонду сүйлөшүү үчүн колдонууга тыюу салынган"</string>
- <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"<xliff:g id="SIMNUMBER">%d</xliff:g> номериндеги SIM-картасына уруксат берилген жок"</string>
- <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"<xliff:g id="SIMNUMBER">%d</xliff:g> номериндеги SIM-карта таанылган жок"</string>
- <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"<xliff:g id="SIMNUMBER">%d</xliff:g> номериндеги SIM-картасына уруксат берилген жок"</string>
- <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"<xliff:g id="SIMNUMBER">%d</xliff:g> номериндеги SIM-картасына уруксат берилген жок"</string>
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> картасына уруксат берилген жок"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> картасы таанылган жок"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> картасына уруксат берилген жок"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> картасына уруксат берилген жок"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Калкып чыкма терезе"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"Колдонмонун мурунку версиясын иштетип жатасыз же ал бул шилтемеге шайкеш эмес"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 4fa37f9..de6d37b 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1285,10 +1285,10 @@
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Уредот не ја поддржува оваа <xliff:g id="NAME">%s</xliff:g>. Допрете за поставување во поддржан формат."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Уредов не ја поддржува оваа <xliff:g id="NAME">%s</xliff:g>. Изберете за поставување во поддржан формат."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> неочекувано е отстранета"</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Откачете ја надворешната меморија пред да ја отстраните за да избегнете губење содржини"</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Исклучете ја надворешната меморија пред да ја отстраните за да избегнете губење содржини"</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> е отстранета"</string>
<string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Некои функции можеби нема да работат правилно. Вметнете нова надворешна меморија."</string>
- <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Се откачува <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Се исклучува <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Не отстранувајте"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Постави"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Извади"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index ad39d8f..62061f1 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1300,7 +1300,7 @@
<string name="ext_media_move_success_title" msgid="7863652232242276066">"ഉള്ളടക്ക കൈമാറ്റം പൂർത്തിയായി"</string>
<string name="ext_media_move_success_message" msgid="8939137931961728009">"ഉള്ളടക്കം <xliff:g id="NAME">%s</xliff:g>-ലേക്ക് നീക്കി"</string>
<string name="ext_media_move_failure_title" msgid="1604422634177382092">"ഉള്ളടക്കം നീക്കാനായില്ല"</string>
- <string name="ext_media_move_failure_message" msgid="7388950499623016135">"ഉള്ളടക്കം നീക്കുന്നതിന് വീണ്ടും ശ്രമിക്കുക"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"ഉള്ളടക്കം നീക്കാൻ വീണ്ടും ശ്രമിക്കുക"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"നീക്കംചെയ്തു"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"ഇജക്റ്റുചെയ്തു"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"പരിശോധിക്കുന്നു…"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 18c665d..dff7e8b 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1273,22 +1273,22 @@
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглахыг хүсэхгүй байгаа бол тохиргоог нээгээд, унтраана уу."</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Унтраах"</string>
<string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g>-г шалгаж байна…"</string>
- <string name="ext_media_checking_notification_message" msgid="410185170877285434">"Одоогийн агуулгыг харж байна"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"Одоогийн агуулгыг хянаж байна"</string>
<string name="ext_media_new_notification_title" msgid="1621805083736634077">"Шинэ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_new_notification_message" msgid="3673685270558405087">"Тохируулахын тулд товшино уу"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Зураг, медиа шилжүүлэхэд зориулсан"</string>
- <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g>-р олгоно уу"</string>
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> алдаатай байна"</string>
<string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"Засахын тулд товшино уу"</string>
<string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> эвдэрсэн байна. Засахын тулд сонгоно уу."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"Дэмжээгүй <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Энэ төхөөрөмж нь <xliff:g id="NAME">%s</xliff:g>-г дэмждэггүй. Дэмжигдсэн хэлбэршүүлэлтэд тохируулахын тулд товшино уу."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Энэ төхөөрөмж <xliff:g id="NAME">%s</xliff:g>-г дэмждэггүй. Дэмжсэн хэлбэршүүлэлтэд тохируулахын тулд сонгоно уу."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g>-ыг гэнэт гаргасан байна"</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Агуулга алдахаас сэргийлэхийн тулд медиаг устгахаасаа өмнө салгана уу"</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Агуулга алдахаас сэргийлэхийн тулд медиаг төхөөрөмжөөс салгахаасаа өмнө холболтыг салгана уу"</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g>-г устгасан"</string>
<string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Зарим функц зөв ажиллахгүй байж болзошгүй. Шинэ хадгалах сан оруулна уу."</string>
<string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g>-г салгаж байна"</string>
- <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Бүү устга"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Бүү салга"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Тохируулах"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Салгах"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"Судлах"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index aa54aca4..7ebb087 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"व्हॉइस सेवा नाही"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"व्हॉइस सेवा किंवा आणीबाणी कॉलिंग नाही"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"तुमच्या वाहकाने तात्पुरते बंद केले आहे"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"<xliff:g id="SIMNUMBER">%d</xliff:g> सिमसाठी तुमच्या वाहकाने तात्पुरते बंद केले आहे"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"मोबाइल नेटवर्क उपलब्ध नाही"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"प्राधान्य दिलेले नेटवर्क बदलण्याचा प्रयत्न करा. बदलण्यासाठी टॅप करा."</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"आणीबाणी कॉलिंग अनुपलब्ध"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"ओळखले नाही"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"फिंगरप्रिंट ऑथेंटिकेट केली आहे"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फिंगरप्रिंट हार्डवेअर उपलब्ध नाही."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"फिंगरप्रिंट स्टोअर केले जाऊ शकत नाही. कृपया विद्यमान फिंगरप्रिंट काढा."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिंट टाइमआउट झाले. पुन्हा प्रयत्न करा."</string>
@@ -1275,49 +1273,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य अॅप्सवर प्रदर्शित करत आहे"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ने हे वैशिष्ट्य वापरू नये असे आपण इच्छित असल्यास, सेटिंग्ज उघडण्यासाठी टॅप करा आणि ते बंद करा."</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"बंद करा"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> तपासत आहे…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"सध्याच्या आशयाचे पुनरावलोकन करत आहे"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"नवीन <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"सेट करण्यासाठी टॅप करा"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"फोटो आणि मीडिया स्थानांतरित करण्यासाठी"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> सह समस्या"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"दुरुस्त करण्यासाठी टॅप करा"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> दूषित आहे. निश्चित करण्यासाठी निवडा."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> असमर्थित"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"हे डिव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी टॅप करा."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"हे डिव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी निवडा."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> अनपेक्षितरित्या काढले"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"आशय गमावणे टाळण्यासाठी काढून टाकण्यापूर्वी मीडिया इजेक्ट करा"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> काढून टाकले आहे."</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"काही कार्यक्षमता कदाचीत योग्यरित्या कार्य करू करणार नाहीत. नवीन स्टोरेज घाला."</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> बाहेर काढत आहे"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"काढू नका"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"सेट करा"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"बाहेर काढा"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"एक्सप्लोर करा"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> गहाळ आहे"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"डिव्हाइस पुन्हा घाला"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> हलवित आहे"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"डेटा हलवित आहे"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"आशय ट्रांसफर झाला आहे"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"<xliff:g id="NAME">%s</xliff:g> वर आशय हलवला आहे"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"आशय हलवू शकलो नाही"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"पुन्हा आशय हलवून पहा"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"काढले"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"बाहेर काढले"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"तपासत आहे..."</string>
@@ -1865,14 +1848,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"सिममध्ये व्हॉइसची तरतूद नाही"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"व्हॉइसची सिमला अनुमती नाही"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"व्हॉइसची फोनला अनुमती नाही"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"<xliff:g id="SIMNUMBER">%d</xliff:g> सिमला अनुमती नाही"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"<xliff:g id="SIMNUMBER">%d</xliff:g> सिमची तरतूद केलेली नाही"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"<xliff:g id="SIMNUMBER">%d</xliff:g> सिमला अनुमती नाही"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"<xliff:g id="SIMNUMBER">%d</xliff:g> सिमला अनुमती नाही"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"पॉपअप विंडो"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"अॅपची आवृत्ती डाउनग्रेड केली, किंवा ती या शॉर्टकटशी कंपॅटिबल नाही"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index e802f0c..5a30d2e 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -497,7 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"အသိအမှတ်မပြုပါ"</string>
- <string name="fingerprint_authenticated" msgid="5309333983002526448">"လက်ဗွေကို အထောက်အထားစိစစ်ပြီးပါပြီ"</string>
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"လက်ဗွေကို အထောက်အထား စိစစ်ပြီးပါပြီ"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"လက်ဗွေရာ ဟာ့ဒ်ဝဲ မရနိုင်ပါ။"</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"လက်ဗွေရာ သိုလှောင်၍မရပါ။ ကျေးဇူးပြု၍ ရှိပြီးလက်ဗွေရာအား ဖယ်ရှားပါ။"</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index ddd4111..3f64397 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -287,7 +287,7 @@
<string name="permgrouprequest_storage" msgid="7885942926944299560">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toegang geven tot foto\'s, media en bestanden op je apparaat?"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Microfoon"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"audio opnemen"</string>
- <string name="permgrouprequest_microphone" msgid="9167492350681916038">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toestaan om audio op te nemen?"</string>
+ <string name="permgrouprequest_microphone" msgid="9167492350681916038">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> het volgende toestaan: audio opnemen."</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"foto\'s maken en video opnemen"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toestaan om foto\'s te maken en video op te nemen?"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index b660c20..b341cf4 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"କୌଣସି ଭଏସ୍ ସେବା ନାହିଁ"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"କୌଣସି ଭଏସ୍ ସେବା କିମ୍ବା ଜରୁରୀକାଳୀନ କଲିଙ୍ଗ ନାହିଁ"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"ଆପଣଙ୍କ କେରିଅର୍ଙ୍କ ଦ୍ୱାରା ଅସ୍ଥାୟୀ ରୂପେ ବନ୍ଦ କରାଯାଇଛି"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> ପାଇଁ ଆପଣଙ୍କ କେରିଅର୍ ଦ୍ୱାରା ଅସ୍ଥାୟୀ ରୂପେ ବନ୍ଦ କରାଯାଇଛି"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"ମୋବାଇଲ୍ ନେଟ୍ୱର୍କ ମିଳୁନାହିଁ"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"ନିଜ ପସନ୍ଦର ନେଟ୍ୱର୍କକୁ ଯିବାପାଇଁ ଚେଷ୍ଟା କରନ୍ତୁ। ବଦଳାଇବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"ଜରୁରୀକାଳୀନ କଲ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"ଚିହ୍ନଟ ହେଲା ନାହିଁ"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପ୍ରମାଣୀକୃତ ହେଲା"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଷ୍ଟୋର୍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଆଙ୍ଗୁଠି ଚିହ୍ନକୁ ବାହାର କରିଦିଅନ୍ତୁ।"</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ଆଙ୍ଗୁଠି ଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
@@ -1275,49 +1273,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ଅନ୍ୟ ଆପ୍ ଉପରେ ଦେଖାଯାଉଛି"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"ଏହି ବୈଶିଷ୍ଟ୍ୟ <xliff:g id="NAME">%s</xliff:g> ବ୍ୟବହାର ନକରିବାକୁ ଯଦି ଆପଣ ଚାହାଁନ୍ତି, ସେଟିଙ୍ଗ ଖୋଲିବାକୁ ଟାପ୍ କରନ୍ତୁ ଏବଂ ଏହା ଅଫ୍ କରିଦିଅନ୍ତୁ।"</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"ବନ୍ଦ କରନ୍ତୁ"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g>ର ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"ସାମ୍ପ୍ରତିକ କଣ୍ଟେଣ୍ଟର ଯାଞ୍ଚ କରାଯାଉଛି"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"ନୂଆ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"ସେଟଅପ୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ଫଟୋ ଓ ମିଡିଆ ସ୍ଥାନାନ୍ତର କରାଯିବା ପାଇଁ"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> ସହ ସମସ୍ୟା"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"ଠିକ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> ଖରାପ ହୋଇଯାଇଛି। ଠିକ୍ କରିବାକୁ ଚୟନ କରନ୍ତୁ।"</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> ସପୋର୍ଟ କରୁନାହିଁ"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"ଏହି ଡିଭାଇସ୍ ଏହି <xliff:g id="NAME">%s</xliff:g>କୁ ସପୋର୍ଟ କରେନାହିଁ। ଗୋଟିଏ ସପୋର୍ଟ କରୁଥିବା ଫର୍ମାଟ୍ରେ ସେଟ୍ ଅପ୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"ଏହି ଡିଭାଇସ୍ ଏହି <xliff:g id="NAME">%s</xliff:g>କୁ ସପୋର୍ଟ କରେ ନାହିଁ। ଗୋଟିଏ ସପୋର୍ଟ କରୁଥିବା ଫର୍ମାଟରେ ସେଟ୍ ଅପ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g>କୁ ହଠାତ୍ କାଢ଼ିଦିଆଗଲା"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"କଣ୍ଟେଣ୍ତ ହରାଇବାକୁ ଏଡ଼ାଇବା ପାଇଁ କାଢ଼ିବା ପୂର୍ବରୁ ମିଡିଆକୁ ଇଜେକ୍ଟ କରନ୍ତୁ"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g>କୁ କାଢ଼ିଦିଆଗଲା"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"କିଛି କାର୍ଯ୍ୟକ୍ଷମତା ଠିକ୍ ଭାବେ କାମ ନକରିପାରେ। ନୂଆ ଷ୍ଟୋରେଜ୍ ଭର୍ତ୍ତି କରନ୍ତୁ।"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g>କୁ ଇଜେକ୍ଟ କରାଯାଉଛି"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"କାଢ଼ନ୍ତୁ ନାହିଁ"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"ବାହାର କରନ୍ତୁ"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"ଖୋଜନ୍ତୁ"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> ନାହିଁ"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"ଡିଭାଇସ୍କୁ ପୁଣି ଭର୍ତ୍ତି କରନ୍ତୁ"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> ନିଆଯାଉଛି"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"ଡାଟା ନିଆଯାଉଛି"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"କଣ୍ଟେଣ୍ଟ ସ୍ଥାନାନ୍ତର ହୋଇଗଲା"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"କଣ୍ଟେଣ୍ଟକୁ <xliff:g id="NAME">%s</xliff:g>କୁ ନିଆଗଲା"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"କଣ୍ଟେଣ୍ଟକୁ ନେଇହେବ ନାହିଁ"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"କଣ୍ଟେଣ୍ଟକୁ ପୁଣିଥରେ ନେବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"ବାହାର କରିଦିଆଗଲା"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"ବାହାର କରାଗଲା"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
@@ -1865,14 +1848,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM କାର୍ଡକୁ ଭଏସ୍ ପାଇଁ ପ୍ରସ୍ତୁତ କରାଯାଇନାହିଁ"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"SIM କାର୍ଡକୁ ଭଏସ୍ ପାଇଁ ଅନୁମତି ଦିଆଯାଇନାହିଁ"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"ଫୋନକୁ ଭଏସ୍ ପାଇଁ ଅନୁମତି ଦିଆଯାଇନାହିଁ"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g>ର ଅନୁମତି ନାହିଁ"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g>ର ପ୍ରାବଧାନ ନାହିଁ"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g>ର ଅନୁମତି ନାହିଁ"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g>ର ଅନୁମତି ନାହିଁ"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ପପ-ଅପ୍ ୱିଣ୍ଡୋ"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"ଆପ୍ ଭର୍ସନ୍ ପୁରୁଣା ହୋଇଯାଇଛି କିମ୍ବା ଏହି ଶର୍ଟକଟ୍ ସହିତ କାମ କରୁନାହିଁ।"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 6e429a5..568b237 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"ਕੋਈ ਆਵਾਜ਼ੀ ਸੇਵਾ ਨਹੀਂ"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"ਕੋਈ ਅਵਾਜ਼ੀ ਸੇਵਾ ਜਾਂ ਸੰਕਟਕਾਲੀਨ ਕਾਲਿੰਗ ਨਹੀਂ"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਬੰਦ ਹੈ"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"ਸਿਮ <xliff:g id="SIMNUMBER">%d</xliff:g> ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਬੰਦ ਹੈ"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"ਤਰਜੀਹੀ ਨੈੱਟਵਰਕ ਨੂੰ ਬਦਲ ਕੇ ਦੇਖੋ। ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"ਸੰਕਟਕਾਲੀਨ ਕਾਲਿੰਗ ਉਪਲਬਧ ਨਹੀਂ"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਮੌਜੂਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਟਾਓ।"</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
@@ -1275,49 +1273,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ਐਪ ਹੋਰਾਂ ਐਪਾਂ ਦੇ ਉੱਤੇ ਹੈ।"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"ਜੇਕਰ ਤੁਸੀਂ ਨਹੀਂ ਚਾਹੁੰਦੇ ਕਿ <xliff:g id="NAME">%s</xliff:g> ਐਪ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਕਰੇ, ਤਾਂ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"ਬੰਦ ਕਰੋ"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> ਦੀ ਜਾਂਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"ਵਰਤਮਾਨ ਸਮੱਗਰੀ ਦੀ ਸਮੀਖਿਆ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"ਨਵਾਂ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ ਨੂੰ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰਨ ਲਈ"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"ਠੀਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> ਖਰਾਬ ਹੈ। ਠੀਕ ਕਰਨ ਲਈ ਚੁਣੋ।"</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"ਅਸਮਰਥਿਤ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਕਿਸੇ ਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ ਸਥਾਪਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਕਿਸੇ ਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ ਸਥਾਪਤ ਕਰਨ ਲਈ ਚੁਣੋ।"</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਅਚਨਚੇਤ ਹਟਾਇਆ ਗਿਆ"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"ਸਮੱਗਰੀ ਗੁਆਉਣ ਤੋਂ ਬਚਣ ਲਈ ਹਟਾਉਣ ਤੋਂ ਪਹਿਲਾਂ ਮੀਡੀਆ ਕੱਢੋ"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਹਟਾਇਆ ਗਿਆ"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"ਸ਼ਾਇਦ ਕੁਝ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ। ਨਵੀਂ ਸਟੋਰੇਜ ਸ਼ਾਮਲ ਕਰੋ।"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਬਾਹਰ ਕੱਢਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"ਨਾ ਹਟਾਓ"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"ਸਥਾਪਤ ਕਰੋ"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"ਬਾਹਰ ਕੱਢੋ"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"ਐਕਸਪਲੋਰ ਕਰੋ"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> ਲਾਪਤਾ"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"ਦੁਬਾਰਾ ਡੀਵਾਈਸ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> ਮੂਵ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">" ਡਾਟਾ ਮੂਵ ਕਰ ਰਿਹਾ ਹੈ"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"ਸਮੱਗਰੀ ਟ੍ਰਾਂਸਫ਼ਰ ਪੂਰਾ ਹੋਇਆ"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"ਸਮੱਗਰੀ <xliff:g id="NAME">%s</xliff:g> ਵਿੱਚ ਲਿਜਾਈ ਗਈ"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"ਸਮੱਗਰੀ ਲਿਜਾਈ ਨਹੀਂ ਜਾ ਸਕੀ"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"ਦੁਬਾਰਾ ਸਮੱਗਰੀ ਲਿਜਾ ਕੇ ਦੇਖੋ"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"ਹਟਾਏ ਗਏ"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"ਹਟਾਇਆ ਗਿਆ"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ..."</string>
@@ -1865,14 +1848,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"ਸਿਮ ਰਾਹੀਂ ਅਵਾਜ਼ੀ ਕਾਲ ਕਰਨ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"ਸਿਮ ਰਾਹੀਂ ਅਵਾਜ਼ੀ ਕਾਲ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"ਫ਼ੋਨ ਰਾਹੀਂ ਅਵਾਜ਼ੀ ਕਾਲ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"ਸਿਮ <xliff:g id="SIMNUMBER">%d</xliff:g> ਨੂੰ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"ਸਿਮ <xliff:g id="SIMNUMBER">%d</xliff:g> ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"ਸਿਮ <xliff:g id="SIMNUMBER">%d</xliff:g> ਨੂੰ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"ਸਿਮ <xliff:g id="SIMNUMBER">%d</xliff:g> ਨੂੰ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ਪੌਪਅੱਪ ਵਿੰਡੋ"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"ਐਪ ਦਾ ਵਰਜਨ ਡਾਊਨਗ੍ਰੇਡ ਕੀਤਾ ਗਿਆ, ਜਾਂ ਇਸ ਸ਼ਾਰਟਕੱਟ ਦੇ ਅਨੁਕੂਲ ਨਹੀਂ ਹੈ"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index b6e2e57..784d316 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1286,7 +1286,7 @@
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> foi removido inesperadamente"</string>
<string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Ejete o armazenamento multimédia antes de o remover para evitar a perda de conteúdos."</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> removido"</string>
- <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Algumas funcionalidades podem não funcionar corretamente. Insira um novo armazenamento."</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Algumas funcionalidades podem não funcionar corretamente. Insira um novo dispositivo de armazenamento."</string>
<string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"A ejetar <xliff:g id="NAME">%s</xliff:g>…"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Não remova."</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Configurar"</string>
@@ -1848,7 +1848,7 @@
<string name="mmcc_illegal_ms" msgid="807334478177362062">"SIM não permitido para voz"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"Telemóvel não permitido para voz"</string>
<string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não autorizado"</string>
- <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não aprovisionado"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não fornecido"</string>
<string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não autorizado"</string>
<string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não autorizado"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Janela pop-up"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 34e1c82..3aa5d25 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1306,10 +1306,10 @@
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Dispozitivul nu este compatibil cu acest <xliff:g id="NAME">%s</xliff:g>. Atingeți pentru configurare într-un format compatibil."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Dispozitivul nu este compatibil cu acest <xliff:g id="NAME">%s</xliff:g>. Selectați pentru configurare într-un format compatibil."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> scos pe neașteptate"</string>
- <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Îndepărtați dispozitivele media înainte de a le elimina pentru a evita pierderea conținutului"</string>
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Deconectați din setări dispozitivele media înainte de a le îndepărta, pentru a evita pierderea conținutului"</string>
<string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"S-a eliminat <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Este posibil ca unele funcții să nu funcționeze corespunzător. Introduceți un spațiu de stocare nou."</string>
- <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Se scoate <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"Funcționarea ar putea fi necorespunzătoare. Introduceți un dispozitiv de stocare nou."</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"Se deconectează <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"Nu scoateți"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"Configurați"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"Scoateți"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index d710876..db9cd0a 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -122,12 +122,13 @@
<string name="roamingText11" msgid="4154476854426920970">"ரோமிங் பேனர் இயக்கத்தில் உள்ளது"</string>
<string name="roamingText12" msgid="1189071119992726320">"ரோமிங் பேனர் முடக்கப்பட்டது"</string>
<string name="roamingTextSearching" msgid="8360141885972279963">"சேவையைத் தேடுகிறது"</string>
- <!-- no translation found for wfcRegErrorTitle (3855061241207182194) -->
- <skip />
+ <string name="wfcRegErrorTitle" msgid="3855061241207182194">"வைஃபை அழைப்பை அமைக்க முடியவில்லை"</string>
<string-array name="wfcOperatorErrorAlertMessages">
<item msgid="3910386316304772394">"வைஃபை மூலம் அழைக்கவும் செய்திகளை அனுப்பவும், முதலில் தொலைத்தொடர்பு நிறுவனத்திடம் இந்தச் சேவையை அமைக்குமாறு கேட்கவும். பிறகு அமைப்புகளில் மீண்டும் வைஃபை அழைப்பை இயக்கவும். (பிழைக் குறியீடு <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
- <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (7372514042696663278) -->
+ <string-array name="wfcOperatorErrorNotificationMessages">
+ <item msgid="7372514042696663278">"உங்கள் மொபைல் நிறுவனத்துடன் வைஃபை அழைப்பைப் பதிவுசெய்வதில் சிக்கல்: <xliff:g id="CODE">%1$s</xliff:g>"</item>
+ </string-array>
<string-array name="wfcSpnFormats">
<item msgid="6830082633573257149">"%s"</item>
<item msgid="4397097370387921767">"%s வைஃபை அழைப்பு"</item>
@@ -1157,8 +1158,7 @@
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"திறந்த வைஃபை நெட்வொர்க்குடன் இணைக்கவும்"</string>
<string name="wifi_available_carrier_network_title" msgid="4527932626916527897">"தொலைத்தொடர்பு சேவை வழங்கும் நிறுவனத்தின் வைஃபை நெட்வொர்க்குடன் இணைக்கிறது"</string>
- <!-- no translation found for wifi_available_title_connecting (1139126673968899002) -->
- <skip />
+ <string name="wifi_available_title_connecting" msgid="1139126673968899002">"வைஃபை நெட்வொர்க்குடன் இணைக்கிறது"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"வைஃபை நெட்வொர்க்குடன் இணைக்கப்பட்டது"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"வைஃபை நெட்வொர்க்குடன் இணைக்க முடியவில்லை"</string>
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"எல்லா நெட்வொர்க்குகளையும் பார்க்க, தட்டவும்"</string>
@@ -1286,8 +1286,8 @@
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"படங்களையும் மீடியாவையும் மாற்றலாம்"</string>
<!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
<skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"Tap to fix"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> சிதைந்துள்ளது. சரிசெய்ய, தேர்ந்தெடுக்கவும்."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"ஆதரிக்கப்படாத <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"சாதனம் இந்த <xliff:g id="NAME">%s</xliff:g>ஐ ஆதரிக்கவில்லை. ஆதரிக்கப்படும் வடிவமைப்பில் அமைக்க, தட்டவும்."</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"சாதனம் இந்த <xliff:g id="NAME">%s</xliff:g>ஐ ஆதரிக்கவில்லை. ஆதரிக்கப்படும் வடிவமைப்பில் அமைக்க, தேர்ந்தெடுக்கவும்."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 5f351842..5a22dc5 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -82,8 +82,7 @@
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"کوئی صوتی سروس نہیں"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"کوئی صوتی سروس یا ہنگامی کالنگ دستیاب نہیں ہے"</string>
<string name="RestrictedStateContent" msgid="6538703255570997248">"آپ کے کیریئر نے عارضی طور پر آف کر دیا ہے"</string>
- <!-- no translation found for RestrictedStateContentMsimTemplate (673416791370248176) -->
- <skip />
+ <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> کے لئے آپ کے کیریئر نے عارضی طور پر آف کر دیا ہے"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"موبائل نیٹ ورک تک رسائی نہیں ہو سکتی"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"ترجیحی نیٹ ورک تبدیل کر کے دیکھیں۔ تبدیل کرنے کے لیے تھپتھپائیں۔"</string>
<string name="EmergencyCallWarningTitle" msgid="813380189532491336">"ہنگامی کالنگ دستیاب نہیں ہے"</string>
@@ -498,8 +497,7 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"تسلیم شدہ نہیں ہے"</string>
- <!-- no translation found for fingerprint_authenticated (5309333983002526448) -->
- <skip />
+ <string name="fingerprint_authenticated" msgid="5309333983002526448">"فنگر پرنٹ کی تصدیق ہو گئی"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"فنگر پرنٹ ہارڈ ویئر دستیاب نہیں ہے۔"</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"فنگر پرنٹ اسٹور نہیں کیا جا سکتا ہے۔ براہ کرم ایک موجودہ فنگر پرنٹ ہٹائیں۔"</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
@@ -1275,49 +1273,34 @@
<string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> دیگر ایپس پر ڈسپلے ہو رہی ہے"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"اگر آپ نہیں چاہتے ہیں کہ <xliff:g id="NAME">%s</xliff:g> اس خصوصیت کا استعمال کرے تو ترتیبات کھولنے کیلئے تھپتھپائیں اور اسے بند کریں۔"</string>
<string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"آف کریں"</string>
- <!-- no translation found for ext_media_checking_notification_title (4411133692439308924) -->
- <skip />
- <!-- no translation found for ext_media_checking_notification_message (410185170877285434) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_title (1621805083736634077) -->
- <skip />
- <!-- no translation found for ext_media_new_notification_message (3673685270558405087) -->
- <skip />
+ <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> کو چیک کیا جا رہا ہے…"</string>
+ <string name="ext_media_checking_notification_message" msgid="410185170877285434">"موجودہ مواد کا جائزہ لیا جا رہا ہے"</string>
+ <string name="ext_media_new_notification_title" msgid="1621805083736634077">"نیا <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="ext_media_new_notification_message" msgid="3673685270558405087">"سیٹ اپ کرنے کیلئے تھپتھپائیں"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"تصاویر اور میڈیا منتقل کرنے کیلئے"</string>
- <!-- no translation found for ext_media_unmountable_notification_title (4179418065210797130) -->
- <skip />
- <!-- no translation found for ext_media_unmountable_notification_message (4193858924381066522) -->
- <skip />
+ <string name="ext_media_unmountable_notification_title" msgid="4179418065210797130">"<xliff:g id="NAME">%s</xliff:g> کے ساتھ مسئلہ"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"درست کرنے کیلئے تھپتھپائیں"</string>
+ <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> خراب ہے۔ اسے ٹھیک کرنے کیلئے منتخب کریں۔"</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"غیر تعاون یافتہ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"یہ آلہ <xliff:g id="NAME">%s</xliff:g> کو سپورٹ نہیں کرتا۔ ایک سپورٹ یافتہ فارمیٹ میں سیٹ اپ کرنے کیلئے تھپتھپائیں۔"</string>
<string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"یہ آلہ اس <xliff:g id="NAME">%s</xliff:g> کو سپورٹ نہیں کرتا ہے۔ ایک سپورٹ یافتہ فارمیٹ میں سیٹ اپ کرنے کیلئے منتخب کریں۔"</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> غیر متوقع طور پر ہٹا دیا گیا"</string>
- <!-- no translation found for ext_media_badremoval_notification_message (8556885808951260574) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_title (6593814191061956856) -->
- <skip />
- <!-- no translation found for ext_media_nomedia_notification_message (2110883356419799994) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_title (5046532339291216076) -->
- <skip />
- <!-- no translation found for ext_media_unmounting_notification_message (1003926904442321115) -->
- <skip />
+ <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"مواد کھونے سے بچنے کے لئے ہٹانے سے پہلے میڈیا خارج کریں"</string>
+ <string name="ext_media_nomedia_notification_title" msgid="6593814191061956856">"<xliff:g id="NAME">%s</xliff:g> کو ہٹا دیا گیا"</string>
+ <string name="ext_media_nomedia_notification_message" msgid="2110883356419799994">"شاید کچھ فنکشن ٹھیک طرح سے کام نہ کریں۔ نیا اسٹوریج داخل کریں۔"</string>
+ <string name="ext_media_unmounting_notification_title" msgid="5046532339291216076">"<xliff:g id="NAME">%s</xliff:g> کو خارج کیا جا رہا ہے"</string>
+ <string name="ext_media_unmounting_notification_message" msgid="1003926904442321115">"نہ ہٹائیں"</string>
<string name="ext_media_init_action" msgid="7952885510091978278">"سیٹ اپ کریں"</string>
<string name="ext_media_unmount_action" msgid="1121883233103278199">"خارج کریں"</string>
<string name="ext_media_browse_action" msgid="8322172381028546087">"دریافت کریں"</string>
<string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> غائب ہے"</string>
- <!-- no translation found for ext_media_missing_message (4012389235250987930) -->
- <skip />
+ <string name="ext_media_missing_message" msgid="4012389235250987930">"آلہ دوبارہ داخل کریں"</string>
<string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> کو منتقل کیا جا رہا ہے"</string>
<string name="ext_media_move_title" msgid="1022809140035962662">"ڈیٹا منتقل کیا جا رہا ہے…"</string>
- <!-- no translation found for ext_media_move_success_title (7863652232242276066) -->
- <skip />
- <!-- no translation found for ext_media_move_success_message (8939137931961728009) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_title (1604422634177382092) -->
- <skip />
- <!-- no translation found for ext_media_move_failure_message (7388950499623016135) -->
- <skip />
+ <string name="ext_media_move_success_title" msgid="7863652232242276066">"مواد کی منتقلی مکمل ہو گئی"</string>
+ <string name="ext_media_move_success_message" msgid="8939137931961728009">"مواد کو <xliff:g id="NAME">%s</xliff:g> میں منتقل کر دیا گیا"</string>
+ <string name="ext_media_move_failure_title" msgid="1604422634177382092">"مواد منتقل نہیں کیا جا سکا"</string>
+ <string name="ext_media_move_failure_message" msgid="7388950499623016135">"دوبارہ مواد کو منتقل کرنے کی کوشش کریں"</string>
<string name="ext_media_status_removed" msgid="6576172423185918739">"ہٹا دیا گیا"</string>
<string name="ext_media_status_unmounted" msgid="2551560878416417752">"اخراج شدہ"</string>
<string name="ext_media_status_checking" msgid="6193921557423194949">"چیک کیا جا رہا ہے…"</string>
@@ -1865,14 +1848,10 @@
<string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM میں آواز کیلئے سہولت نہیں ہے"</string>
<string name="mmcc_illegal_ms" msgid="807334478177362062">"آواز کیلئے SIM کو اجازت نہیں ہے"</string>
<string name="mmcc_illegal_me" msgid="1950705155760872972">"آواز کیلئے فون کو اجازت نہیں ہے"</string>
- <!-- no translation found for mmcc_authentication_reject_msim_template (1217031195834766479) -->
- <skip />
- <!-- no translation found for mmcc_imsi_unknown_in_hlr_msim_template (5636464607596778986) -->
- <skip />
- <!-- no translation found for mmcc_illegal_ms_msim_template (5994323296399913454) -->
- <skip />
- <!-- no translation found for mmcc_illegal_me_msim_template (5550259730350571826) -->
- <skip />
+ <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> کو اجازت نہیں ہے"</string>
+ <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> فراہم کردہ نہیں ہے"</string>
+ <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> کو اجازت نہیں ہے"</string>
+ <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> کو اجازت نہیں ہے"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"پاپ اپ ونڈو"</string>
<string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"ایپ کے ورژن کا درجہ کم ہے یا اس شارٹ کٹ کے ساتھ مطابقت پذیر نہیں ہے"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index aceba08..fe34d98 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2154,9 +2154,6 @@
Corresponds to <code>LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES</code>.
-->
<enum name="shortEdges" value="1" />
- <!-- Use <code>shortEdges</code> instead. This is temporarily here to unblock pushing
- the SDK until all usages have been migrated to <code>shortEdges</code> -->
- <enum name="always" value="1" />
<!-- <p>
The window is never allowed to overlap with the <code>DisplayCutout</code> area.
<p>
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 7048511..0fe80a1 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -38,4 +38,8 @@
<color name="background_device_default_light">@color/background_material_light</color>
<color name="background_floating_device_default_dark">@color/background_floating_material_dark</color>
<color name="background_floating_device_default_light">@color/background_floating_material_light</color>
+
+ <!-- Error color -->
+ <color name="error_color_device_default_dark">@color/error_color_material_dark</color>
+ <color name="error_color_device_default_light">@color/error_color_material_light</color>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 12e5dfe..fc030ca 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -27,6 +27,7 @@
<!-- Do not translate. Defines the slots for the right-hand side icons. That is to say, the
icons in the status bar that are not notifications. -->
<string-array name="config_statusBarIcons">
+ <item><xliff:g id="id">@string/status_bar_alarm_clock</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_rotate</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_headset</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_data_saver</xliff:g></item>
@@ -44,7 +45,6 @@
<item><xliff:g id="id">@string/status_bar_phone_evdo_signal</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_phone_signal</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_secure</xliff:g></item>
- <item><xliff:g id="id">@string/status_bar_alarm_clock</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_bluetooth</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_managed_profile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_cast</xliff:g></item>
@@ -974,6 +974,9 @@
-->
<integer name="config_longPressOnBackBehavior">0</integer>
+ <!-- Allows activities to be launched on a long press on power during device setup. -->
+ <bool name="config_allowStartActivityForLongPressOnPowerInSetup">false</bool>
+
<!-- Control the behavior when the user short presses the power button.
0 - Nothing
1 - Go to sleep (doze)
@@ -1286,6 +1289,32 @@
in darkness (although they may not be visible in a bright room). -->
<integer name="config_screenBrightnessDark">1</integer>
+ <!-- Array of lux values to define the minimum brightness curve, which guarantees that any
+ brightness curve that dips below it is rejected by the system.
+ This prevents auto-brightness from setting the screen so dark as to prevent the user from
+ resetting or disabling it.
+
+ The values must be non-negative and strictly increasing, and correspond to the values in
+ the config_minimumBrightnessCurveNits array. -->
+ <array name="config_minimumBrightnessCurveLux">
+ <item>0.0</item>
+ <item>2000.0</item>
+ <item>4000.0</item>
+ </array>
+
+ <!-- Array of nits values to define the minimum brightness curve, which guarantees that any
+ brightness curve that dips below it is rejected by the system.
+ This should map lux to the absolute minimum nits that are still readable in that ambient
+ brightness.
+
+ The values must be non-negative and non-decreasing, and correspond to the values in the
+ config_minimumBrightnessCurveLux array. -->
+ <array name="config_minimumBrightnessCurveNits">
+ <item>0.0</item>
+ <item>50.0</item>
+ <item>90.0</item>
+ </array>
+
<!-- Array of light sensor lux values to define our levels for auto backlight brightness support.
The N entries of this array define N + 1 control points as follows:
(1-based arrays)
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 715be5b..bd824de 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4515,7 +4515,7 @@
<string name="package_deleted_device_owner">Deleted by your admin</string>
<!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
- <string name="battery_saver_description">To extend battery life, Battery Saver reduces your device\'s performance and limits or turns off vibration, location services, and background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery Saver turns off automatically when your device is charging.</string>
+ <string name="battery_saver_description">To extend your battery life, Battery Saver turns off some device features and restricts apps.</string>
<!-- [CHAR_LIMIT=NONE] Data saver: Feature description -->
<string name="data_saver_description">To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them.</string>
@@ -4943,9 +4943,9 @@
<!-- Title for the notification channel notifying user of do not disturb system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] -->
<string name="notification_channel_do_not_disturb">Do Not Disturb</string>
<!-- Title of notification indicating do not disturb visual interruption settings have changed when upgrading to P -->
- <string name="zen_upgrade_notification_visd_title">Do Not Disturb is hiding notifications to help you focus</string>
+ <string name="zen_upgrade_notification_visd_title">New: Do Not Disturb is hiding notifications</string>
<!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
- <string name="zen_upgrade_notification_visd_content">This is new behavior. Tap to change.</string>
+ <string name="zen_upgrade_notification_visd_content">Tap to learn more and change.</string>
<!-- Title of notification indicating do not disturb settings have changed when upgrading to P -->
<string name="zen_upgrade_notification_title">Do Not Disturb has changed</string>
<!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 1a51c1d..d722961 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -128,6 +128,9 @@
<style name="Widget.DeviceDefault.TextSelectHandle" parent="Widget.Material.TextSelectHandle"/>
<style name="Widget.DeviceDefault.TextView.ListSeparator" parent="Widget.Material.TextView.ListSeparator"/>
<style name="Widget.DeviceDefault.TimePicker" parent="Widget.Material.TimePicker"/>
+ <style name="Widget.DeviceDefault.Toolbar" parent="Widget.Material.Toolbar">
+ <item name="titleTextAppearance">@style/TextAppearance.DeviceDefault.Widget.Toolbar.Title</item>
+ </style>
<style name="Widget.DeviceDefault.Light" parent="Widget.Material.Light"/>
<style name="Widget.DeviceDefault.Light.Button" parent="Widget.Material.Light.Button"/>
@@ -186,7 +189,9 @@
<style name="Widget.DeviceDefault.Light.ActionBar.TabView" parent="Widget.Material.Light.ActionBar.TabView"/>
<style name="Widget.DeviceDefault.Light.ActionBar.TabText" parent="Widget.Material.Light.ActionBar.TabText"/>
<style name="Widget.DeviceDefault.Light.ActionBar.TabBar" parent="Widget.Material.Light.ActionBar.TabBar"/>
- <style name="Widget.DeviceDefault.Light.ActionBar.Solid" parent="Widget.Material.Light.ActionBar.Solid"/>
+ <style name="Widget.DeviceDefault.Light.ActionBar.Solid" parent="Widget.Material.Light.ActionBar.Solid">
+ <item name="titleTextStyle">@style/TextAppearance.DeviceDefault.Widget.ActionBar.Title</item>
+ </style>
<!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
<style name="Widget.DeviceDefault.Light.ActionBar.Solid.Inverse" parent="Widget.Holo.Light.ActionBar.Solid.Inverse"/>
<!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
@@ -242,12 +247,18 @@
<style name="TextAppearance.DeviceDefault.Widget.PopupMenu" parent="TextAppearance.Material.Widget.PopupMenu"/>
<style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Large" parent="TextAppearance.Material.Widget.PopupMenu.Large"/>
<style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Small" parent="TextAppearance.Material.Widget.PopupMenu.Small"/>
- <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title" parent="TextAppearance.Material.Widget.ActionBar.Title"/>
+ <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title" parent="TextAppearance.Material.Widget.ActionBar.Title">
+ <item name="fontFamily">@string/config_headlineFontFamilyMedium</item>
+ </style>
<style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle" parent="TextAppearance.Material.Widget.ActionBar.Subtitle"/>
<style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title" parent="TextAppearance.Material.Widget.ActionMode.Title"/>
<style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle" parent="TextAppearance.Material.Widget.ActionMode.Subtitle"/>
- <style name="TextAppearance.DeviceDefault.WindowTitle" parent="TextAppearance.Material.WindowTitle"/>
- <style name="TextAppearance.DeviceDefault.DialogWindowTitle" parent="TextAppearance.Material.DialogWindowTitle"/>
+ <style name="TextAppearance.DeviceDefault.WindowTitle" parent="TextAppearance.Material.WindowTitle">
+ <item name="fontFamily">@string/config_headlineFontFamilyMedium</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.DialogWindowTitle" parent="TextAppearance.Material.DialogWindowTitle">
+ <item name="fontFamily">@string/config_headlineFontFamilyMedium</item>
+ </style>
<!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
<style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Material.Widget.ActionBar.Title.Inverse"/>
<!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
@@ -257,6 +268,7 @@
<!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
<style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse"/>
<style name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" parent="TextAppearance.Material.Widget.ActionBar.Menu"/>
+ <style name="TextAppearance.DeviceDefault.Widget.Toolbar.Title" parent="TextAppearance.DeviceDefault.Widget.ActionBar.Title" />
<!-- Preference Styles -->
<style name="Preference.DeviceDefault" parent="Preference.Material"/>
@@ -280,11 +292,15 @@
<style name="Animation.DeviceDefault.Dialog" parent="Animation.Material.Dialog"/>
<!-- DialogWindowTitle Styles -->
- <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Material"/>
- <style name="DialogWindowTitle.DeviceDefault.Light" parent="DialogWindowTitle.Material.Light"/>
+ <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Material">
+ <item name="textAppearance">@style/TextAppearance.DeviceDefault.DialogWindowTitle</item>
+ </style>
+ <style name="DialogWindowTitle.DeviceDefault.Light"/>
<!-- WindowTitle Styles -->
- <style name="WindowTitle.DeviceDefault" parent="WindowTitle.Material"/>
+ <style name="WindowTitle.DeviceDefault" parent="WindowTitle.Material">
+ <item name="textAppearance">@style/TextAppearance.DeviceDefault.WindowTitle</item>
+ </style>
<style name="WindowTitleBackground.DeviceDefault" parent="WindowTitleBackground.Material"/>
<!-- Other Styles -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5856648..b6f0b70 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -434,6 +434,7 @@
<java-symbol type="integer" name="config_veryLongPressOnPowerBehavior" />
<java-symbol type="integer" name="config_veryLongPressTimeout" />
<java-symbol type="integer" name="config_longPressOnBackBehavior" />
+ <java-symbol type="bool" name="config_allowStartActivityForLongPressOnPowerInSetup" />
<java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAdjust" />
<java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAbsolute" />
<java-symbol type="integer" name="config_max_pan_devices" />
@@ -1809,6 +1810,8 @@
<java-symbol type="array" name="config_dynamicHysteresisBrightLevels" />
<java-symbol type="array" name="config_dynamicHysteresisDarkLevels" />
<java-symbol type="array" name="config_dynamicHysteresisLuxLevels" />
+ <java-symbol type="array" name="config_minimumBrightnessCurveLux" />
+ <java-symbol type="array" name="config_minimumBrightnessCurveNits" />
<java-symbol type="array" name="config_protectedNetworks" />
<java-symbol type="array" name="config_statusBarIcons" />
<java-symbol type="array" name="config_tether_bluetooth_regexs" />
@@ -2546,6 +2549,7 @@
<java-symbol type="drawable" name="ic_settings_24dp" />
<java-symbol type="drawable" name="ic_storage_48dp" />
<java-symbol type="drawable" name="ic_usb_48dp" />
+ <java-symbol type="drawable" name="ic_zen_24dp" />
<!-- Floating toolbar -->
<java-symbol type="id" name="floating_toolbar_menu_item_image" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 2327b33..92b2f33 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -181,6 +181,9 @@
<item name="actionBarStyle">@style/Widget.DeviceDefault.ActionBar.Solid</item>
<item name="actionModePopupWindowStyle">@style/Widget.DeviceDefault.PopupWindow.ActionMode</item>
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
<item name="buttonBarStyle">@style/DeviceDefault.ButtonBar</item>
<item name="segmentedButtonStyle">@style/DeviceDefault.SegmentedButton</item>
@@ -207,6 +210,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
</style>
@@ -218,6 +222,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -233,6 +238,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar. This theme
@@ -242,6 +250,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -257,6 +266,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar and
@@ -268,6 +280,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -283,6 +296,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault} that has no title bar and translucent
@@ -293,6 +309,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -308,6 +325,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault theme for dialog windows and activities. This changes the window to be
@@ -333,6 +353,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -341,6 +362,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
@@ -350,6 +374,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -365,6 +390,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
@@ -373,6 +401,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -388,6 +417,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
@@ -397,6 +429,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -412,6 +445,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
@@ -437,6 +473,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -452,6 +489,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault theme for a window without an action bar that will be displayed either
@@ -462,6 +502,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -477,6 +518,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault theme for a presentation window on a secondary display. -->
@@ -485,6 +529,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -500,6 +545,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault theme for panel windows. This removes all extraneous window
@@ -510,6 +558,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -525,6 +574,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
@@ -534,6 +586,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -549,6 +602,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
@@ -558,6 +614,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -573,6 +630,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault style for input methods, which is used by the
@@ -582,6 +642,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -597,6 +658,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault style for input methods, which is used by the
@@ -606,6 +670,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -621,6 +686,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Material.Dialog.Alert">
@@ -634,6 +702,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Text styles -->
<item name="textAppearanceButton">@style/TextAppearance.DeviceDefault.Widget.Button</item>
@@ -645,6 +714,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
@@ -652,6 +724,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -667,6 +740,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
@@ -674,6 +750,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -689,6 +766,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with a light-colored style -->
@@ -822,6 +902,9 @@
<item name="actionBarStyle">@style/Widget.DeviceDefault.Light.ActionBar.Solid</item>
<item name="actionModePopupWindowStyle">@style/Widget.DeviceDefault.Light.PopupWindow.ActionMode</item>
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
<item name="buttonBarStyle">@style/DeviceDefault.Light.ButtonBar</item>
<item name="segmentedButtonStyle">@style/DeviceDefault.Light.SegmentedButton</item>
@@ -845,6 +928,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
</style>
<!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
@@ -854,6 +938,7 @@
<item name="colorPrimary">@color/primary_device_default_dark</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -869,6 +954,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar -->
@@ -877,6 +965,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -892,6 +981,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar.
@@ -901,6 +993,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -916,6 +1009,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar
@@ -927,6 +1023,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -942,6 +1039,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} that has no title bar and translucent
@@ -952,6 +1052,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -967,6 +1068,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault light theme for dialog windows and activities. This changes the window to be
@@ -994,19 +1098,27 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} that has a nice minimum width for a
regular dialog. -->
<style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Material.Light.Dialog.MinWidth">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1022,14 +1134,21 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} without an action bar -->
<style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Material.Light.Dialog.NoActionBar">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1045,15 +1164,22 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog_NoActionBar} that has a nice minimum
width for a regular dialog. -->
<style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Light.Dialog.NoActionBar.MinWidth">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1069,6 +1195,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
@@ -1082,6 +1211,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
</style>
<!-- Variant of Theme.DeviceDefault.Dialog.NoActionBar that has a fixed size. -->
@@ -1095,15 +1225,20 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
</style>
<!-- DeviceDefault light theme for a window that will be displayed either full-screen on smaller
screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
<style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1119,16 +1254,23 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault light theme for a window without an action bar that will be displayed either
full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
xlarge). -->
<style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1144,14 +1286,21 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault light theme for a presentation window on a secondary display. -->
<style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1167,6 +1316,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault light theme for panel windows. This removes all extraneous window
@@ -1177,6 +1329,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1192,6 +1345,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.Alert">
@@ -1201,6 +1357,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1216,6 +1373,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Material.Light.SearchBar">
@@ -1223,6 +1383,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1238,6 +1399,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Light.Voice" parent="Theme.Material.Light.Voice">
@@ -1245,6 +1409,7 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1260,11 +1425,15 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault theme for a window that should look like the Settings app. -->
<style name="Theme.DeviceDefault.Settings" parent="Theme.Material.Settings">
<!-- action bar -->
+ <item name="actionBarStyle">@style/Widget.DeviceDefault.Light.ActionBar.Solid</item>
<item name="actionBarTheme">@style/ThemeOverlay.DeviceDefault.ActionBar.Accent</item>
<item name="popupTheme">@style/ThemeOverlay.DeviceDefault.Popup.Light</item>
@@ -1274,6 +1443,7 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
<item name="colorSecondary">@color/secondary_device_default_settings_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<item name="colorEdgeEffect">@android:color/black</item>
<!-- Add white nav bar with divider that matches material -->
@@ -1295,6 +1465,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- @hide DeviceDefault theme for a window that should use Settings theme colors
@@ -1305,6 +1478,7 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
<item name="colorSecondary">@color/secondary_device_default_settings_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<item name="colorControlNormal">?attr/textColorPrimary</item>
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
@@ -1319,6 +1493,9 @@
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
<!-- volume background -->
<item name="panelColorBackground">@color/primary_material_light</item>
</style>
@@ -1329,11 +1506,15 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
<item name="colorSecondary">@color/secondary_device_default_settings_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Settings_Dark} with no action bar -->
@@ -1343,6 +1524,7 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1358,14 +1540,21 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Settings.Dialog" parent="Theme.Material.Settings.Dialog">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1381,14 +1570,21 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Settings.DialogWhenLarge" parent="Theme.Material.Settings.DialogWhenLarge">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1404,14 +1600,21 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.Alert">
+ <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Dialog attributes -->
<item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
@@ -1427,6 +1630,9 @@
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<style name="Theme.DeviceDefault.Settings.Dialog.NoActionBar" parent="Theme.DeviceDefault.Light.Dialog.NoActionBar" />
@@ -1457,10 +1663,14 @@
<item name="colorPrimary">@color/primary_device_default_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
+ <item name="colorError">@color/error_color_device_default_light</item>
<!-- Progress bar attributes -->
<item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+ <!-- Toolbar attributes -->
+ <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
<!-- DeviceDefault theme for the default system theme. -->
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 7b5ad9a..68ef34b 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -25,5 +25,6 @@
<option name="test-tag" value="FrameworksCoreTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.coretests" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index bad0d25..5ef30a8 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -41,7 +41,7 @@
};
private static final float[] NITS_LEVELS = {
- 0.5f,
+ 1f,
90f,
100f,
};
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index b1936b9..a5941b2 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -60,7 +60,6 @@
Settings.System.ALARM_ALERT, // backup candidate?
Settings.System.ALARM_ALERT_CACHE, // internal cache
Settings.System.APPEND_FOR_LAST_AUDIBLE, // suffix deprecated since API 2
- Settings.System.DISPLAY_COLOR_MODE, // bug?
Settings.System.EGG_MODE, // I am the lolrus
Settings.System.END_BUTTON_BEHAVIOR, // bug?
Settings.System
@@ -72,6 +71,7 @@
Settings.System.NOTIFICATION_SOUND_CACHE, // internal cache
Settings.System.POINTER_LOCATION, // backup candidate?
Settings.System.RINGTONE_CACHE, // internal cache
+ Settings.System.SCREEN_BRIGHTNESS, // removed in P
Settings.System.SETUP_WIZARD_HAS_RUN, // Only used by SuW
Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup?
Settings.System.SHOW_TOUCHES, // bug?
@@ -246,6 +246,9 @@
Settings.Global.HDMI_CONTROL_ENABLED,
Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
+ Settings.Global.HIDDEN_API_POLICY_P_APPS,
+ Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS,
+ Settings.Global.HIDE_ERROR_DIALOGS,
Settings.Global.HTTP_PROXY,
HYBRID_SYSUI_BATTERY_WARNING_FLAGS,
Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY,
@@ -301,6 +304,12 @@
Settings.Global.NETSTATS_UID_TAG_DELETE_AGE,
Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES,
Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE,
+ Settings.Global.NETPOLICY_QUOTA_ENABLED,
+ Settings.Global.NETPOLICY_QUOTA_UNLIMITED,
+ Settings.Global.NETPOLICY_QUOTA_LIMITED,
+ Settings.Global.NETPOLICY_QUOTA_FRAC_JOBS,
+ Settings.Global.NETPOLICY_QUOTA_FRAC_MULTIPATH,
+ Settings.Global.NETPOLICY_OVERRIDE_ENABLED,
Settings.Global.NETWORK_AVOID_BAD_WIFI,
Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES,
Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE,
@@ -411,6 +420,7 @@
Settings.Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
Settings.Global.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD,
Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
+ Settings.Global.UNGAZE_SLEEP_ENABLED,
Settings.Global.UNLOCK_SOUND,
Settings.Global.USE_GOOGLE_MAIL,
Settings.Global.VT_IMS_ENABLED,
diff --git a/core/tests/coretests/src/android/text/SpannableTest.java b/core/tests/coretests/src/android/text/SpannableTest.java
index 307ac62..f368428 100644
--- a/core/tests/coretests/src/android/text/SpannableTest.java
+++ b/core/tests/coretests/src/android/text/SpannableTest.java
@@ -16,6 +16,8 @@
package android.text;
+import static org.junit.Assert.assertEquals;
+
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -24,6 +26,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -53,4 +57,34 @@
spans = spannable.getSpans(2, 2, Object.class);
MoreAsserts.assertEquals(new Object[]{unemptySpan}, spans);
}
+
+ @Test
+ public void testRemoveSpanWithIntermediateFlag() {
+ Spannable spannable = newSpannableWithText("abcdef");
+ Object emptySpan = new Object();
+ spannable.setSpan(emptySpan, 1, 1, 0);
+ Object unemptySpan = new Object();
+ spannable.setSpan(unemptySpan, 1, 2, 0);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ SpanWatcher watcher = new SpanWatcher() {
+ @Override
+ public void onSpanAdded(Spannable text, Object what, int start, int end) {}
+
+ @Override
+ public void onSpanRemoved(Spannable text, Object what, int start, int end) {
+ latch.countDown();
+ }
+
+ @Override
+ public void onSpanChanged(Spannable text, Object what, int ostart, int oend, int nstart,
+ int nend) {}
+ };
+ spannable.setSpan(watcher, 0, 2, 0);
+
+ spannable.removeSpan(emptySpan, Spanned.SPAN_INTERMEDIATE);
+ assertEquals(1, latch.getCount());
+ spannable.removeSpan(unemptySpan);
+ assertEquals(0, latch.getCount());
+ }
}
diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java
index 04d2dad..c02d97c 100644
--- a/core/tests/coretests/src/android/text/format/FormatterTest.java
+++ b/core/tests/coretests/src/android/text/format/FormatterTest.java
@@ -16,12 +16,14 @@
package android.text.format;
+import static android.text.format.Formatter.FLAG_IEC_UNITS;
+import static android.text.format.Formatter.FLAG_SI_UNITS;
+
import static org.junit.Assert.assertEquals;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.icu.util.MeasureUnit;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -34,7 +36,6 @@
import org.junit.runner.RunWith;
import java.util.Locale;
-import java.util.Set;
@Presubmit
@SmallTest
@@ -104,6 +105,27 @@
checkFormatBytes(9123000, false, "9,12", 9120000);
}
+ @Test
+ public void testFormatBytesSi() {
+ setLocale(Locale.US);
+
+ checkFormatBytes(1_000, FLAG_SI_UNITS, "1.00", 1_000);
+ checkFormatBytes(1_024, FLAG_SI_UNITS, "1.02", 1_020);
+ checkFormatBytes(1_500, FLAG_SI_UNITS, "1.50", 1_500);
+ checkFormatBytes(12_582_912L, FLAG_SI_UNITS, "12.58", 12_580_000L);
+ }
+
+ @Test
+ public void testFormatBytesIec() {
+ setLocale(Locale.US);
+
+ checkFormatBytes(1_000, FLAG_IEC_UNITS, "0.98", 1_003);
+ checkFormatBytes(1_024, FLAG_IEC_UNITS, "1.00", 1_024);
+ checkFormatBytes(1_500, FLAG_IEC_UNITS, "1.46", 1_495);
+ checkFormatBytes(12_500_000L, FLAG_IEC_UNITS, "11.92", 12_499_025L);
+ checkFormatBytes(12_582_912L, FLAG_IEC_UNITS, "12.00", 12_582_912L);
+ }
+
private static final long SECOND = 1000;
private static final long MINUTE = 60 * SECOND;
private static final long HOUR = 60 * MINUTE;
@@ -195,8 +217,14 @@
private void checkFormatBytes(long bytes, boolean useShort,
String expectedString, long expectedRounded) {
+ checkFormatBytes(bytes, (useShort ? Formatter.FLAG_SHORTER : 0),
+ expectedString, expectedRounded);
+ }
+
+ private void checkFormatBytes(long bytes, int flags,
+ String expectedString, long expectedRounded) {
BytesResult r = Formatter.formatBytes(mContext.getResources(), bytes,
- Formatter.FLAG_CALCULATE_ROUNDED | (useShort ? Formatter.FLAG_SHORTER : 0));
+ Formatter.FLAG_CALCULATE_ROUNDED | flags);
assertEquals(expectedString, r.value);
assertEquals(expectedRounded, r.roundedBytes);
}
diff --git a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
index 42b6048..39d492d 100644
--- a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
+++ b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
@@ -57,13 +57,13 @@
assertTrue(r.isMonthly());
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = r.cycleIterator();
assertTrue(it.hasNext());
- assertEquals(Pair.create(
+ assertEquals(new Range<>(
ZonedDateTime.parse("2015-11-14T00:00:00.00Z"),
ZonedDateTime.parse("2015-12-14T00:00:00.00Z")), it.next());
assertTrue(it.hasNext());
- assertEquals(Pair.create(
+ assertEquals(new Range<>(
ZonedDateTime.parse("2015-10-14T00:00:00.00Z"),
ZonedDateTime.parse("2015-11-14T00:00:00.00Z")), it.next());
}
@@ -77,13 +77,13 @@
assertFalse(r.isMonthly());
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = r.cycleIterator();
assertTrue(it.hasNext());
- assertEquals(Pair.create(
+ assertEquals(new Range<>(
ZonedDateTime.parse("2010-11-17T00:11:00.00Z"),
ZonedDateTime.parse("2010-11-20T00:11:00.00Z")), it.next());
assertTrue(it.hasNext());
- assertEquals(Pair.create(
+ assertEquals(new Range<>(
ZonedDateTime.parse("2010-11-14T00:11:00.00Z"),
ZonedDateTime.parse("2010-11-17T00:11:00.00Z")), it.next());
assertFalse(it.hasNext());
@@ -98,9 +98,9 @@
assertFalse(r.isMonthly());
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = r.cycleIterator();
assertTrue(it.hasNext());
- assertEquals(Pair.create(
+ assertEquals(new Range<>(
ZonedDateTime.parse("2010-11-14T00:11:00.000Z"),
ZonedDateTime.parse("2010-11-20T00:11:00.000Z")), it.next());
assertFalse(it.hasNext());
@@ -112,7 +112,7 @@
assertFalse(r.isMonthly());
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = r.cycleIterator();
assertFalse(it.hasNext());
}
@@ -122,22 +122,22 @@
ZonedDateTime.parse("2030-01-31T00:00:00.000Z"),
Period.ofMonths(1));
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = r.cycleIterator();
ZonedDateTime lastStart = null;
int months = 0;
while (it.hasNext()) {
- final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next();
+ final Range<ZonedDateTime> cycle = it.next();
// Make sure cycle has reasonable length
- final long length = cycle.second.toEpochSecond() - cycle.first.toEpochSecond();
+ final long length = cycle.getUpper().toEpochSecond() - cycle.getLower().toEpochSecond();
assertTrue(cycle + " must be more than 4 weeks", length >= 2419200);
assertTrue(cycle + " must be less than 5 weeks", length <= 3024000);
// Make sure we have no gaps
if (lastStart != null) {
- assertEquals(lastStart, cycle.second);
+ assertEquals(lastStart, cycle.getUpper());
}
- lastStart = cycle.first;
+ lastStart = cycle.getLower();
months++;
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java b/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
index 861a43a..a3c6179 100644
--- a/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
@@ -19,7 +19,6 @@
import static org.junit.Assert.assertEquals;
import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -31,20 +30,34 @@
public class SelectionEventTest {
@Test
+ public void testCreateSelectionActionEvent_valid() {
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_OVERTYPE);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_COPY);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_PASTE);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_CUT);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_SHARE);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_SMART_SHARE);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_DRAG);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_ABANDON);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_OTHER);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_SELECT_ALL);
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.ACTION_RESET);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateSelectionActionEvent_badRange() {
+ SelectionEvent.createSelectionActionEvent(0, -1, SelectionEvent.ACTION_OVERTYPE);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateSelectionActionEvent_badAction() {
+ SelectionEvent.createSelectionActionEvent(0, 1, SelectionEvent.EVENT_SELECTION_STARTED);
+ }
+
+ @Test
public void testParcel() {
- final SelectionEvent[] captured = new SelectionEvent[1];
- final Logger logger = new Logger(
- new Logger.Config(
- InstrumentationRegistry.getTargetContext(),
- TextClassifier.WIDGET_TYPE_TEXTVIEW,
- null)) {
- @Override
- public void writeEvent(SelectionEvent event) {
- captured[0] = event;
- }
- };
- logger.logSelectionStartedEvent(SelectionEvent.INVOCATION_MANUAL, 0);
- final SelectionEvent event = captured[0];
+ final SelectionEvent event = SelectionEvent.createSelectionStartedEvent(
+ SelectionEvent.INVOCATION_MANUAL, 0);
final Parcel parcel = Parcel.obtain();
event.writeToParcel(parcel, event.describeContents());
parcel.setDataPosition(0);
diff --git a/core/tests/privacytests/AndroidTest.xml b/core/tests/privacytests/AndroidTest.xml
index 8098c14..a3e785c 100644
--- a/core/tests/privacytests/AndroidTest.xml
+++ b/core/tests/privacytests/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.coretests.privacy" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/core/tests/utiltests/AndroidTest.xml b/core/tests/utiltests/AndroidTest.xml
index 270d773..f32acb4 100644
--- a/core/tests/utiltests/AndroidTest.xml
+++ b/core/tests/utiltests/AndroidTest.xml
@@ -25,5 +25,6 @@
<option name="test-tag" value="FrameworksUtilTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.utiltests" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 20c22b7..18dd97f 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -738,6 +738,23 @@
/**
* Creates a typeface object that best matches the specified existing typeface and the specified
* weight and italic style
+ * <p>Below are numerical values and corresponding common weight names.</p>
+ * <table>
+ * <thead>
+ * <tr><th>Value</th><th>Common weight name</th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><td>100</td><td>Thin</td></tr>
+ * <tr><td>200</td><td>Extra Light</td></tr>
+ * <tr><td>300</td><td>Light</td></tr>
+ * <tr><td>400</td><td>Normal</td></tr>
+ * <tr><td>500</td><td>Medium</td></tr>
+ * <tr><td>600</td><td>Semi Bold</td></tr>
+ * <tr><td>700</td><td>Bold</td></tr>
+ * <tr><td>800</td><td>Extra Bold</td></tr>
+ * <tr><td>900</td><td>Black</td></tr>
+ * </tbody>
+ * </table>
*
* <p>
* This method is thread safe.
@@ -749,6 +766,9 @@
* @param italic {@code true} if italic style is desired to be drawn. Otherwise, {@code false}
* @return A {@link Typeface} object for drawing specified weight and italic style. Never
* returns {@code null}
+ *
+ * @see #getWeight()
+ * @see #isItalic()
*/
public static @NonNull Typeface create(@Nullable Typeface family,
@IntRange(from = 1, to = 1000) int weight, boolean italic) {
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 985a756..7d4e6f8 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -456,6 +456,22 @@
uninit();
+ // The chunk must be at least the size of the string pool header.
+ if (size < sizeof(ResStringPool_header)) {
+ LOG_ALWAYS_FATAL("Bad string block: data size %zu is too small to be a string block", size);
+ return (mError=BAD_TYPE);
+ }
+
+ // The data is at least as big as a ResChunk_header, so we can safely validate the other
+ // header fields.
+ // `data + size` is safe because the source of `size` comes from the kernel/filesystem.
+ if (validate_chunk(reinterpret_cast<const ResChunk_header*>(data), sizeof(ResStringPool_header),
+ reinterpret_cast<const uint8_t*>(data) + size,
+ "ResStringPool_header") != NO_ERROR) {
+ LOG_ALWAYS_FATAL("Bad string block: malformed block dimensions");
+ return (mError=BAD_TYPE);
+ }
+
const bool notDeviceEndian = htods(0xf0) != 0xf0;
if (copyData || notDeviceEndian) {
@@ -467,6 +483,8 @@
data = mOwnedData;
}
+ // The size has been checked, so it is safe to read the data in the ResStringPool_header
+ // data structure.
mHeader = (const ResStringPool_header*)data;
if (notDeviceEndian) {
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
index f9cf549..1696661 100644
--- a/libs/hwui/ProfileData.cpp
+++ b/libs/hwui/ProfileData.cpp
@@ -104,7 +104,8 @@
dprintf(fd, "\nStats since: %" PRIu64 "ns", mStatStartTime);
dprintf(fd, "\nTotal frames rendered: %u", mTotalFrameCount);
dprintf(fd, "\nJanky frames: %u (%.2f%%)", mJankFrameCount,
- (float)mJankFrameCount / (float)mTotalFrameCount * 100.0f);
+ mTotalFrameCount == 0 ? 0.0f :
+ (float)mJankFrameCount / (float)mTotalFrameCount * 100.0f);
dprintf(fd, "\n50th percentile: %ums", findPercentile(50));
dprintf(fd, "\n90th percentile: %ums", findPercentile(90));
dprintf(fd, "\n95th percentile: %ums", findPercentile(95));
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 1602b4b..0a6c45b 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -65,6 +65,8 @@
bool Properties::debuggingEnabled = false;
bool Properties::isolatedProcess = false;
+int Properties::contextPriority = 0;
+
static int property_get_int(const char* key, int defaultValue) {
char buf[PROPERTY_VALUE_MAX] = {
'\0',
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 81a3657..764c502 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -271,6 +271,8 @@
ANDROID_API static bool debuggingEnabled;
ANDROID_API static bool isolatedProcess;
+ ANDROID_API static int contextPriority;
+
private:
static ProfileType sProfileType;
static bool sDisableProfileBars;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 5b87e10..6e239e3 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -82,6 +82,7 @@
bool pixelFormatFloat = false;
bool glColorSpace = false;
bool scRGB = false;
+ bool contextPriority = false;
} EglExtensions;
EglManager::EglManager(RenderThread& thread)
@@ -168,6 +169,7 @@
#else
EglExtensions.scRGB = extensions.has("EGL_EXT_gl_colorspace_scrgb");
#endif
+ EglExtensions.contextPriority = extensions.has("EGL_IMG_context_priority");
}
bool EglManager::hasEglContext() {
@@ -247,10 +249,18 @@
}
void EglManager::createContext() {
- EGLint attribs[] = {EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE};
+ std::vector<EGLint> contextAttributes;
+ contextAttributes.reserve(5);
+ contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
+ contextAttributes.push_back(GLES_VERSION);
+ if (Properties::contextPriority != 0 && EglExtensions.contextPriority) {
+ contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
+ contextAttributes.push_back(Properties::contextPriority);
+ }
+ contextAttributes.push_back(EGL_NONE);
mEglContext = eglCreateContext(
mEglDisplay, EglExtensions.noConfigContext ? ((EGLConfig) nullptr) : mEglConfig,
- EGL_NO_CONTEXT, attribs);
+ EGL_NO_CONTEXT, contextAttributes.data());
LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, "Failed to create context, error = %s",
eglErrorString());
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 38286a3..6eb3d8d 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -29,6 +29,7 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -392,6 +393,18 @@
}
/**
+ * @hide
+ */
+ @TestApi
+ public String[] getBackgroundThrottlingWhitelist() {
+ try {
+ return mService.getBackgroundThrottlingWhitelist();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide - hide this constructor because it has a parameter
* of type ILocationManager, which is a system private class. The
* right way to create an instance of this class is using the
diff --git a/location/tests/locationtests/AndroidTest.xml b/location/tests/locationtests/AndroidTest.xml
index 0c5b7cc..bb6547b 100644
--- a/location/tests/locationtests/AndroidTest.xml
+++ b/location/tests/locationtests/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.locationtests" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 0458931..9152ff2 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -250,9 +250,10 @@
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_GAME, SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT, SUPPRESSIBLE_MEDIA);
+ /** default volume assignment is STREAM_MUSIC, handle unknown usage as media */
+ SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN, SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING, SUPPRESSIBLE_SYSTEM);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_SONIFICATION, SUPPRESSIBLE_SYSTEM);
- SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN, SUPPRESSIBLE_SYSTEM);
}
/**
@@ -1057,8 +1058,7 @@
case USAGE_ASSISTANCE_ACCESSIBILITY:
return AudioSystem.STREAM_ACCESSIBILITY;
case USAGE_UNKNOWN:
- return fromGetVolumeControlStream ?
- AudioManager.USE_DEFAULT_STREAM_TYPE : AudioSystem.STREAM_MUSIC;
+ return AudioSystem.STREAM_MUSIC;
default:
if (fromGetVolumeControlStream) {
throw new IllegalArgumentException("Unknown usage value " + aa.getUsage() +
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index 7104dad..fe89b89 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.os.Bundle;
import android.os.Handler;
@@ -262,6 +263,7 @@
* Returns the focus change listener set for this {@code AudioFocusRequest}.
* @return null if no {@link AudioManager.OnAudioFocusChangeListener} was set.
*/
+ @TestApi
public @Nullable OnAudioFocusChangeListener getOnAudioFocusChangeListener() {
return mFocusListener;
}
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index f98480b..d0a2c98 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -437,6 +438,7 @@
* @param mask a combination of the CHANNEL_IN_* definitions, even CHANNEL_IN_DEFAULT
* @return number of channels for the mask
*/
+ @TestApi
public static int channelCountFromInChannelMask(int mask) {
return Integer.bitCount(mask);
}
@@ -446,6 +448,7 @@
* @param mask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT
* @return number of channels for the mask
*/
+ @TestApi
public static int channelCountFromOutChannelMask(int mask) {
return Integer.bitCount(mask);
}
@@ -492,6 +495,7 @@
// CHANNEL_IN_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_IN_ALL
/** @hide */
+ @TestApi
public static int getBytesPerSample(int audioFormat)
{
switch (audioFormat) {
@@ -562,6 +566,7 @@
}
/** @hide */
+ @TestApi
public static boolean isEncodingLinearPcm(int audioFormat)
{
switch (audioFormat) {
diff --git a/media/java/android/media/AudioPresentation.java b/media/java/android/media/AudioPresentation.java
index e39cb7d..ce71436 100644
--- a/media/java/android/media/AudioPresentation.java
+++ b/media/java/android/media/AudioPresentation.java
@@ -18,8 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-
-import com.android.internal.annotations.VisibleForTesting;
+import android.annotation.TestApi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -94,7 +93,7 @@
/**
* @hide
*/
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ @TestApi
public AudioPresentation(int presentationId,
int programId,
@NonNull Map<String, String> labels,
@@ -119,7 +118,7 @@
* decoder. Presentation id is typically sequential, but does not have to be.
* @hide
*/
- @VisibleForTesting
+ @TestApi
public int getPresentationId() {
return mPresentationId;
}
@@ -129,7 +128,7 @@
* Program id can be used to further uniquely identify the presentation to a decoder.
* @hide
*/
- @VisibleForTesting
+ @TestApi
public int getProgramId() {
return mProgramId;
}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index bc0e43b..7888436 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -66,7 +66,7 @@
/**
* This is a class for reading and writing Exif tags in a JPEG file or a RAW image file.
* <p>
- * Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW and RAF.
+ * 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.
*/
@@ -2524,46 +2524,46 @@
private void getHeifAttributes(ByteOrderedDataInputStream in) throws IOException {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
- if (mSeekableFileDescriptor != null) {
- retriever.setDataSource(mSeekableFileDescriptor);
- } else {
- retriever.setDataSource(new MediaDataSource() {
- long mPosition;
+ retriever.setDataSource(new MediaDataSource() {
+ long mPosition;
- @Override
- public void close() throws IOException {}
+ @Override
+ public void close() throws IOException {}
- @Override
- public int readAt(long position, byte[] buffer, int offset, int size)
- throws IOException {
- if (size == 0) {
- return 0;
- }
- if (position < 0) {
- return -1;
- }
- if (mPosition != position) {
- in.seek(position);
- mPosition = position;
- }
-
- int bytesRead = in.read(buffer, offset, size);
- if (bytesRead < 0) {
- mPosition = -1; // need to seek on next read
- return -1;
- }
-
- mPosition += bytesRead;
- return bytesRead;
+ @Override
+ public int readAt(long position, byte[] buffer, int offset, int size)
+ throws IOException {
+ if (size == 0) {
+ return 0;
}
-
- @Override
- public long getSize() throws IOException {
+ if (position < 0) {
return -1;
}
- });
- }
+ if (mPosition != position) {
+ in.seek(position);
+ mPosition = position;
+ }
+ int bytesRead = in.read(buffer, offset, size);
+ if (bytesRead < 0) {
+ mPosition = -1; // need to seek on next read
+ return -1;
+ }
+
+ mPosition += bytesRead;
+ return bytesRead;
+ }
+
+ @Override
+ public long getSize() throws IOException {
+ return -1;
+ }
+ });
+
+ String exifOffsetStr = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_EXIF_OFFSET);
+ String exifLengthStr = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_EXIF_LENGTH);
String hasImage = retriever.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE);
String hasVideo = retriever.extractMetadata(
@@ -2622,6 +2622,30 @@
ExifAttribute.createUShort(orientation, mExifByteOrder));
}
+ if (exifOffsetStr != null && exifLengthStr != null) {
+ int offset = Integer.parseInt(exifOffsetStr);
+ int length = Integer.parseInt(exifLengthStr);
+ if (length <= 6) {
+ throw new IOException("Invalid exif length");
+ }
+ in.seek(offset);
+ byte[] identifier = new byte[6];
+ if (in.read(identifier) != 6) {
+ throw new IOException("Can't read identifier");
+ }
+ offset += 6;
+ length -= 6;
+ if (!Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) {
+ throw new IOException("Invalid identifier");
+ }
+
+ byte[] bytes = new byte[length];
+ if (in.read(bytes) != length) {
+ throw new IOException("Can't read exif");
+ }
+ readExifSegment(bytes, IFD_TYPE_PRIMARY);
+ }
+
if (DEBUG) {
Log.d(TAG, "Heif meta: " + width + "x" + height + ", rotation " + rotation);
}
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 37c5785..9828275 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -193,6 +193,13 @@
public abstract int getTransform();
/**
+ * Get the scaling mode associated with this frame.
+ * @return The scaling mode that needs to be applied for this frame.
+ * @hide
+ */
+ public abstract int getScalingMode();
+
+ /**
* Get the {@link android.hardware.HardwareBuffer HardwareBuffer} handle of the input image
* intended for GPU and/or hardware access.
* <p>
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 72d52d3..8ec0e35 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -871,6 +871,12 @@
}
@Override
+ public int getScalingMode() {
+ throwISEIfImageIsInvalid();
+ return mScalingMode;
+ }
+
+ @Override
public HardwareBuffer getHardwareBuffer() {
throwISEIfImageIsInvalid();
return nativeGetHardwareBuffer();
@@ -1004,14 +1010,11 @@
private long mNativeBuffer;
/**
- * This field is set by native code during nativeImageSetup().
+ * These fields are set by native code during nativeImageSetup().
*/
private long mTimestamp;
-
- /**
- * This field is set by native code during nativeImageSetup().
- */
private int mTransform;
+ private int mScalingMode;
private SurfacePlane[] mPlanes;
private int mFormat = ImageFormat.UNKNOWN;
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index 8ee27ae..397768a 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -371,7 +371,7 @@
Rect crop = image.getCropRect();
nativeQueueInputImage(mNativeContext, image, image.getTimestamp(), crop.left, crop.top,
- crop.right, crop.bottom, image.getTransform());
+ crop.right, crop.bottom, image.getTransform(), image.getScalingMode());
/**
* Only remove and cleanup the Images that are owned by this
@@ -558,7 +558,7 @@
Rect crop = image.getCropRect();
nativeAttachAndQueueImage(mNativeContext, image.getNativeContext(), image.getFormat(),
image.getTimestamp(), crop.left, crop.top, crop.right, crop.bottom,
- image.getTransform());
+ image.getTransform(), image.getScalingMode());
}
/**
@@ -676,6 +676,7 @@
private long mTimestamp = DEFAULT_TIMESTAMP;
private int mTransform = 0; //Default no transform
+ private int mScalingMode = 0; //Default frozen scaling mode
public WriterSurfaceImage(ImageWriter writer) {
mOwner = writer;
@@ -721,6 +722,13 @@
}
@Override
+ public int getScalingMode() {
+ throwISEIfImageIsInvalid();
+
+ return mScalingMode;
+ }
+
+ @Override
public long getTimestamp() {
throwISEIfImageIsInvalid();
@@ -866,11 +874,12 @@
private synchronized native void nativeDequeueInputImage(long nativeCtx, Image wi);
private synchronized native void nativeQueueInputImage(long nativeCtx, Image image,
- long timestampNs, int left, int top, int right, int bottom, int transform);
+ long timestampNs, int left, int top, int right, int bottom, int transform,
+ int scalingMode);
private synchronized native int nativeAttachAndQueueImage(long nativeCtx,
long imageNativeBuffer, int imageFormat, long timestampNs, int left,
- int top, int right, int bottom, int transform);
+ int top, int right, int bottom, int transform, int scalingMode);
private synchronized native void cancelImage(long nativeCtx, Image image);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index e3fba0c..1f00c78 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -3574,6 +3574,7 @@
private final static int TYPE_YUV = 1;
private final int mTransform = 0; //Default no transform
+ private final int mScalingMode = 0; //Default frozen scaling mode
@Override
public int getFormat() {
@@ -3600,6 +3601,12 @@
}
@Override
+ public int getScalingMode() {
+ throwISEIfImageIsInvalid();
+ return mScalingMode;
+ }
+
+ @Override
public long getTimestamp() {
throwISEIfImageIsInvalid();
return mTimestamp;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 0955dd6..8ab5ec4 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -890,5 +890,14 @@
*/
public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32;
+ /**
+ * @hide
+ */
+ public static final int METADATA_KEY_EXIF_OFFSET = 33;
+
+ /**
+ * @hide
+ */
+ public static final int METADATA_KEY_EXIF_LENGTH = 34;
// Add more here...
}
diff --git a/media/java/android/media/PlaybackParams.java b/media/java/android/media/PlaybackParams.java
index 938a953..b85e4d0 100644
--- a/media/java/android/media/PlaybackParams.java
+++ b/media/java/android/media/PlaybackParams.java
@@ -17,6 +17,7 @@
package android.media;
import android.annotation.IntDef;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -151,6 +152,7 @@
* @param audioStretchMode
* @return this <code>PlaybackParams</code> instance.
*/
+ @TestApi
public PlaybackParams setAudioStretchMode(@AudioStretchMode int audioStretchMode) {
mAudioStretchMode = audioStretchMode;
mSet |= SET_AUDIO_STRETCH_MODE;
@@ -163,6 +165,7 @@
* @return audio stretch mode
* @throws IllegalStateException if the audio stretch mode is not set.
*/
+ @TestApi
public @AudioStretchMode int getAudioStretchMode() {
if ((mSet & SET_AUDIO_STRETCH_MODE) == 0) {
throw new IllegalStateException("audio stretch mode not set");
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 3068706..b654214 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -843,6 +844,7 @@
* @return the same {@code Builder} instance.
* @throws IllegalArgumentException if flag is not recognized.
*/
+ @TestApi
public @NonNull Builder setOptionFlags(@OptionFlag int optionFlags) {
if ((optionFlags & ~OPTION_FLAG_PUBLIC_ALL) != 0) {
throw new IllegalArgumentException("invalid bits in flag: " + optionFlags);
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 1cb4d67..24c595f 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -494,6 +494,7 @@
* @return true if the device implements the specified effect type, false otherwise.
* @hide
*/
+ @TestApi
public static boolean isEffectTypeAvailable(UUID type) {
AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
if (desc == null) {
@@ -546,6 +547,7 @@
* @throws IllegalStateException
* @hide
*/
+ @TestApi
public int setParameter(byte[] param, byte[] value)
throws IllegalStateException {
checkState("setParameter()");
@@ -558,6 +560,7 @@
* @see #setParameter(byte[], byte[])
* @hide
*/
+ @TestApi
public int setParameter(int param, int value) throws IllegalStateException {
byte[] p = intToByteArray(param);
byte[] v = intToByteArray(value);
@@ -571,6 +574,7 @@
* @see #setParameter(byte[], byte[])
* @hide
*/
+ @TestApi
public int setParameter(int param, short value)
throws IllegalStateException {
byte[] p = intToByteArray(param);
@@ -585,6 +589,7 @@
* @see #setParameter(byte[], byte[])
* @hide
*/
+ @TestApi
public int setParameter(int param, byte[] value)
throws IllegalStateException {
byte[] p = intToByteArray(param);
@@ -598,6 +603,7 @@
* @see #setParameter(byte[], byte[])
* @hide
*/
+ @TestApi
public int setParameter(int[] param, int[] value)
throws IllegalStateException {
if (param.length > 2 || value.length > 2) {
@@ -649,6 +655,7 @@
* @see #setParameter(byte[], byte[])
* @hide
*/
+ @TestApi
public int setParameter(int[] param, byte[] value)
throws IllegalStateException {
if (param.length > 2) {
@@ -677,6 +684,7 @@
* @throws IllegalStateException
* @hide
*/
+ @TestApi
public int getParameter(byte[] param, byte[] value)
throws IllegalStateException {
checkState("getParameter()");
@@ -690,6 +698,7 @@
* @see #getParameter(byte[], byte[])
* @hide
*/
+ @TestApi
public int getParameter(int param, byte[] value)
throws IllegalStateException {
byte[] p = intToByteArray(param);
@@ -705,6 +714,7 @@
* In case of success, returns the number of meaningful integers in value array.
* @hide
*/
+ @TestApi
public int getParameter(int param, int[] value)
throws IllegalStateException {
if (value.length > 2) {
@@ -736,6 +746,7 @@
* In case of success, returns the number of meaningful short integers in value array.
* @hide
*/
+ @TestApi
public int getParameter(int param, short[] value)
throws IllegalStateException {
if (value.length > 2) {
@@ -801,6 +812,7 @@
* In case of success, returns the number of meaningful short integers in value array.
* @hide
*/
+ @TestApi
public int getParameter(int[] param, short[] value)
throws IllegalStateException {
if (param.length > 2 || value.length > 2) {
@@ -940,6 +952,7 @@
* @param listener
* @hide
*/
+ @TestApi
public void setParameterListener(OnParameterChangeListener listener) {
synchronized (mListenerLock) {
mParameterChangeListener = listener;
@@ -1001,6 +1014,7 @@
* when a parameter is changed in the effect engine by the controlling application.
* @hide
*/
+ @TestApi
public interface OnParameterChangeListener {
/**
* Called on the listener to notify it that a parameter value has changed.
@@ -1293,6 +1307,7 @@
/**
* @hide
*/
+ @TestApi
public static boolean isError(int status) {
return (status < 0);
}
@@ -1300,6 +1315,7 @@
/**
* @hide
*/
+ @TestApi
public static int byteArrayToInt(byte[] valueBuf) {
return byteArrayToInt(valueBuf, 0);
@@ -1318,6 +1334,7 @@
/**
* @hide
*/
+ @TestApi
public static byte[] intToByteArray(int value) {
ByteBuffer converter = ByteBuffer.allocate(4);
converter.order(ByteOrder.nativeOrder());
@@ -1328,6 +1345,7 @@
/**
* @hide
*/
+ @TestApi
public static short byteArrayToShort(byte[] valueBuf) {
return byteArrayToShort(valueBuf, 0);
}
@@ -1345,6 +1363,7 @@
/**
* @hide
*/
+ @TestApi
public static byte[] shortToByteArray(short value) {
ByteBuffer converter = ByteBuffer.allocate(2);
converter.order(ByteOrder.nativeOrder());
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index bfb3ea2..c36858a 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -46,6 +46,7 @@
#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mNativeBuffer"
#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp"
#define ANDROID_MEDIA_SURFACEIMAGE_TF_JNI_ID "mTransform"
+#define ANDROID_MEDIA_SURFACEIMAGE_SM_JNI_ID "mScalingMode"
#define CONSUMER_BUFFER_USAGE_UNKNOWN 0;
// ----------------------------------------------------------------------------
@@ -68,6 +69,7 @@
jfieldID mNativeBuffer;
jfieldID mTimestamp;
jfieldID mTransform;
+ jfieldID mScalingMode;
jfieldID mPlanes;
} gSurfaceImageClassInfo;
@@ -315,6 +317,12 @@
"can't find android/graphics/ImageReader.%s",
ANDROID_MEDIA_SURFACEIMAGE_TF_JNI_ID);
+ gSurfaceImageClassInfo.mScalingMode = env->GetFieldID(
+ imageClazz, ANDROID_MEDIA_SURFACEIMAGE_SM_JNI_ID, "I");
+ LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mScalingMode == NULL,
+ "can't find android/graphics/ImageReader.%s",
+ ANDROID_MEDIA_SURFACEIMAGE_SM_JNI_ID);
+
gSurfaceImageClassInfo.mPlanes = env->GetFieldID(
imageClazz, "mPlanes", "[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;");
LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mPlanes == NULL,
@@ -606,6 +614,8 @@
static_cast<jlong>(buffer->mTimestamp));
env->SetIntField(image, gSurfaceImageClassInfo.mTransform,
static_cast<jint>(buffer->mTransform));
+ env->SetIntField(image, gSurfaceImageClassInfo.mScalingMode,
+ static_cast<jint>(buffer->mScalingMode));
return ACQUIRE_SUCCESS;
}
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 2b8f9f89..11659e4 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -421,7 +421,8 @@
}
static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, jobject image,
- jlong timestampNs, jint left, jint top, jint right, jint bottom, jint transform) {
+ jlong timestampNs, jint left, jint top, jint right, jint bottom, jint transform,
+ jint scalingMode) {
ALOGV("%s", __FUNCTION__);
JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx);
if (ctx == NULL || thiz == NULL) {
@@ -471,6 +472,12 @@
return;
}
+ res = native_window_set_scaling_mode(anw.get(), scalingMode);
+ if (res != OK) {
+ jniThrowRuntimeException(env, "Set scaling mode failed");
+ return;
+ }
+
// Finally, queue input buffer
res = anw->queueBuffer(anw.get(), buffer, fenceFd);
if (res != OK) {
@@ -493,7 +500,7 @@
static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nativeCtx,
jlong nativeBuffer, jint imageFormat, jlong timestampNs, jint left, jint top,
- jint right, jint bottom, jint transform) {
+ jint right, jint bottom, jint transform, jint scalingMode) {
ALOGV("%s", __FUNCTION__);
JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx);
if (ctx == NULL || thiz == NULL) {
@@ -536,8 +543,8 @@
}
sp < ANativeWindow > anw = surface;
- // Step 2. Set timestamp, crop and transform. Note that we do not need unlock the image because
- // it was not locked.
+ // Step 2. Set timestamp, crop, transform and scaling mode. Note that we do not need unlock the
+ // image because it was not locked.
ALOGV("timestamp to be queued: %" PRId64, timestampNs);
res = native_window_set_buffers_timestamp(anw.get(), timestampNs);
if (res != OK) {
@@ -562,6 +569,12 @@
return res;
}
+ res = native_window_set_scaling_mode(anw.get(), scalingMode);
+ if (res != OK) {
+ jniThrowRuntimeException(env, "Set scaling mode failed");
+ return res;
+ }
+
// Step 3. Queue Image.
res = anw->queueBuffer(anw.get(), buffer->mGraphicBuffer.get(), /*fenceFd*/
-1);
@@ -797,9 +810,9 @@
{"nativeInit", "(Ljava/lang/Object;Landroid/view/Surface;II)J",
(void*)ImageWriter_init },
{"nativeClose", "(J)V", (void*)ImageWriter_close },
- {"nativeAttachAndQueueImage", "(JJIJIIIII)I", (void*)ImageWriter_attachAndQueueImage },
+ {"nativeAttachAndQueueImage", "(JJIJIIIIII)I", (void*)ImageWriter_attachAndQueueImage },
{"nativeDequeueInputImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_dequeueImage },
- {"nativeQueueInputImage", "(JLandroid/media/Image;JIIIII)V", (void*)ImageWriter_queueImage },
+ {"nativeQueueInputImage", "(JLandroid/media/Image;JIIIIII)V", (void*)ImageWriter_queueImage },
{"cancelImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_cancelImage },
};
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index b4ca88c..ed2afdd 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -809,7 +809,11 @@
mAudioTrack = newTrack;
ALOGV("using new track %p for sample %d", newTrack.get(), sample->sampleID());
}
- newTrack->setVolume(leftVolume, rightVolume);
+ if (mMuted) {
+ newTrack->setVolume(0.0f, 0.0f);
+ } else {
+ newTrack->setVolume(leftVolume, rightVolume);
+ }
newTrack->setLoop(0, frameCount, loop);
mPos = 0;
mSample = sample;
diff --git a/packages/CarrierDefaultApp/res/values-eu/strings.xml b/packages/CarrierDefaultApp/res/values-eu/strings.xml
index f98a192..81bd6f8 100644
--- a/packages/CarrierDefaultApp/res/values-eu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-eu/strings.xml
@@ -5,7 +5,7 @@
<string name="android_system_label" msgid="2797790869522345065">"Telefonia mugikorreko operadorea"</string>
<string name="portal_notification_id" msgid="5155057562457079297">"Agortu egin dira datu mugikorrak"</string>
<string name="no_data_notification_id" msgid="668400731803969521">"Desaktibatu da datu-konexioa"</string>
- <string name="portal_notification_detail" msgid="2295729385924660881">"Sakatu hau %s gunera joateko"</string>
+ <string name="portal_notification_detail" msgid="2295729385924660881">"Sakatu hau %s webgunera joateko"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"Jarri harremanetan %s operadorearekin"</string>
<string name="no_mobile_data_connection_title" msgid="7449525772416200578">"Ez dago datu-konexiorik"</string>
<string name="no_mobile_data_connection" msgid="544980465184147010">"Gehitu datuak eta ibiltaritza-plana %s bidez"</string>
diff --git a/packages/InputDevices/res/raw/keyboard_layout_polish.kcm b/packages/InputDevices/res/raw/keyboard_layout_polish.kcm
new file mode 100644
index 0000000..559ec07
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_polish.kcm
@@ -0,0 +1,327 @@
+# 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.
+
+#
+# Polish (qwerty) keyboard layout.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '^'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u0119'
+ ralt+shift, ralt+capslock: '\u0118'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+ ralt: '\u00F3'
+ ralt+shift, ralt+capslock: '\u00D3'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base: '['
+ shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base: ']'
+ shift: '}'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+ ralt: '\u0105'
+ ralt+shift, ralt+capslock: '\u0104'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+ ralt: '\u015b'
+ ralt+shift, ralt+capslock: '\u015a'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+ ralt: '\u0142'
+ ralt+shift, ralt+capslock: '\u0141'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base: '\''
+ shift: '"'
+}
+
+### ROW 4
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+ ralt: '\u017c'
+ ralt+shift, ralt+capslock: '\u017b'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+ ralt: '\u017a'
+ ralt+shift, ralt+capslock: '\u0179'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+ ralt: '\u0107'
+ ralt+shift, ralt+capslock: '\u0106'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+ ralt: '\u0144'
+ ralt+shift, ralt+capslock: '\u0143'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '<'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 61d3234..5fdc4a6 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -125,4 +125,7 @@
<!-- Azerbaijani keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_azerbaijani">Azerbaijani</string>
+
+ <!-- Polish keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_polish">Polish</string>
</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index c6bfc1f..1807aea 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -159,4 +159,8 @@
<keyboard-layout android:name="keyboard_layout_azerbaijani"
android:label="@string/keyboard_layout_azerbaijani"
android:keyboardLayout="@raw/keyboard_layout_azerbaijani" />
+
+ <keyboard-layout android:name="keyboard_layout_polish"
+ android:label="@string/keyboard_layout_polish"
+ android:keyboardLayout="@raw/keyboard_layout_polish" />
</keyboard-layouts>
diff --git a/packages/MtpDocumentsProvider/tests/AndroidTest.xml b/packages/MtpDocumentsProvider/tests/AndroidTest.xml
index 940d364..f84131c 100644
--- a/packages/MtpDocumentsProvider/tests/AndroidTest.xml
+++ b/packages/MtpDocumentsProvider/tests/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.InstrumentationTest" >
<option name="package" value="com.android.mtp.tests" />
<option name="runner" value="com.android.mtp.TestResultInstrumentation" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/PrintSpooler/res/values-bs/strings.xml b/packages/PrintSpooler/res/values-bs/strings.xml
index 2e9bfa3..e7f6d13 100644
--- a/packages/PrintSpooler/res/values-bs/strings.xml
+++ b/packages/PrintSpooler/res/values-bs/strings.xml
@@ -42,7 +42,7 @@
<string name="page_description_template" msgid="6831239682256197161">"Strana <xliff:g id="CURRENT_PAGE">%1$d</xliff:g> od <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="summary_template" msgid="8899734908625669193">"Rezime, primjeraka <xliff:g id="COPIES">%1$s</xliff:g>, veličina papira <xliff:g id="PAPER_SIZE">%2$s</xliff:g>"</string>
<string name="expand_handle" msgid="7282974448109280522">"Regulator za proširivanje"</string>
- <string name="collapse_handle" msgid="6886637989442507451">"Regulator za skupljanje"</string>
+ <string name="collapse_handle" msgid="6886637989442507451">"Regulator za sužavanje"</string>
<string name="print_button" msgid="645164566271246268">"Štampaj"</string>
<string name="savetopdf_button" msgid="2976186791686924743">"Sačuvaj u PDF"</string>
<string name="print_options_expanded" msgid="6944679157471691859">"Opcije za štampanje su proširene"</string>
diff --git a/packages/PrintSpooler/res/values-ne/strings.xml b/packages/PrintSpooler/res/values-ne/strings.xml
index 18f96dd..da49afb 100644
--- a/packages/PrintSpooler/res/values-ne/strings.xml
+++ b/packages/PrintSpooler/res/values-ne/strings.xml
@@ -70,7 +70,7 @@
<string name="print_no_printers" msgid="4869403323900054866">"कुनै प्रिन्टरहरू भेटाइएन"</string>
<string name="cannot_add_printer" msgid="7840348733668023106">"प्रिन्टरहरू थप्न सक्दैन"</string>
<string name="select_to_add_printers" msgid="3800709038689830974">"प्रिन्टर थप्नका लागि चयन गर्नुहोस्"</string>
- <string name="enable_print_service" msgid="3482815747043533842">"सक्षम गर्नका लागि चयन गर्नुहोस्"</string>
+ <string name="enable_print_service" msgid="3482815747043533842">"सक्षम गर्नाका लागि चयन गर्नुहोस्"</string>
<string name="enabled_services_title" msgid="7036986099096582296">"सक्षम गरिएका सेवाहरू"</string>
<string name="recommended_services_title" msgid="3799434882937956924">"सिफारिस गरिएका सेवाहरू"</string>
<string name="disabled_services_title" msgid="7313253167968363211">"असक्षम गरिएका सेवाहरू"</string>
diff --git a/packages/PrintSpooler/tests/outofprocess/AndroidTest.xml b/packages/PrintSpooler/tests/outofprocess/AndroidTest.xml
index 15dd64b..d21a2e4 100644
--- a/packages/PrintSpooler/tests/outofprocess/AndroidTest.xml
+++ b/packages/PrintSpooler/tests/outofprocess/AndroidTest.xml
@@ -25,5 +25,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.printspooler.outofprocess.tests" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/SettingsLib/res/layout/preference_category_material_settings.xml b/packages/SettingsLib/res/layout/preference_category_material_settings.xml
index 245e3b7..1086106 100644
--- a/packages/SettingsLib/res/layout/preference_category_material_settings.xml
+++ b/packages/SettingsLib/res/layout/preference_category_material_settings.xml
@@ -50,6 +50,7 @@
android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:textAppearance="@android:style/TextAppearance.Material.Body2"
android:textAlignment="viewStart"
android:textColor="?android:attr/colorAccent"
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 0c617ba..a181ee2 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-ৰ মাধ্যমেদি সংযোগ কৰা হৈছে"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযোজিত, ইণ্টাৰনেট নাই"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ইণ্টাৰনেট সংযোগ নাই"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ছাইন ইন কৰা দৰকাৰী"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"একচেছ পইণ্ট কিছু সময়ৰ বাবে পূৰ্ণ হৈ আছে"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$sৰ যোগেৰে সংযোজিত"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"সংযোগ কৰা হ\'ল (ফ\'ন নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"সংযোগ কৰা হ\'ল (মিডিয়া নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"সংযোগ কৰা হ\'ল (কোনো ফ\'ন বা মিডিয়া নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"সক্ৰিয়, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰি"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰি"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"সক্ৰিয়"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"মিডিয়াৰ অডিঅ’"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ফ\'ন কলসমূহ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ফাইল স্থানান্তৰণ"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"হেডফ\'ন"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ইনপুট সম্পৰ্কীয় বাহ্য় ডিভাইচ"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ব্লুটুথ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"বাওঁফালৰ শ্ৰৱণ যন্ত্ৰটো যোৰ পতোৱা হৈছে…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"সোঁফালৰ শ্ৰৱণ যন্ত্ৰটো যোৰ পতোৱা হৈছে…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰি বাকী আছে"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"সোঁ - বেটাৰি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"ৱাই-ফাই অফহৈ আছে।"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"ৱাইফাই সংযোগ বিচ্ছিন্ন হৈ আছে।"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"ৱাই-ফাই এদাল দণ্ড।"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"স্বয়ংক্ৰিয়"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ব্যক্তিগত ডিএনএছ প্ৰদানকাৰীৰ হোষ্টনাম"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএছ সেৱা যোগানকাৰীৰ হ\'ষ্টনাম দিয়ক"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"সংযোগ কৰিব পৰা নগ\'ল"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"বেতাঁৰ ডিছপ্লে প্ৰমাণপত্ৰৰ বাবে বিকল্পসমূহ দেখুৱাওক"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ৱাই-ফাই লগিঙৰ মাত্ৰা বঢ়াওক, Wi‑Fi পিকাৰত প্ৰতি SSID RSSI দেখুৱাওক"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ৱাই-ফাই নেটৱৰ্কৰ লগত সংযোগ কৰি থকাৰ সময়ত MAC ঠিকনা যাদৃচ্ছিক কৰক"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"নিৰিখ-নিৰ্দিষ্ট"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"নিৰিখ অনিৰ্দিষ্ট"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"লগাৰৰ বাফাৰৰ আকাৰ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"প্ৰতিটো লগ বাফাৰত ল\'গাৰৰ আকাৰ বাছনি কৰক"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"লগাৰৰ স্থায়ী সঞ্চয়াগাৰৰ বস্তুবোৰ মচিবনে?"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index faa7eb0..499a2fb 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -114,8 +114,8 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Навушнікі"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Перыферыйная прылада ўводу"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Спалучаецца левы навушнік…"</string>
- <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Спалучаецца правы навушнік…"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Спалучаецца левы слыхавы апарат…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Спалучаецца правы слыхавы апарат…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Левы – узровень зараду <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Правы – узровень зараду <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi выключаны."</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 7f3c954..6b37300 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s মাধ্যমে সংযুক্ত হয়েছে"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s এর মাধ্যমে উপলব্ধ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযুক্ত, ইন্টারনেট নেই"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ইন্টারনেট কানেকশন নেই"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"সাইন-ইন করা দরকার"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"এই মুহূর্তে অ্যাক্সেস পয়েন্টের কোনও কানেকশন ফাঁকা নেই"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s এর মাধ্যমে সংযুক্ত হয়েছে"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s এর মাধ্যমে পাওয়া যাচ্ছে"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"কানেক্ট করা আছে (ফোনের অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"কানেক্ট করা আছে (মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"কানেক্ট করা আছে (ফোনের বা মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"চালু আছে, চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"চালু আছে"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"মিডিয়া অডিও"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ফোন কল"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ফাইল স্থানান্তর"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"হেডফোন"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"পেরিফেরাল ইনপুট"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ব্লুটুথ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"বাঁদিকের হিয়ারিং এডটি পেয়ার করা হচ্ছে..."</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"ডানদিকের হিয়ারিং এড পেয়ার করা হচ্ছে…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> চার্জ বাকি আছে"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"ডানদিকের - চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"ওয়াই ফাই বন্ধ৷"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"ওয়াই ফাই এর সংযোগ বিচ্ছিন্ন হয়েছে৷"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"ওয়াই ফাই এ একটি দণ্ড৷"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"অটোমেটিক"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ব্যক্তিগত ডিএনএস প্রদানকারীর হোস্টনেম"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএস প্রদানকারীর হোস্টনেম লিখুন"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"কানেক্ট করা যায়নি"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ওয়াই-ফাই নেটওয়ার্কে সংযুক্ত করার সময় MAC অ্যাড্রেস র্যান্ডমাইজ করুন"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"পরিমাপ করা"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"পরিমাপ করা নয়"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"লগার বাফারের আকারগুলি"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"লগ বাফার প্রতি অপেক্ষাকৃত বড় আকারগুলির বেছে নিন"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"লগারের স্টোরেজ সাফ করবেন?"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index a5b92de..2909265 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Connectada mitjançant %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Disponible mitjançant %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connectada, sense Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sense connexió a Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Cal iniciar la sessió"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"El punt d\'accés està temporalment ple"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Connectat mitjançant %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Disponible mitjançant %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon ni al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Actiu, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actiu"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Àudio multimèdia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Trucades telefòniques"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència del fitxer"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Auricular"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Perifèric d\'entrada"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"S\'està vinculant l\'audiòfon esquerre…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"S\'està vinculant l\'audiòfon dret…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Esquerre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Dret: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi desactivada."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi desconnectada."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Senyal Wi-Fi: una barra."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automàtic"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'amfitrió del proveïdor de DNS privat"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introdueix el nom d\'amfitrió del proveïdor de DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"No s\'ha pogut connectar"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Augmenta nivell de registre Wi‑Fi i mostra\'l per SSID RSSI al Selector de Wi‑Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Aleatoritza l\'adreça MAC quan estiguis connectat a una xarxa Wi-Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Amb límit de dades"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Sense límit de dades"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Mides memòria intermèdia Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Mida Logger per memòria intermèdia"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vols esborrar l\'emmagatzematge persistent del registrador?"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 8c353f4..f3c7323 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -65,9 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon eller medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktiv, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktivt, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
- <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktiv"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktivt"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medielyd"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonopkald"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filoverførsel"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 3d3c66e..c518415 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -241,8 +241,8 @@
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de registro de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Ordenar las direcciones MAC de forma aleatoria al conectarse a redes Wi‑Fi"</string>
- <string name="wifi_metered_label" msgid="4514924227256839725">"Medido"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"No medido"</string>
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Medida"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"No medida"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"¿Borrar almacenamiento continuo del registrador?"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 6acd2ca..4919aa9 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s દ્વારા કનેક્ટ થયેલ"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s દ્વારા ઉપલબ્ધ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"કનેક્ટ કર્યું, કોઈ ઇન્ટરનેટ નથી"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ઇન્ટરનેટ ઍક્સેસ નથી"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"સાઇન ઇન આવશ્યક"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ઍક્સેસ પૉઇન્ટ અસ્થાયીરૂપે ભરાયેલ છે"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s દ્વારા કનેક્ટ થયેલ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s દ્વારા ઉપલબ્ધ"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન અથવા મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"સક્રિય, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"સક્રિય"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"મીડિયા ઑડિઓ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ફોન કૉલ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ફાઇલ સ્થાનાંતરણ"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"હેડફોન"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ઇનપુટ પેરિફેરલ"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"બ્લૂટૂથ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ડાબી બાજુના શ્રવણ યંત્ર સાથે જોડાણ કરી રહ્યાં છીએ…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"જમણી બાજુના શ્રવણ યંત્ર સાથે જોડાણ કરી રહ્યાં છીએ…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"ડાબે - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"જમણી બાજુની - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi બંધ."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi ડિસ્કનેક્ટ થયું."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi એક બાર."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"આપમેળે"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ખાનગી DNS પ્રદાતા હોસ્ટનું નામ"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS પ્રદાતાના હોસ્ટનું નામ દાખલ કરો"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"કનેક્ટ કરી શકાયું નથી"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"વાઇ-ફાઇ નેટવર્ક સાથે જ્યારે કનેક્ટ કરી રહ્યાં હોય ત્યારે MAC ઍડ્રેસને રેન્ડમાઇઝ કરો"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"મીટર કરેલ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"મીટર ન કરેલ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"લોગર બફર કદ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"લૉગર નિરંતર સ્ટોરેજ સાફ કરીએ?"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 9b5c572..f15cdd0 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s के द्वारा उपलब्ध"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s के द्वारा उपलब्ध"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"कनेक्ट हो गया है, लेकिन इंटरनेट नहीं है"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"इंटरनेट कनेक्शन नहीं है"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन करना ज़रूरी है"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"एक्सेस प्वाइंट फ़िलहाल भरा हुआ है"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s के ज़रिए कनेक्ट"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s के ज़रिए उपलब्ध"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"जुड़ गया (फ़ोन के ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"जुड़ गया (मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"जुड़ गया (फ़ोन या मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"चालू, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"चालू"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडियो"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"फ़ोन कॉल"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"फ़ाइल स्थानांतरण"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"हेडफ़ोन"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"इनपुट पेरिफ़ेरल"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ब्लूटूथ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"सुनने में मददगार बाईं ओर का डिवाइस जोड़ा जा रहा है…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"सुनने में मददगार दाईं ओर का डिवाइस जोड़ा जा रहा है…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"बाईं ओर का डिवाइस - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"दाईं ओर का डिवाइस - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"वाई-फ़ाई बंद है."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"वाई-फ़ाई डिसकनेक्ट है."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"वाई-फ़ाई का एक बार है."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"अपने आप"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"निजी DNS सेवा देने वाले का होस्टनाम"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS सेवा देने वाले का होस्टनाम डालें"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"कनेक्ट नहीं हो सका"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस दिखाई देने के लिए प्रमाणन विकल्प दिखाएं"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाई-फ़ाई प्रवेश स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"वाई-फ़ाई से जुड़ते समय अलग-अलग एमएसी पते इस्तेमाल करें"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"डेटा इस्तेमाल करने की सीमा तय की गई है"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"डेटा इस्तेमाल करने की सीमा तय नहीं की गई है"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफ़र आकार"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफ़र लॉगर आकार चुनें"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"लॉगर सतत मेमोरी साफ़ करें?"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index eb611ac..0150f32 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -65,7 +65,7 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Terhubung (tanpa ponsel), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Terhubung (tanpa media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Terhubung (tanpa ponsel atau media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktif, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterai"</string>
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktif, baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="1447164613319663655">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktif"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio media"</string>
@@ -116,8 +116,8 @@
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
<string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Menyambungkan alat bantu dengar sebelah kiri…"</string>
<string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Menyambungkan alat bantu dengar sebelah kanan…"</string>
- <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Kiri - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterai"</string>
- <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Kanan - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterai"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Kiri - baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Kanan - baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi tidak aktif."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi tidak tersambung."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi satu baris."</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 38251b3..9eca2b2 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -65,7 +65,7 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono escluso), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono o contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Attivo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria"</string>
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Attivo - Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="1447164613319663655">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Attivo"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimediale"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index fa29adc..9547d90 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -114,8 +114,8 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Слушалка"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Периферен влез"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Се спарува лев апарат за слушање…"</string>
- <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Се спарува десен апарат за слушање…"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Се спарува лево слушно помагало…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Се спарува десно слушно помагало…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Лево - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Десно - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi е исклучено."</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index e3f996a..22ea56c 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -114,7 +114,7 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"နားကြပ်"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ချိတ်ဆက်အသုံးပြုရသည့် စက်ပစ္စည်းများ"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ဘလူးတုသ်"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ဘယ်ဘက် နားကြီးကိရိယာကို တွဲချိတ်နေသည်…"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ဘယ်ဘက် နားကြားကိရိယာကို တွဲချိတ်နေသည်…"</string>
<string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"ညာဘက် နားကြားကိရိယာကို တွဲချိတ်နေသည်…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"ဘယ်ဘက် − ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"ညာဘက် − ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -241,8 +241,8 @@
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ကြိုးမဲ့ အခင်းအကျင်း အသိအမှတ်ပြုလက်မှတ်အတွက် ရွေးချယ်စရာများပြရန်"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi မှတ်တမ်းတင်ခြင်း နှုန်းအားမြင့်ကာ၊ Wi‑Fi ရွေးရာတွင် SSID RSSI ဖြင့်ပြပါ"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi ကွန်ရက်များသို့ ချိတ်ဆက်သည့်အခါ MAC လိပ်စာ ကျပန်းပြုလုပ်ခြင်း"</string>
- <string name="wifi_metered_label" msgid="4514924227256839725">"မိမိအသုံးပြုမှုအလိုက် ကောက်ခံထားသည်"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"မိမိအသုံးပြုမှုအလိုက် ကောက်ခံခြင်းမရှိပါ"</string>
+ <string name="wifi_metered_label" msgid="4514924227256839725">"အခမဲ့ မဟုတ်ပါ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"အခမဲ့"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"လော့ဂါး ဘာဖား ဆိုက်များ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"လော့ ဘာဖားတွက် လော့ဂါးဆိုက် ရွေး"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"မှတ်တမ်းထိန်းသိမ်းပေးသည့် သိုလှောင်ခန်းကို ရှင်းလင်းမလား။"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index f6352c06..434823f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -116,8 +116,8 @@
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
<string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Se asociază aparatul auditiv stâng…"</string>
<string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Se asociază aparatul auditiv drept…"</string>
- <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Stâng - baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Drept - baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Stânga – baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Dreapta – baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi dezactivat."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi deconectat."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Semnal Wi-Fi: o bară."</string>
@@ -241,8 +241,8 @@
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Afișează aleatoriu adresa MAC când te conectezi la rețele Wi‑Fi"</string>
- <string name="wifi_metered_label" msgid="4514924227256839725">"Contorizat"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"Necontorizat"</string>
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Contorizată"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Necontorizată"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Dimensiunile tamponului jurnalului"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Dimensiuni jurnal / tampon jurnal"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ștergeți stocarea permanentă a jurnalului?"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index fd2f1ea..8162a76 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"منسلک بذریعہ %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"دستیاب بذریعہ %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"منسلک، انٹرنیٹ نہیں ہے"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"انٹرنیٹ نہیں ہے"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"سائن ان درکار ہے"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"رسائی پوائنٹ عارضی طور پر فُل ہے"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"منسلک بذریعہ %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"دستیاب بذریعہ %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"منسلک ہے (فون کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"منسلک ہے (میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"منسلک ہے (فون یا میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"فعال، <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"فعال"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"میڈيا آڈیو"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"فون کالز"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"فائل کی منتقلی"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"ہیڈ فون"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ان پٹ پیریفرل"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"بلوٹوتھ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"بائيں جانب کے سماعتی آلہ کا جوڑا بنایا جا رہا ہے…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"دائیں جانب کے سماعتی آلہ کا جوڑا بنایا جا رہا ہے…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"بائيں - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"دائيں - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi آف ہے۔"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi غیر منسلک ہو گیا۔"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi ایک بار۔"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"خودکار"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"نجی DNS فراہم کنندہ میزبان کا نام"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS فراہم کنندہ کے میزبان کا نام درج کریں"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"منسلک نہیں ہو سکا"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"وائرلیس ڈسپلے سرٹیفیکیشن کیلئے اختیارات دکھائیں"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi لاگنگ لیول میں اضافہ کریں، Wi‑Fi منتخب کنندہ میں فی SSID RSSI دکھائیں"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi نیٹ ورکس سے منسلک کرتے وقت MAC پتے کو غیر مرتب کریں"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"میٹرڈ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"غیر میٹر شدہ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"لاگر بفر کے سائز"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"فی لاگ بفر لاگر کے سائز منتخب کریں"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"لاگر مستقل اسٹوریج صاف کریں؟"</string>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 7b09ef7..cf4261c 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -33,6 +33,8 @@
<dimen name="user_spinner_item_height">56dp</dimen>
<dimen name="two_target_pref_small_icon_size">24dp</dimen>
+ <dimen name="two_target_pref_medium_icon_size">32dp</dimen>
+
<!-- Lock icon for preferences locked by admin -->
<dimen name="restricted_icon_size">16dp</dimen>
<dimen name="restricted_icon_padding">4dp</dimen>
diff --git a/packages/SettingsLib/src/com/android/settingslib/TwoTargetPreference.java b/packages/SettingsLib/src/com/android/settingslib/TwoTargetPreference.java
index 8b39f60..02b68d8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/TwoTargetPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/TwoTargetPreference.java
@@ -16,6 +16,7 @@
package com.android.settingslib;
+import android.annotation.IntDef;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
@@ -24,10 +25,24 @@
import android.widget.ImageView;
import android.widget.LinearLayout;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
public class TwoTargetPreference extends Preference {
- private boolean mUseSmallIcon;
+ @IntDef({ICON_SIZE_DEFAULT, ICON_SIZE_MEDIUM, ICON_SIZE_SMALL})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IconSize {
+ }
+
+ public static final int ICON_SIZE_DEFAULT = 0;
+ public static final int ICON_SIZE_MEDIUM = 1;
+ public static final int ICON_SIZE_SMALL = 2;
+
+ @IconSize
+ private int mIconSize;
private int mSmallIconSize;
+ private int mMediumIconSize;
public TwoTargetPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
@@ -54,22 +69,30 @@
setLayoutResource(R.layout.preference_two_target);
mSmallIconSize = context.getResources().getDimensionPixelSize(
R.dimen.two_target_pref_small_icon_size);
+ mMediumIconSize = context.getResources().getDimensionPixelSize(
+ R.dimen.two_target_pref_medium_icon_size);
final int secondTargetResId = getSecondTargetResId();
if (secondTargetResId != 0) {
setWidgetLayoutResource(secondTargetResId);
}
}
- public void setUseSmallIcon(boolean useSmallIcon) {
- mUseSmallIcon = useSmallIcon;
+ public void setIconSize(@IconSize int iconSize) {
+ mIconSize = iconSize;
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
- if (mUseSmallIcon) {
- ImageView icon = holder.itemView.findViewById(android.R.id.icon);
- icon.setLayoutParams(new LinearLayout.LayoutParams(mSmallIconSize, mSmallIconSize));
+ final ImageView icon = holder.itemView.findViewById(android.R.id.icon);
+ switch (mIconSize) {
+ case ICON_SIZE_SMALL:
+ icon.setLayoutParams(new LinearLayout.LayoutParams(mSmallIconSize, mSmallIconSize));
+ break;
+ case ICON_SIZE_MEDIUM:
+ icon.setLayoutParams(
+ new LinearLayout.LayoutParams(mMediumIconSize, mMediumIconSize));
+ break;
}
final View divider = holder.findViewById(R.id.two_target_divider);
final View widgetFrame = holder.findViewById(android.R.id.widget_frame);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 6c068ff..dc2ecea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -631,7 +631,7 @@
}
HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
if (hearingAidProfile != null) {
- mIsActiveDeviceHearingAid = hearingAidProfile.isActiveDevice(mDevice);
+ mIsActiveDeviceHearingAid = hearingAidProfile.getActiveDevices().contains(mDevice);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 920500f..6c5ecbf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -136,13 +136,12 @@
public boolean setActiveDevice(BluetoothDevice device) {
if (mService == null) return false;
- mService.setActiveDevice(device);
- return true;
+ return mService.setActiveDevice(device);
}
- public boolean isActiveDevice(BluetoothDevice device) {
- if (mService == null) return false;
- return mService.isActiveDevice(device);
+ public List<BluetoothDevice> getActiveDevices() {
+ if (mService == null) return new ArrayList<>();
+ return mService.getActiveDevices();
}
public boolean isPreferred(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
new file mode 100644
index 0000000..941964a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHidDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * HidProfile handles Bluetooth HID profile.
+ */
+public class HidDeviceProfile implements LocalBluetoothProfile {
+ private static final String TAG = "HidDeviceProfile";
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 18;
+ // HID Device Profile is always preferred.
+ private static final int PREFERRED_VALUE = -1;
+ private static final boolean DEBUG = true;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private final LocalBluetoothProfileManager mProfileManager;
+ static final String NAME = "HID DEVICE";
+
+ private BluetoothHidDevice mService;
+ private boolean mIsProfileReady;
+
+ HidDeviceProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ adapter.getProfileProxy(context, new HidDeviceServiceListener(),
+ BluetoothProfile.HID_DEVICE);
+ }
+
+ // These callbacks run on the main thread.
+ private final class HidDeviceServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (DEBUG) {
+ Log.d(TAG,"Bluetooth service connected :-)");
+ }
+ mService = (BluetoothHidDevice) proxy;
+ // We just bound to the service, so refresh the UI for any connected HID devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ for (BluetoothDevice nextDevice : deviceList) {
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "HidProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ Log.d(TAG, "Connection status changed: " + device);
+ device.onProfileStateChanged(HidDeviceProfile.this,
+ BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+ mIsProfileReady = true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (DEBUG) {
+ Log.d(TAG, "Bluetooth service disconnected");
+ }
+ mIsProfileReady = false;
+ }
+ }
+
+ @Override
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ @Override
+ public boolean isConnectable() {
+ return true;
+ }
+
+ @Override
+ public boolean isAutoConnectable() {
+ return false;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device) {
+ return false;
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) {
+ return false;
+ }
+ return mService.disconnect(device);
+ }
+
+ @Override
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+
+ return !deviceList.isEmpty() && deviceList.contains(device)
+ ? mService.getConnectionState(device)
+ : BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ @Override
+ public boolean isPreferred(BluetoothDevice device) {
+ return getConnectionStatus(device) != BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ @Override
+ public int getPreferred(BluetoothDevice device) {
+ return PREFERRED_VALUE;
+ }
+
+ @Override
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ // if set preferred to false, then disconnect to the current device
+ if (!preferred) {
+ mService.disconnect(device);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return NAME;
+ }
+
+ @Override
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ @Override
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_hid;
+ }
+
+ @Override
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ final int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_hid_profile_summary_use_for;
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_hid_profile_summary_connected;
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ @Override
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_misc_hid;
+ }
+
+ protected void finalize() {
+ if (DEBUG) {
+ Log.d(TAG, "finalize()");
+ }
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HID_DEVICE,
+ mService);
+ mService = null;
+ } catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up HID proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index 213002f..93c4017 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -48,7 +48,7 @@
private static final int ORDINAL = 3;
// These callbacks run on the main thread.
- private final class InputDeviceServiceListener
+ private final class HidHostServiceListener
implements BluetoothProfile.ServiceListener {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -86,7 +86,7 @@
mLocalAdapter = adapter;
mDeviceManager = deviceManager;
mProfileManager = profileManager;
- adapter.getProfileProxy(context, new InputDeviceServiceListener(),
+ adapter.getProfileProxy(context, new HidHostServiceListener(),
BluetoothProfile.HID_HOST);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 34a099c..6413aab 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -22,6 +22,7 @@
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothHidDevice;
import android.bluetooth.BluetoothHidHost;
import android.bluetooth.BluetoothMap;
import android.bluetooth.BluetoothMapClient;
@@ -86,6 +87,7 @@
private MapProfile mMapProfile;
private MapClientProfile mMapClientProfile;
private final HidProfile mHidProfile;
+ private HidDeviceProfile mHidDeviceProfile;
private OppProfile mOppProfile;
private final PanProfile mPanProfile;
private PbapClientProfile mPbapClientProfile;
@@ -123,7 +125,7 @@
updateLocalProfiles(uuids);
}
- // Always add HID and PAN profiles
+ // Always add HID host, HID device, and PAN profiles
mHidProfile = new HidProfile(context, mLocalAdapter, mDeviceManager, this);
addProfile(mHidProfile, HidProfile.NAME,
BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
@@ -132,6 +134,10 @@
addPanProfile(mPanProfile, PanProfile.NAME,
BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
+ mHidDeviceProfile = new HidDeviceProfile(context, mLocalAdapter, mDeviceManager, this);
+ addProfile(mHidDeviceProfile, HidDeviceProfile.NAME,
+ BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
+
if(DEBUG) Log.d(TAG, "Adding local MAP profile");
if (mUseMapClient) {
mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
@@ -195,8 +201,10 @@
if (DEBUG) Log.d(TAG, "Adding local HEADSET profile");
mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter,
mDeviceManager, this);
- addProfile(mHeadsetProfile, HeadsetProfile.NAME,
- BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
+ addHeadsetProfile(mHeadsetProfile, HeadsetProfile.NAME,
+ BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
+ BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
+ BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
}
} else if (mHeadsetProfile != null) {
Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
@@ -208,8 +216,10 @@
if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
mHfpClientProfile =
new HfpClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
- addProfile(mHfpClientProfile, HfpClientProfile.NAME,
- BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
+ addHeadsetProfile(mHfpClientProfile, HfpClientProfile.NAME,
+ BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED,
+ BluetoothHeadsetClient.ACTION_AUDIO_STATE_CHANGED,
+ BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED);
}
} else if (mHfpClientProfile != null) {
Log.w(TAG,
@@ -277,6 +287,15 @@
// There is no local SDP record for HID and Settings app doesn't control PBAP Server.
}
+ private void addHeadsetProfile(LocalBluetoothProfile profile, String profileName,
+ String stateChangedAction, String audioStateChangedAction, int audioDisconnectedState) {
+ BluetoothEventManager.Handler handler = new HeadsetStateChangeHandler(
+ profile, audioStateChangedAction, audioDisconnectedState);
+ mEventManager.addProfileHandler(stateChangedAction, handler);
+ mEventManager.addProfileHandler(audioStateChangedAction, handler);
+ mProfileNameMap.put(profileName, profile);
+ }
+
private final Collection<ServiceListener> mServiceListeners =
new ArrayList<ServiceListener>();
@@ -323,18 +342,47 @@
cachedDevice = mDeviceManager.addDevice(mLocalAdapter,
LocalBluetoothProfileManager.this, device);
}
+ onReceiveInternal(intent, cachedDevice);
+ }
+
+ protected void onReceiveInternal(Intent intent, CachedBluetoothDevice cachedDevice) {
int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
if (newState == BluetoothProfile.STATE_DISCONNECTED &&
oldState == BluetoothProfile.STATE_CONNECTING) {
Log.i(TAG, "Failed to connect " + mProfile + " device");
}
-
cachedDevice.onProfileStateChanged(mProfile, newState);
cachedDevice.refresh();
}
}
+ /** Connectivity and audio state change handler for headset profiles. */
+ private class HeadsetStateChangeHandler extends StateChangedHandler {
+ private final String mAudioChangeAction;
+ private final int mAudioDisconnectedState;
+
+ HeadsetStateChangeHandler(LocalBluetoothProfile profile, String audioChangeAction,
+ int audioDisconnectedState) {
+ super(profile);
+ mAudioChangeAction = audioChangeAction;
+ mAudioDisconnectedState = audioDisconnectedState;
+ }
+
+ @Override
+ public void onReceiveInternal(Intent intent, CachedBluetoothDevice cachedDevice) {
+ if (mAudioChangeAction.equals(intent.getAction())) {
+ int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
+ if (newState != mAudioDisconnectedState) {
+ cachedDevice.onProfileStateChanged(mProfile, BluetoothProfile.STATE_CONNECTED);
+ }
+ cachedDevice.refresh();
+ } else {
+ super.onReceiveInternal(intent, cachedDevice);
+ }
+ }
+ }
+
/** State change handler for NAP and PANU profiles. */
private class PanStateChangedHandler extends StateChangedHandler {
@@ -505,6 +553,12 @@
removedProfiles.remove(mHidProfile);
}
+ if (mHidProfile != null && mHidDeviceProfile.getConnectionStatus(device)
+ != BluetoothProfile.STATE_DISCONNECTED) {
+ profiles.add(mHidDeviceProfile);
+ removedProfiles.remove(mHidDeviceProfile);
+ }
+
if(isPanNapConnected)
if(DEBUG) Log.d(TAG, "Valid PAN-NAP connection exists.");
if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP) &&
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index 835ff07..f7b16f8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -148,15 +148,32 @@
Secure.putInt(context.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
}
+ /**
+ * Don't show the automatic battery suggestion notification in the future.
+ */
public static void suppressAutoBatterySaver(Context context) {
Secure.putInt(context.getContentResolver(),
Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, 1);
}
- public static void scheduleAutoBatterySaver(Context context, int level) {
+ /**
+ * Set the automatic battery saver trigger level to {@code level}.
+ */
+ public static void setAutoBatterySaverTriggerLevel(Context context, int level) {
+ if (level > 0) {
+ suppressAutoBatterySaver(context);
+ }
+ Global.putInt(context.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL, level);
+ }
+
+ /**
+ * Set the automatic battery saver trigger level to {@code level}, but only when
+ * automatic battery saver isn't enabled yet.
+ */
+ public static void ensureAutoBatterySaver(Context context, int level) {
if (Global.getInt(context.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)
== 0) {
- Global.putInt(context.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL, level);
+ setAutoBatterySaverTriggerLevel(context, level);
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
index 7081678..06e2ee1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
@@ -16,6 +16,7 @@
package com.android.settingslib.fuelgauge;
+import android.content.pm.PackageManager;
import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -24,6 +25,8 @@
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
+
/**
* Handles getting/changing the whitelist for the exceptions to battery saving features.
*/
@@ -68,6 +71,19 @@
return mSysWhitelistedAppsExceptIdle.contains(pkg);
}
+ public boolean isSysWhitelistedExceptIdle(String[] pkgs) {
+ if (ArrayUtils.isEmpty(pkgs)) {
+ return false;
+ }
+ for (String pkg : pkgs) {
+ if (isSysWhitelistedExceptIdle(pkg)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public void addApp(String pkg) {
try {
mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index 8b3da39..de29030 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -144,7 +144,8 @@
FIFTEEN_MINUTES_MILLIS);
// convert the time to a properly formatted string.
- DateFormat fmt = DateFormat.getTimeInstance(DateFormat.SHORT);
+ 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);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 9347674..547cd9a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -41,8 +41,9 @@
private final WifiManager mWifiManager;
private final NetworkScoreManager mNetworkScoreManager;
private final ConnectivityManager mConnectivityManager;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
private final WifiNetworkScoreCache.CacheListener mCacheListener =
- new WifiNetworkScoreCache.CacheListener(new Handler(Looper.getMainLooper())) {
+ new WifiNetworkScoreCache.CacheListener(mHandler) {
@Override
public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) {
updateStatusLabel();
@@ -89,7 +90,8 @@
mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
mWifiNetworkScoreCache.registerListener(mCacheListener);
- mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
+ mConnectivityManager.registerNetworkCallback(
+ mNetworkRequest, mNetworkCallback, mHandler);
} else {
mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI,
mWifiNetworkScoreCache);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index a128b54..d8f0886 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -313,7 +313,8 @@
mContext.registerReceiver(mReceiver, mFilter, null /* permission */, mWorkHandler);
// NetworkCallback objects cannot be reused. http://b/20701525 .
mNetworkCallback = new WifiTrackerNetworkCallback();
- mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
+ mConnectivityManager.registerNetworkCallback(
+ mNetworkRequest, mNetworkCallback, mWorkHandler);
mRegistered = true;
}
}
@@ -788,7 +789,7 @@
// We don't send a NetworkInfo object along with this message, because even if we
// fetch one from ConnectivityManager, it might be older than the most recent
// NetworkInfo message we got via a WIFI_STATE_CHANGED broadcast.
- mWorkHandler.post(() -> updateNetworkInfo(null));
+ updateNetworkInfo(null);
}
}
}
diff --git a/packages/SettingsLib/tests/integ/AndroidTest.xml b/packages/SettingsLib/tests/integ/AndroidTest.xml
index 96621eb..d7ee618 100644
--- a/packages/SettingsLib/tests/integ/AndroidTest.xml
+++ b/packages/SettingsLib/tests/integ/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.settingslib" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
index c5e93f0..480143a7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
@@ -16,6 +16,9 @@
package com.android.settingslib;
+import static com.android.settingslib.TwoTargetPreference.ICON_SIZE_DEFAULT;
+import static com.android.settingslib.TwoTargetPreference.ICON_SIZE_MEDIUM;
+import static com.android.settingslib.TwoTargetPreference.ICON_SIZE_SMALL;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -75,8 +78,8 @@
}
@Test
- public void bind_smallIcon_shouldUseSmallIcon() {
- mPreference.setUseSmallIcon(true);
+ public void bind_smallIcon_shouldUseSmallIconSize() {
+ mPreference.setIconSize(ICON_SIZE_SMALL);
mPreference.onBindViewHolder(mViewHolder);
@@ -91,8 +94,24 @@
}
@Test
- public void bind_normalIcon_shouldUseNormalIcon() {
- mPreference.setUseSmallIcon(false);
+ public void bind_mediumIcon_shouldUseMediumIconSize() {
+ mPreference.setIconSize(ICON_SIZE_MEDIUM);
+
+ mPreference.onBindViewHolder(mViewHolder);
+
+ final int size = mContext.getResources().getDimensionPixelSize(
+ R.dimen.two_target_pref_medium_icon_size);
+ final LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) mViewHolder
+ .findViewById(android.R.id.icon)
+ .getLayoutParams();
+
+ assertThat(layoutParams.width).isEqualTo(size);
+ assertThat(layoutParams.height).isEqualTo(size);
+ }
+
+ @Test
+ public void bind_defaultIcon_shouldUseDefaultIconSize() {
+ mPreference.setIconSize(ICON_SIZE_DEFAULT);
mPreference.onBindViewHolder(mViewHolder);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
index b33df30..ba5a2c5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -16,7 +16,9 @@
package com.android.settingslib.fuelgauge;
+import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
@@ -28,6 +30,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
+import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import com.android.settingslib.SettingsLibRobolectricTestRunner;
@@ -41,6 +44,9 @@
@RunWith(SettingsLibRobolectricTestRunner.class)
public class BatterySaverUtilsTest {
+ final int BATTERY_SAVER_THRESHOLD_1 = 15;
+ final int BATTERY_SAVER_THRESHOLD_2 = 20;
+
@Mock
Context mMockContext;
@@ -149,4 +155,37 @@
assertEquals(-2,
Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
+
+ @Test
+ public void testEnsureAutoBatterysaver_setNewPositiveValue_doNotOverwrite() throws Exception {
+ Global.putString(mMockResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, "null");
+
+ BatterySaverUtils.ensureAutoBatterySaver(mMockContext, BATTERY_SAVER_THRESHOLD_1);
+
+ assertThat(Secure.getInt(mMockResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1))
+ .isEqualTo(BATTERY_SAVER_THRESHOLD_1);
+
+ // Once a positive number is set, ensureAutoBatterySaver() won't overwrite it.
+ BatterySaverUtils.ensureAutoBatterySaver(mMockContext, BATTERY_SAVER_THRESHOLD_2);
+ assertThat(Secure.getInt(mMockResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1))
+ .isEqualTo(BATTERY_SAVER_THRESHOLD_1);
+ }
+
+ @Test
+ public void testSetAutoBatterySaverTriggerLevel_setSuppressSuggestion() throws Exception {
+ Global.putString(mMockResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, "null");
+ Secure.putString(mMockResolver, Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, "null");
+
+ BatterySaverUtils.setAutoBatterySaverTriggerLevel(mMockContext, 0);
+ assertThat(Global.getInt(mMockResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1))
+ .isEqualTo(0);
+ assertThat(Secure.getInt(mMockResolver, Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, -1))
+ .isEqualTo(-1); // not set.
+
+ BatterySaverUtils.setAutoBatterySaverTriggerLevel(mMockContext, BATTERY_SAVER_THRESHOLD_1 );
+ assertThat( Global.getInt(mMockResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1))
+ .isEqualTo(BATTERY_SAVER_THRESHOLD_1);
+ assertThat(Secure.getInt(mMockResolver, Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, -1))
+ .isEqualTo(1);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index 5a123af..f591781 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -92,7 +92,7 @@
}
@Test
- public void testIsSystemWhitelistedExceptIdle() throws Exception {
+ public void testIsSystemWhitelistedExceptIdle_onePackage() throws Exception {
doReturn(new String[]{PACKAGE_TWO}).when(
mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
mPowerWhitelistBackend.refreshList();
@@ -100,4 +100,17 @@
assertThat(mPowerWhitelistBackend.isSysWhitelistedExceptIdle(PACKAGE_ONE)).isFalse();
assertThat(mPowerWhitelistBackend.isSysWhitelistedExceptIdle(PACKAGE_TWO)).isTrue();
}
+
+ @Test
+ public void testIsSystemWhitelistedExceptIdle_packageArray() throws Exception {
+ doReturn(new String[]{PACKAGE_TWO}).when(
+ mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
+ mPowerWhitelistBackend.refreshList();
+
+ final String[] idlePackages = {PACKAGE_ONE, PACKAGE_TWO};
+ final String[] normalPackages = {PACKAGE_ONE};
+
+ assertThat(mPowerWhitelistBackend.isSysWhitelistedExceptIdle(normalPackages)).isFalse();
+ assertThat(mPowerWhitelistBackend.isSysWhitelistedExceptIdle(idlePackages)).isTrue();
+ }
}
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 05247ba..dfd48cc 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,8 +42,8 @@
public static final long THIRTY_HOURS_MILLIS = Duration.ofHours(30).toMillis();
public static final String NORMAL_CASE_EXPECTED_PREFIX = "Should last until about";
public static final String ENHANCED_SUFFIX = " based on your usage";
- // matches a time (ex: '1:15 PM', '2 AM')
- public static final String TIME_OF_DAY_REGEX = " (\\d)+:?(\\d)* (AM)|(PM)";
+ // matches a time (ex: '1:15 PM', '2 AM', '23:00')
+ public static final String TIME_OF_DAY_REGEX = " (\\d)+:?(\\d)* ((AM)*)|((PM)*)";
// matches a percentage with parenthesis (ex: '(10%)')
public static final String PERCENTAGE_REGEX = " \\(\\d?\\d%\\)";
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index ad422d8..4c98bb8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -144,10 +144,7 @@
}
try {
- if (Settings.System.SCREEN_BRIGHTNESS.equals(name)) {
- setBrightness(Integer.parseInt(value));
- // fall through to the ordinary write to settings
- } else if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
+ if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
setSoundEffects(Integer.parseInt(value) == 1);
// fall through to the ordinary write to settings
} else if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
@@ -305,10 +302,6 @@
}
}
- private void setBrightness(int brightness) {
- mContext.getSystemService(DisplayManager.class).setTemporaryBrightness(brightness);
- }
-
/* package */ byte[] getLocaleData() {
Configuration conf = mContext.getResources().getConfiguration();
return conf.getLocales().toLanguageTags().getBytes();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 67053d8..a2263b4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2231,6 +2231,12 @@
Settings.Secure.WAKE_GESTURE_ENABLED,
SecureSettingsProto.WAKE_GESTURE_ENABLED);
+ final long launcherToken = p.start(SecureSettingsProto.LAUNCHER);
+ dumpSetting(s, p,
+ Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED,
+ SecureSettingsProto.Launcher.SWIPE_UP_TO_SWITCH_APPS_ENABLED);
+ p.end(launcherToken);
+
// Please insert new settings using the same order as in SecureSettingsProto.
p.end(token);
diff --git a/packages/SettingsProvider/test/AndroidTest.xml b/packages/SettingsProvider/test/AndroidTest.xml
index 3a156895..46b8f94 100644
--- a/packages/SettingsProvider/test/AndroidTest.xml
+++ b/packages/SettingsProvider/test/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.providers.setting.test" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/Shell/res/values-ne/strings.xml b/packages/Shell/res/values-ne/strings.xml
index eadfeb9..77ef32a 100644
--- a/packages/Shell/res/values-ne/strings.xml
+++ b/packages/Shell/res/values-ne/strings.xml
@@ -25,9 +25,9 @@
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"उक्त बग सम्बन्धी रिपोर्ट चाँडै नै यस फोनमा देखा पर्नेछ"</string>
<string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"तपाईंको बग रिपोर्ट आदान प्रदान गर्न चयन गर्नुहोस्"</string>
<string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"तपाईंको बग रिपोर्टलाई साझेदारी गर्न ट्याप गर्नुहोस्"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"तपाईंको बग रिपोर्ट स्क्रिनसट बिना आदान प्रदान गर्नका लागि चयन गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"तपाईंको बग रिपोर्ट स्क्रिनसट बिना आदान प्रदान गर्नाका लागि चयन गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नाका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नाका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
<string name="bugreport_confirm" msgid="5917407234515812495">"बग रिपोर्टहरूमा प्रणालीका विभिन्न लग फाइलहरूको डेटा हुन्छ जसमा तपाईँले संवेदनशील मानेको डेटा समावेश हुन सक्छ (जस्तै अनुप्रयोगको प्रयोग र स्थान सम्बन्धी डेटा)। तपाईँले विश्वास गर्ने व्यक्ति र अनुप्रयोगहरूसँग मात्र बग रिपोर्टहरूलाई साझेदारी गर्नुहोस्।"</string>
<string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"फेरि नदेखाउनुहोस्"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्टहरू"</string>
diff --git a/packages/Shell/tests/AndroidTest.xml b/packages/Shell/tests/AndroidTest.xml
index bd37712c..e592d82 100644
--- a/packages/Shell/tests/AndroidTest.xml
+++ b/packages/Shell/tests/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.shell.tests" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 0ee40d7..67f68d3 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -15,40 +15,32 @@
limitations under the License.
-->
+
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:clipChildren="false"
android:alpha="0"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/car_fullscreen_user_pod_height"
- android:layout_gravity="center_horizontal|bottom" >
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:gravity="fill_horizontal"
+ android:layout_marginTop="@dimen/car_padding_5"
+ android:layout_marginStart="@dimen/car_padding_4">
<ImageView android:id="@+id/user_avatar"
android:layout_centerHorizontal="true"
- android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_image_top"
android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
- android:layout_above="@id/user_name" />
+ />
<TextView android:id="@+id/user_name"
- android:layout_width="@dimen/car_fullscreen_user_pod_width"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_name_top"
- android:layout_marginBottom="@dimen/car_fullscreen_user_pod_margin_name_bottom"
- android:textSize="@dimen/car_fullscreen_user_pod_name_text_size"
+ android:layout_marginTop="@dimen/car_padding_4"
+ android:textSize="@dimen/car_body1_size"
android:textColor="@color/qs_user_detail_name"
android:ellipsize="end"
android:singleLine="true"
- android:gravity="center_horizontal"
- android:layout_above="@id/device_name" />
+ android:gravity="center"
+ android:layout_below="@id/user_avatar"/>
- <TextView android:id="@+id/device_name"
- android:layout_width="@dimen/car_fullscreen_user_pod_width"
- android:layout_height="wrap_content"
- android:textSize="@dimen/car_fullscreen_user_pod_device_text_size"
- android:textColor="@color/qs_user_detail_name"
- android:ellipsize="end"
- android:singleLine="true"
- android:gravity="center_horizontal"
- android:layout_alignParentBottom="true" />
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
deleted file mode 100644
index d666a20..0000000
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:clipChildren="false"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center" >
-
- <!-- car_fullscreen_user_pods will be dynamically added here. -->
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index bfabe52..22452b7 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -39,27 +39,34 @@
android:theme="@android:style/Theme"
android:layout_alignParentTop="true"/>
- <com.android.systemui.statusbar.car.UserGridView
- android:id="@+id/user_grid"
+ <RelativeLayout
+ android:id="@+id/fullscreen_user_switcher_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/car_margin"
- android:layout_marginRight="@dimen/car_margin"
- android:layout_centerInParent="true"/>
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/car_margin"
+ android:layout_marginEnd="@dimen/car_margin">
- <com.android.systemui.statusbar.car.PageIndicator
- android:id="@+id/user_switcher_page_indicator"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_page_indicator_dot_diameter"
- android:layout_below="@+id/user_grid" />
+ <RelativeLayout
+ android:id="@+id/fullscreen_user_switcher_container_inner"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="@dimen/car_padding_4">
- <Button
- android:id="@+id/start_driving"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/car_start_driving_height"
- android:text="@string/start_driving"
- style="@style/CarUserSwitcher.StartDrivingButton"
- android:layout_alignParentBottom="true"
- android:layout_centerHorizontal="true" />
+ <com.android.systemui.statusbar.car.UserGridRecyclerView
+ android:id="@+id/user_grid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/header"
+ android:scrollbars="vertical"
+ android:scrollbarFadeDuration="0"
+ android:verticalScrollbarPosition="left"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"/>
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
</RelativeLayout>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/car_left_navigation_bar.xml b/packages/SystemUI/res/layout/car_left_navigation_bar.xml
index 18301a8..02be457 100644
--- a/packages/SystemUI/res/layout/car_left_navigation_bar.xml
+++ b/packages/SystemUI/res/layout/car_left_navigation_bar.xml
@@ -40,7 +40,7 @@
android:id="@+id/home"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
android:src="@drawable/car_ic_overview"
android:background="?android:attr/selectableItemBackground"
android:paddingTop="30dp"
diff --git a/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
index a65ff16..708f595 100644
--- a/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
+++ b/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
@@ -40,7 +40,7 @@
android:id="@+id/home"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
android:src="@drawable/car_ic_overview"
android:background="?android:attr/selectableItemBackground"
android:paddingTop="30dp"
diff --git a/packages/SystemUI/res/layout/car_navigation_bar.xml b/packages/SystemUI/res/layout/car_navigation_bar.xml
index 9ff16a2..d568d0d 100644
--- a/packages/SystemUI/res/layout/car_navigation_bar.xml
+++ b/packages/SystemUI/res/layout/car_navigation_bar.xml
@@ -38,7 +38,7 @@
android:id="@+id/home"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
android:src="@drawable/car_ic_overview"
android:background="?android:attr/selectableItemBackground"
android:paddingLeft="30dp"
diff --git a/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml
index b0488ae..4ba6c06 100644
--- a/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml
+++ b/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml
@@ -38,7 +38,7 @@
android:id="@+id/home"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
android:src="@drawable/car_ic_overview"
android:background="?android:attr/selectableItemBackground"
android:paddingLeft="30dp"
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index 447970c..c01bbce 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -30,27 +30,29 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/user_switcher_container"
+ android:layout_marginStart="@dimen/car_margin"
+ android:layout_marginEnd="@dimen/car_margin"
android:clipChildren="false"
android:layout_width="match_parent"
- android:layout_height="@dimen/car_user_switcher_container_height"
- android:layout_gravity="center_horizontal" >
+ android:layout_height="@dimen/car_user_switcher_container_height">
- <com.android.systemui.statusbar.car.UserGridView
- android:id="@+id/user_grid"
- android:clipChildren="false"
+ <RelativeLayout
+ android:id="@+id/fullscreen_user_switcher_container_inner"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/car_margin"
- android:layout_marginRight="@dimen/car_margin"
- android:layout_above="@id/user_switcher_page_indicator" />
+ android:layout_height="match_parent"
+ android:layout_marginEnd="@dimen/car_padding_4">
- <com.android.systemui.statusbar.car.PageIndicator
- android:id="@+id/user_switcher_page_indicator"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_page_indicator_dot_diameter"
- android:layout_marginBottom="@dimen/car_page_indicator_margin_bottom"
- android:alpha="0"
- android:layout_alignParentBottom="true" />
+ <com.android.systemui.statusbar.car.UserGridRecyclerView
+ android:id="@+id/user_grid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scrollbars="vertical"
+ android:verticalScrollbarPosition="left"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"
+ android:scrollbarFadeDuration="0"/>
+ </RelativeLayout>
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/car_right_navigation_bar.xml b/packages/SystemUI/res/layout/car_right_navigation_bar.xml
index 99bd23c..91ba026 100644
--- a/packages/SystemUI/res/layout/car_right_navigation_bar.xml
+++ b/packages/SystemUI/res/layout/car_right_navigation_bar.xml
@@ -40,7 +40,7 @@
android:id="@+id/home"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
android:src="@drawable/car_ic_overview"
android:background="?android:attr/selectableItemBackground"
android:paddingTop="30dp"
diff --git a/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
index a65ff16..708f595 100644
--- a/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
+++ b/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
@@ -40,7 +40,7 @@
android:id="@+id/home"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
android:src="@drawable/car_ic_overview"
android:background="?android:attr/selectableItemBackground"
android:paddingTop="30dp"
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index 79e54aa..d72021e 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -27,13 +27,16 @@
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<LinearLayout
android:id="@+id/ends_group"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
+ android:clipToPadding="false"
android:clipChildren="false" />
<LinearLayout
@@ -43,6 +46,7 @@
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"
+ android:clipToPadding="false"
android:clipChildren="false" />
</com.android.systemui.statusbar.phone.NearestTouchFrame>
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 5229f9b..54baa4a 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -41,13 +41,14 @@
android:visibility="invisible">
<ImageView
- android:id="@+id/ringer_mode_icon"
+ android:id="@+id/next_alarm_icon"
android:layout_width="@dimen/qs_header_alarm_icon_size"
android:layout_height="@dimen/qs_header_alarm_icon_size"
+ android:src="@drawable/stat_sys_alarm"
android:tint="?android:attr/textColorPrimary" />
<TextView
- android:id="@+id/ringer_mode_text"
+ android:id="@+id/next_alarm_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
@@ -63,14 +64,13 @@
android:backgroundTint="?android:attr/textColorPrimary" />
<ImageView
- android:id="@+id/next_alarm_icon"
+ android:id="@+id/ringer_mode_icon"
android:layout_width="@dimen/qs_header_alarm_icon_size"
android:layout_height="@dimen/qs_header_alarm_icon_size"
- android:src="@drawable/stat_sys_alarm"
android:tint="?android:attr/textColorPrimary" />
<TextView
- android:id="@+id/next_alarm_text"
+ android:id="@+id/ringer_mode_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index e4ea08e..b5d48b4 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -51,12 +51,10 @@
<ImageButton
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:layout_gravity="center"
android:paddingStart="12dp"
android:paddingEnd="24dp"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
android:id="@+id/remote_input_send"
android:src="@drawable/ic_send"
android:contentDescription="@*android:string/ime_action_send"
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 0a1896f..c830f79 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -74,10 +74,8 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"স্ক্ৰীণশ্বট ছেভ কৰা হ\'ল"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"আপোনাৰ স্ক্ৰীণশ্বট চাবলৈ টিপক"</string>
- <!-- no translation found for screenshot_failed_title (7612509838919089748) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (3637758096565605541) -->
- <skip />
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"স্ক্ৰীণশ্বট আকৌ ল\'বলৈ চেষ্টা কৰক"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"সঞ্চয়াগাৰত সীমিত খালী ঠাই থকাৰ বাবে স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"এপটোৱে বা আপোনাৰ প্ৰতিষ্ঠানে স্ক্ৰীণশ্বট ল\'বলৈ অনুমতি নিদিয়ে"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"ইউএছবিৰে ফাইল স্থানান্তৰণৰ বিকল্পসমূহ"</string>
@@ -348,8 +346,7 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"সূৰ্যাস্তত অন কৰক"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"সূৰ্যোদয়ৰ লৈকে"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>ত অন কৰক"</string>
- <!-- no translation found for quick_settings_secondary_label_until (2749196569462600150) -->
- <skip />
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> পৰ্যন্ত"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC নিষ্ক্ৰিয় হৈ আছে"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC সক্ষম হৈ আছে"</string>
@@ -433,8 +430,7 @@
<string name="media_projection_dialog_text" msgid="3071431025448218928">"আপোনাৰ স্ক্ৰীণত প্ৰদৰ্শন হোৱা সকলো <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> কেপশ্বাৰ কৰা আৰম্ভ কৰিব।"</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"পুনৰাই নেদেখুৱাব"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"সকলো মচক"</string>
- <!-- no translation found for manage_notifications_text (8035284146227267681) -->
- <skip />
+ <string name="manage_notifications_text" msgid="8035284146227267681">"জনানীসমূহ পৰিচালনা কৰক"</string>
<string name="dnd_suppressing_shade_text" msgid="5179021215370153526">"অসুবিধা নিদিব ম\'ডে জাননীসমূহ লুকাই ৰাখিছে"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"এতিয়াই আৰম্ভ কৰক"</string>
<string name="empty_shade_text" msgid="708135716272867002">"কোনো জাননী নাই"</string>
@@ -633,8 +629,7 @@
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"জাননীৰ নিয়ন্ত্ৰণসমূহ"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"জাননীক স্নুজ কৰাৰ বিকল্পসমূহ"</string>
- <!-- no translation found for notification_menu_snooze_action (1112254519029621372) -->
- <skip />
+ <string name="notification_menu_snooze_action" msgid="1112254519029621372">"স্নুজ কৰক"</string>
<string name="snooze_undo" msgid="6074877317002985129">"আনডু কৰক"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ৰ বাবে স্নুজ কৰক"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index ce39f23..05d3148 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -74,10 +74,8 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"স্ক্রিনশট সেভ করা হয়েছে"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"স্ক্রিনশটটি দেখতে ট্যাপ করুন"</string>
- <!-- no translation found for screenshot_failed_title (7612509838919089748) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (3637758096565605541) -->
- <skip />
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"স্ক্রিনশট সেভ করা যায়নি"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"আবার স্ক্রিনশট নেওয়ার চেষ্টা করুন"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"বেশি জায়গা নেই তাই স্ক্রিনশটটি সেভ করা যাবে না৷"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string>
@@ -348,8 +346,7 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"সূর্যাস্তে চালু হবে"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"সূর্যোদয় পর্যন্ত"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> এ চালু হবে"</string>
- <!-- no translation found for quick_settings_secondary_label_until (2749196569462600150) -->
- <skip />
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC অক্ষম করা আছে"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC সক্ষম করা আছে"</string>
@@ -433,8 +430,7 @@
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> আপনার স্ক্রীনে দেখানো সব কিছু ক্যাপচার করা শুরু করবে।"</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"আর দেখাবেন না"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"সবকিছু সাফ করুন"</string>
- <!-- no translation found for manage_notifications_text (8035284146227267681) -->
- <skip />
+ <string name="manage_notifications_text" msgid="8035284146227267681">"বিজ্ঞপ্তি পরিচালনা করুন"</string>
<string name="dnd_suppressing_shade_text" msgid="5179021215370153526">"\'বিরক্ত করবেন না\' মোড চালু আছে, তাই বিজ্ঞপ্তি লুকিয়ে ফেলা হচ্ছে"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"এখন শুরু করুন"</string>
<string name="empty_shade_text" msgid="708135716272867002">"কোনো বিজ্ঞপ্তি নেই"</string>
@@ -633,8 +629,7 @@
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"বিজ্ঞপ্তি মনে করিয়ে দেওয়ার বিকল্পগুলি"</string>
- <!-- no translation found for notification_menu_snooze_action (1112254519029621372) -->
- <skip />
+ <string name="notification_menu_snooze_action" msgid="1112254519029621372">"স্নুজ করুন"</string>
<string name="snooze_undo" msgid="6074877317002985129">"পূর্বাবস্থায় ফিরুন"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> পরে আবার মনে করানো হবে"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 5b06250..35e006e 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -504,7 +504,7 @@
<string name="volume_zen_end_now" msgid="6930243045593601084">"Isključi sada"</string>
<string name="accessibility_volume_settings" msgid="4915364006817819212">"Postavke zvuka"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Proširi"</string>
- <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Skupi"</string>
+ <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Suzi"</string>
<string name="accessibility_output_chooser" msgid="8185317493017988680">"Promijenite izlazni uređaj"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran je prikačen"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Nazad."</string>
@@ -765,9 +765,9 @@
<string name="accessibility_action_divider_top_50" msgid="6385859741925078668">"Gore 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="6201455163864841205">"Gore 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Donji ekran kao cijeli ekran"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvaput dodirnite za uređivanje."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> Dvaput dodirnite za dodavanje."</string>
- <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>. Dvaput dodirnite za odabir."</string>
+ <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dodirnite dvaput za uređivanje."</string>
+ <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> Dodirnite dvaput za dodavanje."</string>
+ <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>. Dodirnite dvaput za odabir."</string>
<string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Pomjeri <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Ukloni <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je dodan na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 58f0f7b3..586a292 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -74,10 +74,8 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"S\'està desant la captura de pantalla..."</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"S\'ha desat la captura de pantalla"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"Toca per veure la captura de pantalla"</string>
- <!-- no translation found for screenshot_failed_title (7612509838919089748) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (3637758096565605541) -->
- <skip />
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"No s\'ha pogut desar la captura de pantalla"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Prova de tornar a fer una captura de pantalla"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string>
@@ -348,8 +346,7 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"A la posta de sol"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Fins a l\'alba"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"S\'activarà a les <xliff:g id="TIME">%s</xliff:g>"</string>
- <!-- no translation found for quick_settings_secondary_label_until (2749196569462600150) -->
- <skip />
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Fins a les <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"L\'NFC està desactivada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"L\'NFC està activada"</string>
@@ -433,8 +430,7 @@
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> començarà a gravar tot el que es mostri a la pantalla."</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"No ho tornis a mostrar"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Esborra-ho tot"</string>
- <!-- no translation found for manage_notifications_text (8035284146227267681) -->
- <skip />
+ <string name="manage_notifications_text" msgid="8035284146227267681">"Gestiona les notificacions"</string>
<string name="dnd_suppressing_shade_text" msgid="5179021215370153526">"El mode No molestis està amagant notificacions"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Comença ara"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Cap notificació"</string>
@@ -633,8 +629,7 @@
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"controls de notificació"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"opcions per posposar la notificació"</string>
- <!-- no translation found for notification_menu_snooze_action (1112254519029621372) -->
- <skip />
+ <string name="notification_menu_snooze_action" msgid="1112254519029621372">"Posposa"</string>
<string name="snooze_undo" msgid="6074877317002985129">"DESFÉS"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"S\'ha posposat <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index b6b79cb..cb05035 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -75,7 +75,7 @@
<string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot gespeichert"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"Tippe, um deinen Screenshot anzusehen"</string>
<string name="screenshot_failed_title" msgid="7612509838919089748">"Screenshot konnte nicht gespeichert werden"</string>
- <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Erstelle einen weiteren Screenshot"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Versuche noch einmal, den Screenshot zu erstellen"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Die App oder deine Organisation lässt das Erstellen von Screenshots nicht zu"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 73b0bba..b4de7f6 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -531,18 +531,15 @@
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ring"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrate"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Mute"</string>
- <!-- no translation found for qs_status_phone_vibrate (204362991135761679) -->
- <skip />
- <!-- no translation found for qs_status_phone_muted (5437668875879171548) -->
- <skip />
+ <string name="qs_status_phone_vibrate" msgid="204362991135761679">"Phone on vibrate"</string>
+ <string name="qs_status_phone_muted" msgid="5437668875879171548">"Phone muted"</string>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s. Tap to set to vibrate."</string>
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tap to mute."</string>
<string name="volume_dialog_title" msgid="7272969888820035876">"%s volume controls"</string>
- <!-- no translation found for volume_dialog_ringer_guidance_ring (3360373718388509040) -->
- <skip />
+ <string name="volume_dialog_ringer_guidance_ring" msgid="3360373718388509040">"Calls and notifications will ring (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
<string name="output_title" msgid="5355078100792942802">"Media output"</string>
<string name="output_calls_title" msgid="8717692905017206161">"Phone call output"</string>
<string name="output_none_found" msgid="5544982839808921091">"No devices found"</string>
@@ -693,8 +690,7 @@
<string name="battery" msgid="7498329822413202973">"Battery"</string>
<string name="clock" msgid="7416090374234785905">"Clock"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
- <!-- no translation found for accessibility_long_click_tile (6687350750091842525) -->
- <skip />
+ <string name="accessibility_long_click_tile" msgid="6687350750091842525">"Open settings"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
<string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index f0faae8..b671dfe 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -851,7 +851,7 @@
<string name="auto_saver_title" msgid="1217959994732964228">"Sakatu bateria-aurrezlea noiz aktibatu antolatzeko"</string>
<string name="auto_saver_text" msgid="6324376061044218113">"Aktibatu automatikoki bateriaren %% <xliff:g id="PERCENTAGE">%d</xliff:g> gelditzen denean"</string>
<string name="no_auto_saver_action" msgid="8086002101711328500">"Ez"</string>
- <string name="auto_saver_enabled_title" msgid="6726474226058316862">"Bateria-aurrezle aktibatu da"</string>
+ <string name="auto_saver_enabled_title" msgid="6726474226058316862">"Bateria-aurrezlea aktibatu da"</string>
<string name="auto_saver_enabled_text" msgid="874711029884777579">"Bateria-aurrezlea automatikoki aktibatuko da bateriaren %% <xliff:g id="PERCENTAGE">%d</xliff:g> gelditzen denean."</string>
<string name="open_saver_setting_action" msgid="8314624730997322529">"Ezarpenak"</string>
<string name="auto_saver_okay_action" msgid="2701221740227683650">"Ados"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index b6349cd..c42206a 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -74,10 +74,8 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"સ્ક્રીનશૉટ સાચવ્યો"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"તમારા સ્ક્રીનશૉટને જોવા માટે ટૅપ કરો"</string>
- <!-- no translation found for screenshot_failed_title (7612509838919089748) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (3637758096565605541) -->
- <skip />
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"સ્ક્રીનશૉટ સાચવી શક્યાં નથી"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ફરીથી સ્ક્રીનશૉટ લેવાનો પ્રયાસ કરો"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"મર્યાદિત સ્ટોરેજ સ્પેસને કારણે સ્ક્રીનશૉટ સાચવી શકાતો નથી"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ફાઇલ ટ્રાન્સફર વિકલ્પો"</string>
@@ -348,8 +346,7 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"સૂર્યાસ્ત વખતે"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"સૂર્યોદય સુધી"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે"</string>
- <!-- no translation found for quick_settings_secondary_label_until (2749196569462600150) -->
- <skip />
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> સુધી"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC અક્ષમ કરેલ છે"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC સક્ષમ કરેલ છે"</string>
@@ -433,8 +430,7 @@
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> તમારી સ્ક્રીન પર જે પ્રદર્શિત થાય છે તે દરેક વસ્તુને કેપ્ચર કરવાનું પ્રારંભ કરશે."</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"ફરીથી બતાવશો નહીં"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"બધુ સાફ કરો"</string>
- <!-- no translation found for manage_notifications_text (8035284146227267681) -->
- <skip />
+ <string name="manage_notifications_text" msgid="8035284146227267681">"સૂચનાઓને મેનેજ કરો"</string>
<string name="dnd_suppressing_shade_text" msgid="5179021215370153526">"ખલેલ પાડશો નહીં નોટિફિકેશન છુપાવી રહ્યું છે"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"હવે પ્રારંભ કરો"</string>
<string name="empty_shade_text" msgid="708135716272867002">"કોઈ સૂચનાઓ નથી"</string>
@@ -633,8 +629,7 @@
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"સૂચના નિયંત્રણો"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"સૂચના સ્નૂઝ કરવાના વિકલ્પો"</string>
- <!-- no translation found for notification_menu_snooze_action (1112254519029621372) -->
- <skip />
+ <string name="notification_menu_snooze_action" msgid="1112254519029621372">"સ્નૂઝ કરો"</string>
<string name="snooze_undo" msgid="6074877317002985129">"પૂર્વવત્ કરો"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> માટે સ્નૂઝ કરો"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f2b281c..13c49f7 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -74,10 +74,8 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"स्क्रीनशॉट सेव किया गया"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"अपना स्क्रीनशॉट देखने के लिए टैप करें"</string>
- <!-- no translation found for screenshot_failed_title (7612509838919089748) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (3637758096565605541) -->
- <skip />
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"स्क्रीनशॉट सेव नहीं किया जा सका"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"स्क्रीनशॉट दोबारा लेने की कोशिश करें"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"मेमोरी कम होने की वजह से स्क्रीनशॉट सेव नहीं किया जा सका"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ऐप्लिकेशन या आपका संगठन स्क्रीनशॉट लेने की अनुमति नहीं देता"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB फ़ाइल स्थानांतरण विकल्प"</string>
@@ -348,8 +346,7 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"शाम को चालू की जाएगी"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"सुबह तक चालू रहेगी"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> पर चालू की जाएगी"</string>
- <!-- no translation found for quick_settings_secondary_label_until (2749196569462600150) -->
- <skip />
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> तक"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC बंद है"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC चालू है"</string>
@@ -433,8 +430,7 @@
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपके स्क्रीन पर दिखाई देने वाली हर सामग्री को कैप्चर करना शुरू कर देगी."</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"फिर से न दिखाएं"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"सभी साफ़ करें"</string>
- <!-- no translation found for manage_notifications_text (8035284146227267681) -->
- <skip />
+ <string name="manage_notifications_text" msgid="8035284146227267681">"सूचनाएं प्रबंधित करें"</string>
<string name="dnd_suppressing_shade_text" msgid="5179021215370153526">"परेशान न करें सुविधा चालू होने की वजह से सूचनाएं नहीं दिखाई जा रही हैं"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"अब शुरू करें"</string>
<string name="empty_shade_text" msgid="708135716272867002">"कोई सूचना नहीं मिली"</string>
@@ -633,8 +629,7 @@
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रण"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना को स्नूज़ (थोड़ी देर के लिए चुप करना) करने के विकल्प"</string>
- <!-- no translation found for notification_menu_snooze_action (1112254519029621372) -->
- <skip />
+ <string name="notification_menu_snooze_action" msgid="1112254519029621372">"स्नूज़ करें"</string>
<string name="snooze_undo" msgid="6074877317002985129">"पहले जैसा करें"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> के लिए याद दिलाया गया"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index f3e15ec..7a19ad0 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -74,10 +74,8 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"Vistar skjámynd…"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"Skjámynd vistuð"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"Ýttu til skoða skjámyndina"</string>
- <!-- no translation found for screenshot_failed_title (7612509838919089748) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (3637758096565605541) -->
- <skip />
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"Ekki var hægt að vista skjámynd"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Prófaðu að taka skjámynd aftur"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Valkostir USB-skráaflutnings"</string>
@@ -348,8 +346,7 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Kveikt við sólsetur"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Til sólarupprásar"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Kveikt klukkan <xliff:g id="TIME">%s</xliff:g>"</string>
- <!-- no translation found for quick_settings_secondary_label_until (2749196569462600150) -->
- <skip />
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Til klukkan <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Slökkt á NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Kveikt á NFC"</string>
@@ -433,8 +430,7 @@
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> mun fanga allt sem birtist á skjánum."</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"Ekki sýna þetta aftur"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Hreinsa allt"</string>
- <!-- no translation found for manage_notifications_text (8035284146227267681) -->
- <skip />
+ <string name="manage_notifications_text" msgid="8035284146227267681">"Stjórna tilkynningum"</string>
<string name="dnd_suppressing_shade_text" msgid="5179021215370153526">"„Ónáðið ekki“ felur tilkynningar"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"Byrja núna"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Engar tilkynningar"</string>
@@ -633,8 +629,7 @@
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"tilkynningastýringar"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"þöggunarstillingar tilkynninga"</string>
- <!-- no translation found for notification_menu_snooze_action (1112254519029621372) -->
- <skip />
+ <string name="notification_menu_snooze_action" msgid="1112254519029621372">"Fresta"</string>
<string name="snooze_undo" msgid="6074877317002985129">"AFTURKALLA"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Þaggað í <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 7e9d830..02b285f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -53,8 +53,8 @@
<string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth con tethering"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura metodi di immissione"</string>
<string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastiera fisica"</string>
- <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vuoi consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
- <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vuoi consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
+ <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
<string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
<string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
<string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nessuna app installata funziona con questo accessorio USB. Altre info su <xliff:g id="URL">%1$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 19b4b5b..eff2a09 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -74,10 +74,8 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ କରାଯାଉଛି…"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇଛି"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"ସ୍କ୍ରୀନଶଟ୍ ଦେଖିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for screenshot_failed_title (7612509838919089748) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (3637758096565605541) -->
- <skip />
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"ସ୍କ୍ରୀନ୍ଶଟ୍ ସେଭ୍ କରିହେବ ନାହିଁ"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ପୁଣିଥରେ ସ୍କ୍ରୀନ୍ଶଟ୍ ନେବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ସୀମିତ ଷ୍ଟୋରେଜ୍ ସ୍ପେସ୍ ହେତୁ ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇପାରିବ ନାହିଁ"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ଆପ୍ କିମ୍ବା ସଂସ୍ଥା ଦ୍ୱାରା ସ୍କ୍ରୀନଶଟ୍ ନେବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ଫାଇଲ୍ ଟ୍ରାନ୍ସଫର୍ର ବିକଳ୍ପ"</string>
@@ -348,8 +346,7 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"ସୂର୍ଯ୍ୟାସ୍ତ ବେଳେ ଅନ୍ ହେବ"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"ସୂର୍ଯ୍ୟୋଦୟ ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>ରେ ଅନ୍ ହେବ"</string>
- <!-- no translation found for quick_settings_secondary_label_until (2749196569462600150) -->
- <skip />
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ସକ୍ଷମ କରାଯାଇଛି"</string>
@@ -433,8 +430,7 @@
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ଆପଣଙ୍କ ସ୍କ୍ରୀନ୍ରେ ପ୍ରଦର୍ଶିତ ହେଉଥିବା ସମସ୍ତ ବସ୍ତୁକୁ କ୍ୟାପଚର୍ କରିବା ଆରମ୍ଭ ହୋଇଯିବ।"</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"ପୁଣି ଦେଖାନ୍ତୁ ନାହିଁ"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ସମସ୍ତ ଖାଲି କରନ୍ତୁ"</string>
- <!-- no translation found for manage_notifications_text (8035284146227267681) -->
- <skip />
+ <string name="manage_notifications_text" msgid="8035284146227267681">"ବିଜ୍ଞପ୍ତି ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="dnd_suppressing_shade_text" msgid="5179021215370153526">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ମୋଡ୍ ଅନ୍ ଥିବାଯୋଗୁଁ ବିଜ୍ଞପ୍ତି ଲୁଚାଇ ଦିଆଯାଉଛି"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ବର୍ତ୍ତମାନ ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="empty_shade_text" msgid="708135716272867002">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
@@ -633,8 +629,7 @@
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ବିଜ୍ଞପ୍ତି ନିୟନ୍ତ୍ରଣ"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"ବିଜ୍ଞପ୍ତି ସ୍ନୁଜ୍ ବିକଳ୍ପ"</string>
- <!-- no translation found for notification_menu_snooze_action (1112254519029621372) -->
- <skip />
+ <string name="notification_menu_snooze_action" msgid="1112254519029621372">"ସ୍ନୁଜ୍"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ପୂର୍ବାବସ୍ଥାକୁ ଫେରାଇ ଆଣନ୍ତୁ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ପାଇଁ ସ୍ନୁଜ୍ କରାଗଲା"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index cf0dae5..de39f4b 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -74,7 +74,7 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"A guardar captura de ecrã..."</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"Captura de ecrã guardada"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"Toque para ver a captura de ecrã."</string>
- <string name="screenshot_failed_title" msgid="7612509838919089748">"Não foi possível gravar a captura de ecrã"</string>
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"Não foi possível guardar a captura de ecrã"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Experimente voltar a efetuar a captura de ecrã."</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"A aplicação ou a sua entidade não permitem tirar capturas de ecrã"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 31c44d2..bf48c26 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -358,7 +358,7 @@
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"Модуль NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Модуль NFC отключен"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Модуль NFC включен"</string>
- <string name="recents_empty_message" msgid="808480104164008572">"Недавних приложений нет"</string>
+ <string name="recents_empty_message" msgid="808480104164008572">"Здесь пока ничего нет."</string>
<string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Вы очистили всё"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Заблокировать в приложении"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 8b341c0..cb215c1 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -74,10 +74,8 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"اسکرین شاٹ محفوظ ہو گیا"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"اپنا اسکرین شاٹ دیکھنے کیلئے تھپتھپائیں"</string>
- <!-- no translation found for screenshot_failed_title (7612509838919089748) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (3637758096565605541) -->
- <skip />
+ <string name="screenshot_failed_title" msgid="7612509838919089748">"اسکرین شاٹ کو محفوظ نہیں کیا جا سکا"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"دوبارہ اسکرین شاٹ لینے کی کوشش کریں"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ کو محفوظ نہیں کیا جا سکتا"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB فائل منتقل کرنیکے اختیارات"</string>
@@ -348,8 +346,7 @@
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"غروب آفتاب کے وقت آن ہوگی"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"طلوع آفتاب تک"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"آن ہوگی بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
- <!-- no translation found for quick_settings_secondary_label_until (2749196569462600150) -->
- <skip />
+ <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"<xliff:g id="TIME">%s</xliff:g> تک"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC غیر فعال ہے"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC فعال ہے"</string>
@@ -433,8 +430,7 @@
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> آپ کی اسکرین پر ڈسپلے ہونے والی ہر چیز کو کیپچر کرنا شروع کر دیگی۔"</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"دوبارہ نہ دکھائیں"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"سبھی کو صاف کریں"</string>
- <!-- no translation found for manage_notifications_text (8035284146227267681) -->
- <skip />
+ <string name="manage_notifications_text" msgid="8035284146227267681">"اطلاعات کا نظم کریں"</string>
<string name="dnd_suppressing_shade_text" msgid="5179021215370153526">"\'ڈسٹرب نہ کریں\' اطلاعات کو چھپا رہی ہے"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ابھی شروع کریں"</string>
<string name="empty_shade_text" msgid="708135716272867002">"کوئی اطلاعات نہیں ہیں"</string>
@@ -633,8 +629,7 @@
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"اطلاع کے کنٹرولز"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"اطلاع اسنوز کرنے کے اختیارات"</string>
- <!-- no translation found for notification_menu_snooze_action (1112254519029621372) -->
- <skip />
+ <string name="notification_menu_snooze_action" msgid="1112254519029621372">"اسنوز کریں"</string>
<string name="snooze_undo" msgid="6074877317002985129">"کالعدم کریں"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> کیلئے اسنوز کیا گیا"</string>
<plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
diff --git a/packages/SystemUI/res/values/attrs_car.xml b/packages/SystemUI/res/values/attrs_car.xml
index 5e4bd79..335ae44 100644
--- a/packages/SystemUI/res/values/attrs_car.xml
+++ b/packages/SystemUI/res/values/attrs_car.xml
@@ -19,6 +19,8 @@
<declare-styleable name="CarFacetButton">
<!-- icon to be rendered (drawable) -->
<attr name="icon" format="reference"/>
+ <!-- icon to be rendered when in selected state -->
+ <attr name="selectedIcon" format="reference"/>
<!-- intent to start when button is click -->
<attr name="intent" format="string"/>
<!-- intent to start when a long press has happened -->
@@ -45,6 +47,12 @@
<attr name="longIntent" format="string"/>
<!-- start the intent as a broad cast instead of an activity if true-->
<attr name="broadcast" format="boolean"/>
+ <!-- Alpha value to used when in selected state. Defaults 1f -->
+ <attr name="selectedAlpha" format="float" />
+ <!-- Alpha value to used when in un-selected state. Defaults 0.7f -->
+ <attr name="unselectedAlpha" format="float" />
+ <!-- icon to be rendered when in selected state -->
+ <attr name="selectedIcon" format="reference"/>
</declare-styleable>
<!-- Custom attributes to configure hvac values -->
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 6caed61..2b91891 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -17,18 +17,14 @@
-->
<resources>
<dimen name="car_margin">148dp</dimen>
+ <dimen name="car_margin_standard">112dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_image_top">24dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_name_top">24dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_name_bottom">20dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen>
- <dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen>
- <dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen>
- <dimen name="car_fullscreen_user_pod_image_avatar_height">192dp</dimen>
- <dimen name="car_fullscreen_user_pod_width">264dp</dimen>
+ <!-- TODO replace with car support lib sizes when available -->
+ <dimen name="car_fullscreen_user_pod_icon_text_size">32sp</dimen>
+ <dimen name="car_fullscreen_user_pod_width">243dp</dimen>
<dimen name="car_fullscreen_user_pod_height">356dp</dimen>
- <dimen name="car_fullscreen_user_pod_name_text_size">40sp</dimen> <!-- B1 -->
- <dimen name="car_fullscreen_user_pod_device_text_size">@dimen/car_body2_size</dimen>
+ <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
+ <dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
<dimen name="car_navigation_button_width">64dp</dimen>
<dimen name="car_navigation_bar_width">760dp</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 0e92c60..d45c427 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -98,5 +98,8 @@
<item type="id" name="status_bar_view_state_tag" />
<item type="id" name="display_cutout" />
+
+ <!-- Optional cancel button on Keyguard -->
+ <item type="id" name="cancel_button"/>
</resources>
diff --git a/packages/SystemUI/res/values/integers_car.xml b/packages/SystemUI/res/values/integers_car.xml
index a462576..7513fd4 100644
--- a/packages/SystemUI/res/values/integers_car.xml
+++ b/packages/SystemUI/res/values/integers_car.xml
@@ -17,4 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<integer name="car_user_switcher_anim_cascade_delay_ms">27</integer>
+ <!-- Full screen user switcher column number TODO: move to support library-->
+ <integer name="user_fullscreen_switcher_num_col">3</integer>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index da6ecc3..c1e1873 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -366,10 +366,10 @@
<string name="data_connection_3g">3G</string>
<!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] -->
- <string name="data_connection_3_5g">3.5G</string>
+ <string name="data_connection_3_5g">H</string>
<!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] -->
- <string name="data_connection_3_5g_plus">3.5G+</string>
+ <string name="data_connection_3_5g_plus">H+</string>
<!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] -->
<string name="data_connection_4g">4G</string>
@@ -384,7 +384,7 @@
<string name="data_connection_lte_plus">LTE+</string>
<!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] -->
- <string name="data_connection_cdma">CDMA</string>
+ <string name="data_connection_cdma">1X</string>
<!-- Content description of the roaming data connection type. [CHAR LIMIT=NONE] -->
<string name="data_connection_roaming">Roaming</string>
diff --git a/packages/SystemUI/res/values/strings_car.xml b/packages/SystemUI/res/values/strings_car.xml
index 658eb4f..0b57ff8 100644
--- a/packages/SystemUI/res/values/strings_car.xml
+++ b/packages/SystemUI/res/values/strings_car.xml
@@ -17,6 +17,10 @@
*/
-->
<resources>
- <string name="unknown_user_label">Unknown</string>
- <string name="start_driving">Start Driving</string>
+ <!-- Name of Guest Profile. [CHAR LIMIT=30] -->
+ <string name="car_guest">Guest</string>
+ <!-- Name of Add User Profile. [CHAR LIMIT=30] -->
+ <string name="car_add_user">Add User</string>
+ <!-- Default name of the new user created. [CHAR LIMIT=30] -->
+ <string name="car_new_user">New User</string>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
index 20d1418..78b1b2614 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java
@@ -15,10 +15,13 @@
*/
package com.android.systemui.shared.recents.model;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
+
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -108,10 +111,12 @@
}
if (desc.getIconResource() != 0) {
try {
- Context packageContext = mContext.createPackageContextAsUser(
- taskKey.getPackageName(), 0, UserHandle.of(userId));
- return createBadgedDrawable(packageContext.getDrawable(desc.getIconResource()),
- userId, desc);
+ PackageManager pm = mContext.getPackageManager();
+ ApplicationInfo appInfo = pm.getApplicationInfo(taskKey.getPackageName(),
+ MATCH_ANY_USER);
+ Resources res = pm.getResourcesForApplication(appInfo);
+ return createBadgedDrawable(res.getDrawable(desc.getIconResource(), null), userId,
+ desc);
} catch (Resources.NotFoundException|PackageManager.NameNotFoundException e) {
Log.e(TAG, "Could not find icon drawable from resource", e);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
index 6fa7db3..32e4bbf 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
@@ -18,23 +18,24 @@
import android.app.AppGlobals;
import android.content.ComponentName;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.RemoteException;
-import java.util.ArrayList;
import java.util.List;
public class PackageManagerWrapper {
- private static final String TAG = "PackageManagerWrapper";
-
private static final PackageManagerWrapper sInstance = new PackageManagerWrapper();
private static final IPackageManager mIPackageManager = AppGlobals.getPackageManager();
+ public static final String ACTION_PREFERRED_ACTIVITY_CHANGED =
+ Intent.ACTION_PREFERRED_ACTIVITY_CHANGED;
+
public static PackageManagerWrapper getInstance() {
return sInstance;
}
@@ -53,40 +54,15 @@
}
/**
- * @return true if the packageName belongs to the current preferred home app on the device.
- *
- * If will also return false if there are multiple home apps and the user has not picked any
- * preferred home, in which case the user would see a disambiguation screen on going to home.
+ * Report the set of 'Home' activity candidates, plus (if any) which of them
+ * is the current "always use this one" setting.
*/
- public boolean isDefaultHomeActivity(String packageName) {
- List<ResolveInfo> allHomeCandidates = new ArrayList<>();
- ComponentName home;
+ public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
try {
- home = mIPackageManager.getHomeActivities(allHomeCandidates);
+ return mIPackageManager.getHomeActivities(allHomeCandidates);
} catch (RemoteException e) {
e.printStackTrace();
- return false;
+ return null;
}
-
- if (home != null && packageName.equals(home.getPackageName())) {
- return true;
- }
-
- // Find the launcher with the highest priority and return that component if there are no
- // other home activity with the same priority.
- int lastPriority = Integer.MIN_VALUE;
- ComponentName lastComponent = null;
- final int size = allHomeCandidates.size();
- for (int i = 0; i < size; i++) {
- final ResolveInfo ri = allHomeCandidates.get(i);
- if (ri.priority > lastPriority) {
- lastComponent = ri.activityInfo.getComponentName();
- lastPriority = ri.priority;
- } else if (ri.priority == lastPriority) {
- // Two components found with same priority.
- lastComponent = null;
- }
- }
- return lastComponent != null && packageName.equals(lastComponent.getPackageName());
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java
new file mode 100644
index 0000000..bf88a29
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java
@@ -0,0 +1,33 @@
+/*
+ * 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.systemui.shared.system;
+
+import android.view.ThreadedRenderer;
+
+/**
+ * @see ThreadedRenderer
+ */
+public class ThreadedRendererCompat {
+
+ public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
+ public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
+ public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
+
+ public static void setContextPriority(int priority) {
+ ThreadedRenderer.setContextPriority(priority);
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
index c82c519..9975c41 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
@@ -101,6 +101,11 @@
return this;
}
+ public TransactionCompat setEarlyWakeup() {
+ mTransaction.setEarlyWakeup();
+ return this;
+ }
+
public TransactionCompat setColor(SurfaceControlCompat surfaceControl, float[] color) {
mTransaction.setColor(surfaceControl.mSurfaceControl, color);
return this;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index c1cff9e..adb2460 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -107,6 +107,13 @@
new View[]{
null, mEcaView, null
}};
+
+ View cancelBtn = findViewById(R.id.cancel_button);
+ if (cancelBtn != null) {
+ cancelBtn.setOnClickListener(view -> {
+ mCallback.reset();
+ });
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 75c52d8..7cc37c4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -205,6 +205,13 @@
}
});
+ View cancelBtn = findViewById(R.id.cancel_button);
+ if (cancelBtn != null) {
+ cancelBtn.setOnClickListener(view -> {
+ mCallback.reset();
+ });
+ }
+
// If there's more than one IME, enable the IME switcher button
updateSwitchImeButton();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 651831e..174dcab 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -157,6 +157,13 @@
if (button != null) {
button.setCallback(this);
}
+
+ View cancelBtn = findViewById(R.id.cancel_button);
+ if (cancelBtn != null) {
+ cancelBtn.setOnClickListener(view -> {
+ mCallback.reset();
+ });
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index ce16efb..ff3af17 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -216,8 +216,7 @@
}
public void refreshTime() {
- mClockView.setFormat12Hour(Patterns.clockView12);
- mClockView.setFormat24Hour(Patterns.clockView24);
+ mClockView.refresh();
}
private void refresh() {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index a4f8d8c..b8a57bf 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -444,13 +444,7 @@
final Surface surface = getSurfaceHolder().getSurface();
surface.hwuiDestroy();
- mLoader = new AsyncTask<Void, Void, Bitmap>() {
- @Override
- protected Bitmap doInBackground(Void... params) {
- mWallpaperManager.forgetLoadedWallpaper();
- return null;
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ mWallpaperManager.forgetLoadedWallpaper();
}
private void scheduleUnloadWallpaper() {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 0ba26e9..c01cafa 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -25,6 +25,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.Dependency.DependencyProvider;
import com.android.systemui.classifier.FalsingManager;
@@ -101,12 +102,13 @@
dismissCallbackRegistry, FalsingManager.getInstance(context));
}
- public ScrimController createScrimController(LightBarController lightBarController,
- ScrimView scrimBehind, ScrimView scrimInFront, LockscreenWallpaper lockscreenWallpaper,
+ public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
+ LockscreenWallpaper lockscreenWallpaper, Consumer<Float> scrimBehindAlphaListener,
+ Consumer<GradientColors> scrimInFrontColorListener,
Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
AlarmManager alarmManager) {
- return new ScrimController(lightBarController, scrimBehind, scrimInFront,
- scrimVisibleListener, dozeParameters, alarmManager);
+ return new ScrimController(scrimBehind, scrimInFront, scrimBehindAlphaListener,
+ scrimInFrontColorListener, scrimVisibleListener, dozeParameters, alarmManager);
}
public NotificationIconAreaController createNotificationIconAreaController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 778e630..c390764 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -109,7 +109,11 @@
switch (newState) {
case DOZE_AOD:
if (oldState == DOZE_AOD_PAUSED) {
+ // Whenever turning on the display, it's necessary to push a new frame.
+ // The display buffers will be empty and need to be filled.
mHost.dozeTimeTick();
+ // The first frame may arrive when the display isn't ready yet.
+ mHandler.postDelayed(mHost::dozeTimeTick, 100);
}
scheduleTimeTick();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
index 6921836..d1d6609 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
@@ -165,7 +166,7 @@
title.setSelected(true);
final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
- if (subtitleText == null) {
+ if (TextUtils.isEmpty(subtitleText)) {
subtitle.setVisibility(View.GONE);
} else {
subtitle.setVisibility(View.VISIBLE);
@@ -173,11 +174,11 @@
}
final CharSequence descriptionText = mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION);
- if (descriptionText == null) {
- subtitle.setVisibility(View.VISIBLE);
+ if (TextUtils.isEmpty(descriptionText)) {
description.setVisibility(View.GONE);
} else {
- description.setText(mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION));
+ description.setVisibility(View.VISIBLE);
+ description.setText(descriptionText);
}
negative.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index a70b358..40ce69b 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -514,7 +514,7 @@
autoTriggerThreshold = 15;
}
- BatterySaverUtils.scheduleAutoBatterySaver(mContext, autoTriggerThreshold);
+ BatterySaverUtils.ensureAutoBatterySaver(mContext, autoTriggerThreshold);
showAutoSaverEnabledConfirmation();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 7161463..a9455f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -16,17 +16,19 @@
package com.android.systemui.qs;
+import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
-import com.android.settingslib.Utils;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.statusbar.CommandQueue;
/**
* Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
@@ -48,6 +50,7 @@
private View mStatusBarBackground;
private int mSideMargins;
+ private boolean mQsDisabled;
public QSContainerImpl(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -85,6 +88,7 @@
}
updateResources();
+ mSizePoint.set(0, 0); // Will be retrieved on next measure pass.
}
@Override
@@ -96,6 +100,16 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mQsDisabled) {
+ // Only show the status bar contents in QQS header when QS is disabled.
+ mHeader.measure(widthMeasureSpec, heightMeasureSpec);
+ LayoutParams layoutParams = (LayoutParams) mHeader.getLayoutParams();
+ int height = layoutParams.topMargin + layoutParams.bottomMargin
+ + mHeader.getMeasuredHeight();
+ super.onMeasure(
+ widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ return;
+ }
// Since we control our own bottom, be whatever size we want.
// Otherwise the QSPanel ends up with 0 height when the window is only the
// size of the status bar.
@@ -110,9 +124,8 @@
// QSCustomizer will always be the height of the screen, but do this after
// other measuring to avoid changing the height of the QS.
- getDisplay().getRealSize(mSizePoint);
mQSCustomizer.measure(widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(mSizePoint.y, MeasureSpec.EXACTLY));
+ MeasureSpec.makeMeasureSpec(getDisplayHeight(), MeasureSpec.EXACTLY));
}
@Override
@@ -121,6 +134,15 @@
updateExpansion();
}
+ public void disable(int state1, int state2, boolean animate) {
+ final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
+ if (disabled == mQsDisabled) return;
+ mQsDisabled = disabled;
+ mBackgroundGradient.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
+ mQSPanel.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
+ mQSFooter.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
+ }
+
private void updateResources() {
LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
@@ -175,4 +197,11 @@
lp.rightMargin = mSideMargins;
lp.leftMargin = mSideMargins;
}
+
+ private int getDisplayHeight() {
+ if (mSizePoint.y == 0) {
+ getDisplay().getRealSize(mSizePoint);
+ }
+ return mSizePoint.y;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 3f3cea2..6c7eda7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -69,4 +69,6 @@
*/
@Nullable
View getExpandView();
+
+ default void disable(int state1, int state2, boolean animate) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index 0fa6597..cf549fa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -47,10 +47,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.R.dimen;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.TouchAnimator.Builder;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
import com.android.systemui.statusbar.phone.SettingsButton;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -62,8 +60,7 @@
import com.android.systemui.tuner.TunerService;
public class QSFooterImpl extends FrameLayout implements QSFooter,
- OnClickListener, OnUserInfoChangedListener, EmergencyListener,
- SignalCallback, CommandQueue.Callbacks {
+ OnClickListener, OnUserInfoChangedListener, EmergencyListener, SignalCallback {
private ActivityStarter mActivityStarter;
private UserInfoController mUserInfoController;
@@ -211,16 +208,9 @@
}
@Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
- }
-
- @Override
@VisibleForTesting
public void onDetachedFromWindow() {
setListening(false);
- SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
super.onDetachedFromWindow();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 018a635..cb068e3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -14,9 +14,12 @@
package com.android.systemui.qs;
+import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Fragment;
+import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
@@ -35,12 +38,14 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.R.id;
+import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
import com.android.systemui.statusbar.stack.StackStateAnimator;
-public class QSFragment extends Fragment implements QS {
+public class QSFragment extends Fragment implements QS, CommandQueue.Callbacks {
private static final String TAG = "QS";
private static final boolean DEBUG = false;
private static final String EXTRA_EXPANDED = "expanded";
@@ -65,6 +70,7 @@
private int mLayoutDirection;
private QSFooter mFooter;
private float mLastQSExpansion = -1;
+ private boolean mQsDisabled;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -176,6 +182,17 @@
}
}
+ @Override
+ public void disable(int state1, int state2, boolean animate) {
+ final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
+ if (disabled == mQsDisabled) return;
+ mQsDisabled = disabled;
+ mContainer.disable(state1, state2, animate);
+ mHeader.disable(state1, state2, animate);
+ mFooter.disable(state1, state2, animate);
+ updateQsState();
+ }
+
private void updateQsState() {
final boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling
|| mHeaderAnimating;
@@ -189,6 +206,9 @@
mFooter.setVisibility((mQsExpanded || !mKeyguardShowing || mHeaderAnimating)
? View.VISIBLE
: View.INVISIBLE);
+ if (mQsDisabled) {
+ mFooter.setVisibility(View.GONE);
+ }
mFooter.setExpanded((mKeyguardShowing && !mHeaderAnimating)
|| (mQsExpanded && !mStackScrollerOverscrolling));
mQSPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
@@ -258,6 +278,12 @@
mHeader.setListening(listening);
mFooter.setListening(listening);
mQSPanel.setListening(mListening && mQsExpanded);
+ if (listening) {
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
+ } else {
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class)
+ .removeCallbacks(this);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 70bfad1..e2af90d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -68,7 +68,7 @@
* battery) and also contains the {@link QuickQSPanel} along with some of the panel's inner
* contents.
*/
-public class QuickStatusBarHeader extends RelativeLayout implements CommandQueue.Callbacks,
+public class QuickStatusBarHeader extends RelativeLayout implements
View.OnClickListener, NextAlarmController.NextAlarmChangeCallback {
private static final String TAG = "QuickStatusBarHeader";
private static final boolean DEBUG = false;
@@ -249,8 +249,9 @@
com.android.internal.R.dimen.quick_qs_offset_height);
mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
- getLayoutParams().height =
- resources.getDimensionPixelSize(com.android.internal.R.dimen.quick_qs_total_height);
+ getLayoutParams().height = resources.getDimensionPixelSize(mQsDisabled
+ ? com.android.internal.R.dimen.quick_qs_offset_height
+ : com.android.internal.R.dimen.quick_qs_total_height);
setLayoutParams(getLayoutParams());
updateStatusIconAlphaAnimator();
@@ -320,20 +321,18 @@
TOOLTIP_NOT_YET_SHOWN_COUNT);
}
- @Override
public void disable(int state1, int state2, boolean animate) {
final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
mHeaderQsPanel.setDisabledByPolicy(disabled);
- final int rawHeight = (int) getResources().getDimension(
- com.android.internal.R.dimen.quick_qs_total_height);
- getLayoutParams().height = disabled ? (rawHeight - mHeaderQsPanel.getHeight()) : rawHeight;
+ mHeaderTextContainerView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
+ mQuickQsStatusIcons.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
+ updateResources();
}
@Override
public void onAttachedToWindow() {
- SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
requestApplyInsets();
}
@@ -354,7 +353,6 @@
@VisibleForTesting
public void onDetachedFromWindow() {
setListening(false);
- SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
Dependency.get(StatusBarIconController.class).removeIconGroup(mIconManager);
super.onDetachedFromWindow();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index 23d3ebbb..24b5a34 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -29,7 +29,6 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSPanel;
-import com.android.systemui.statusbar.car.UserGridView;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.UserInfoController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 0ee6d1f..da21aa5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -20,21 +20,20 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Fragment;
+import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.GridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFooter;
-import com.android.systemui.statusbar.car.PageIndicator;
-import com.android.systemui.statusbar.car.UserGridView;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.car.UserGridRecyclerView;
import java.util.ArrayList;
import java.util.List;
@@ -45,14 +44,12 @@
* status bar, and a static row with access to the user switcher and settings.
*/
public class CarQSFragment extends Fragment implements QS {
- private ViewGroup mPanel;
private View mHeader;
private View mUserSwitcherContainer;
private CarQSFooter mFooter;
private View mFooterUserName;
private View mFooterExpandIcon;
- private UserGridView mUserGridView;
- private PageIndicator mPageIndicator;
+ private UserGridRecyclerView mUserGridView;
private AnimatorSet mAnimatorSet;
private UserSwitchCallback mUserSwitchCallback;
@@ -65,7 +62,6 @@
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- mPanel = (ViewGroup) view;
mHeader = view.findViewById(R.id.header);
mFooter = view.findViewById(R.id.qs_footer);
mFooterUserName = mFooter.findViewById(R.id.user_name);
@@ -75,16 +71,15 @@
updateUserSwitcherHeight(0);
- mUserGridView = view.findViewById(R.id.user_grid);
- mUserGridView.init(null, Dependency.get(UserSwitcherController.class),
- false /* overrideAlpha */);
-
- mPageIndicator = view.findViewById(R.id.user_switcher_page_indicator);
- mPageIndicator.setupWithViewPager(mUserGridView);
+ Context context = getContext();
+ mUserGridView = mUserSwitcherContainer.findViewById(R.id.user_grid);
+ GridLayoutManager layoutManager = new GridLayoutManager(context,
+ context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
+ mUserGridView.setLayoutManager(layoutManager);
+ mUserGridView.buildAdapter();
mUserSwitchCallback = new UserSwitchCallback();
mFooter.setUserSwitchCallback(mUserSwitchCallback);
- mUserGridView.setUserSwitchCallback(mUserSwitchCallback);
}
@Override
@@ -111,13 +106,11 @@
@Override
public void setHeaderListening(boolean listening) {
mFooter.setListening(listening);
- mUserGridView.setListening(listening);
}
@Override
public void setListening(boolean listening) {
mFooter.setListening(listening);
- mUserGridView.setListening(listening);
}
@Override
@@ -219,24 +212,6 @@
mShowing = false;
animateHeightChange(false /* opening */);
}
-
- public void resetShowing() {
- if (mShowing) {
- for (int i = 0; i < mUserGridView.getChildCount(); i++) {
- ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
- // Need to bring the last child to the front to maintain the order in the pod
- // container. Why? ¯\_(ツ)_/¯
- if (podContainer.getChildCount() > 0) {
- podContainer.getChildAt(podContainer.getChildCount() - 1).bringToFront();
- }
- // The alpha values are default to 0, so if the pods have been refreshed, they
- // need to be set to 1 when showing.
- for (int j = 0; j < podContainer.getChildCount(); j++) {
- podContainer.getChildAt(j).setAlpha(1f);
- }
- }
- }
- }
}
private void updateUserSwitcherHeight(int height) {
@@ -260,27 +235,6 @@
});
allAnimators.add(heightAnimator);
- // The user grid contains pod containers that each contain a number of pods. Animate
- // all pods to avoid any discrepancy/race conditions with possible changes during the
- // animation.
- int cascadeDelay = getResources().getInteger(
- R.integer.car_user_switcher_anim_cascade_delay_ms);
- for (int i = 0; i < mUserGridView.getChildCount(); i++) {
- ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
- for (int j = 0; j < podContainer.getChildCount(); j++) {
- View pod = podContainer.getChildAt(j);
- Animator podAnimator = AnimatorInflater.loadAnimator(getContext(),
- opening ? R.anim.car_user_switcher_open_pod_animation
- : R.anim.car_user_switcher_close_pod_animation);
- // Add the cascading delay between pods
- if (opening) {
- podAnimator.setStartDelay(podAnimator.getStartDelay() + j * cascadeDelay);
- }
- podAnimator.setTarget(pod);
- allAnimators.add(podAnimator);
- }
- }
-
Animator nameAnimator = AnimatorInflater.loadAnimator(getContext(),
opening ? R.anim.car_user_switcher_open_name_animation
: R.anim.car_user_switcher_close_name_animation);
@@ -293,12 +247,6 @@
iconAnimator.setTarget(mFooterExpandIcon);
allAnimators.add(iconAnimator);
- Animator pageAnimator = AnimatorInflater.loadAnimator(getContext(),
- opening ? R.anim.car_user_switcher_open_pages_animation
- : R.anim.car_user_switcher_close_pages_animation);
- pageAnimator.setTarget(mPageIndicator);
- allAnimators.add(pageAnimator);
-
mAnimatorSet = new AnimatorSet();
mAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 7dcf5c0..4b312f5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -209,7 +209,7 @@
state.slash.isSlashed = !state.value;
state.label = getTileLabel();
state.secondaryLabel = ZenModeConfig.getDescription(mContext,zen != Global.ZEN_MODE_OFF,
- mController.getConfig());
+ mController.getConfig(), false);
state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
switch (zen) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index 75bc955..30e9afd8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -21,7 +21,6 @@
import android.annotation.TargetApi;
import android.app.ActivityManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -62,6 +61,7 @@
private static final String TAG = "RecentsOnboarding";
private static final boolean RESET_PREFS_FOR_DEBUG = false;
+ private static final boolean ONBOARDING_ENABLED = false;
private static final long SHOW_DELAY_MS = 500;
private static final long SHOW_HIDE_DURATION_MS = 300;
// Don't show the onboarding until the user has launched this number of apps.
@@ -184,6 +184,9 @@
}
public void onConnectedToLauncher() {
+ if (!ONBOARDING_ENABLED) {
+ return;
+ }
boolean alreadySeenRecentsOnboarding = Prefs.getBoolean(mContext,
Prefs.Key.HAS_SEEN_RECENTS_ONBOARDING, false);
if (!mTaskListenerRegistered && !alreadySeenRecentsOnboarding) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 3dd6e35..bfbba7c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -107,7 +107,7 @@
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index b81e9af..29c2edc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -26,6 +26,7 @@
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.MotionEvent;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
@@ -1631,6 +1632,42 @@
return null;
}
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ float y = ev.getY();
+ // We still want to distribute touch events to the remote input even if it's outside the
+ // view boundary. We're therefore manually dispatching these events to the remote view
+ RemoteInputView riv = getRemoteInputForView(getViewForVisibleType(mVisibleType));
+ if (riv != null && riv.getVisibility() == VISIBLE) {
+ int inputStart = mUnrestrictedContentHeight - riv.getHeight();
+ if (y <= mUnrestrictedContentHeight && y >= inputStart) {
+ ev.offsetLocation(0, -inputStart);
+ return riv.dispatchTouchEvent(ev);
+ }
+ }
+ return super.dispatchTouchEvent(ev);
+ }
+
+ /**
+ * Overridden to make sure touches to the reply action bar actually go through to this view
+ */
+ @Override
+ public boolean pointInView(float localX, float localY, float slop) {
+ float top = mClipTopAmount;
+ float bottom = mUnrestrictedContentHeight;
+ return localX >= -slop && localY >= top - slop && localX < ((mRight - mLeft) + slop) &&
+ localY < (bottom + slop);
+ }
+
+ private RemoteInputView getRemoteInputForView(View child) {
+ if (child == mExpandedChild) {
+ return mExpandedRemoteInput;
+ } else if (child == mHeadsUpChild) {
+ return mHeadsUpRemoteInput;
+ }
+ return null;
+ }
+
public int getExpandHeight() {
int viewType = VISIBLE_TYPE_EXPANDED;
if (mExpandedChild == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index a93be00..6238526 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -308,15 +308,15 @@
minimize.setVisibility(GONE);
}
- // Set up app settings link
+ // Set up app settings link (i.e. Customize)
TextView settingsLinkView = findViewById(R.id.app_settings);
Intent settingsIntent = getAppSettingsIntent(mPm, mPkg, mSingleNotificationChannel,
mSbn.getId(), mSbn.getTag());
- if (settingsIntent != null
+ if (!mIsForBlockingHelper
+ && settingsIntent != null
&& !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
settingsLinkView.setVisibility(VISIBLE);
- settingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
- mSbn.getNotification().getSettingsText()));
+ settingsLinkView.setText(mContext.getString(R.string.notification_app_settings));
settingsLinkView.setOnClickListener((View view) -> {
mAppSettingsClickListener.onClick(view, settingsIntent);
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 852239a..abc261e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -172,6 +172,14 @@
}
}
+ if (mediaNotification != null) {
+ mMediaNotificationKey = mediaNotification.notification.getKey();
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
+ + mMediaNotificationKey + " controller=" + mMediaController);
+ }
+ }
+
if (controller != null && !sameSessions(mMediaController, controller)) {
// We have a new media session
clearCurrentMediaNotification();
@@ -183,13 +191,6 @@
+ mMediaMetadata);
}
- if (mediaNotification != null) {
- mMediaNotificationKey = mediaNotification.notification.getKey();
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
- + mMediaNotificationKey + " controller=" + mMediaController);
- }
- }
metaDataChanged = true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index 5f3e2e3..7285db6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -42,6 +42,11 @@
/** App packages that are allowed to be used with this widget */
private String[] mFacetPackages;
private int mIconResourceId;
+ /**
+ * If defined in the xml this will be the icon that's rendered when the button is marked as
+ * selected
+ */
+ private int mSelectedIconResourceId;
private boolean mUseMoreIcon = true;
private float mSelectedAlpha = 1f;
private float mUnselectedAlpha = 1f;
@@ -112,10 +117,9 @@
mIcon.setClickable(false);
mIcon.setAlpha(mUnselectedAlpha);
mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
- if (mIconResourceId == 0) {
- throw new RuntimeException("specified icon resource was not found and is required");
- }
mIcon.setImageResource(mIconResourceId);
+ mSelectedIconResourceId = styledAttributes.getResourceId(
+ R.styleable.CarFacetButton_selectedIcon, mIconResourceId);
mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
mMoreIcon.setClickable(false);
@@ -161,22 +165,10 @@
*/
public void setSelected(boolean selected, boolean showMoreIcon) {
mSelected = selected;
- if (selected) {
- if (mUseMoreIcon) {
- mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
- }
- mIcon.setAlpha(mSelectedAlpha);
- } else {
- mMoreIcon.setVisibility(GONE);
- mIcon.setAlpha(mUnselectedAlpha);
- }
- }
-
- public void setIcon(Drawable d) {
- if (d != null) {
- mIcon.setImageDrawable(d);
- } else {
- mIcon.setImageResource(mIconResourceId);
+ mIcon.setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
+ mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
+ if (mUseMoreIcon) {
+ mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index e73b173..b2cef16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -25,7 +25,9 @@
import android.widget.TextView;
import com.android.keyguard.AlphaOptimizedImageButton;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
/**
* A custom navigation bar for the automotive use case.
@@ -52,6 +54,17 @@
if (mNotificationsButton != null) {
mNotificationsButton.setOnClickListener(this::onNotificationsClick);
}
+ View mStatusIcons = findViewById(R.id.statusIcons);
+ if (mStatusIcons != null) {
+ // Attach the controllers for Status icons such as wifi and bluetooth if the standard
+ // container is in the view.
+ StatusBarIconController.DarkIconManager mDarkIconManager =
+ new StatusBarIconController.DarkIconManager(
+ mStatusIcons.findViewById(R.id.statusIcons));
+ mDarkIconManager.setShouldLog(true);
+ Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
+ }
+
}
void setStatusBar(CarStatusBar carStatusBar) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index 0cdaec1..ec243fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -4,6 +4,7 @@
import android.content.Intent;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import android.util.Log;
import android.widget.ImageView;
import com.android.systemui.R;
@@ -17,23 +18,34 @@
*/
public class CarNavigationButton extends com.android.keyguard.AlphaOptimizedImageButton {
- private static final float SELECTED_ALPHA = 1;
- private static final float UNSELECTED_ALPHA = 0.7f;
-
+ private static final String TAG = "CarNavigationButton";
private Context mContext;
- private String mIntent = null;
- private String mLongIntent = null;
- private boolean mBroadcastIntent = false;
+ private String mIntent;
+ private String mLongIntent;
+ private boolean mBroadcastIntent;
private boolean mSelected = false;
+ private float mSelectedAlpha = 1f;
+ private float mUnselectedAlpha = 1f;
+ private int mSelectedIconResourceId;
+ private int mIconResourceId;
public CarNavigationButton(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarNavigationButton);
+ TypedArray typedArray = context.obtainStyledAttributes(
+ attrs, R.styleable.CarNavigationButton);
mIntent = typedArray.getString(R.styleable.CarNavigationButton_intent);
mLongIntent = typedArray.getString(R.styleable.CarNavigationButton_longIntent);
mBroadcastIntent = typedArray.getBoolean(R.styleable.CarNavigationButton_broadcast, false);
+ mSelectedAlpha = typedArray.getFloat(
+ R.styleable.CarNavigationButton_selectedAlpha, mSelectedAlpha);
+ mUnselectedAlpha = typedArray.getFloat(
+ R.styleable.CarNavigationButton_unselectedAlpha, mUnselectedAlpha);
+ mIconResourceId = typedArray.getResourceId(
+ com.android.internal.R.styleable.ImageView_src, 0);
+ mSelectedIconResourceId = typedArray.getResourceId(
+ R.styleable.CarNavigationButton_selectedIcon, mIconResourceId);
}
@@ -45,17 +57,20 @@
public void onFinishInflate() {
super.onFinishInflate();
setScaleType(ImageView.ScaleType.CENTER);
- setAlpha(UNSELECTED_ALPHA);
+ setAlpha(mUnselectedAlpha);
try {
if (mIntent != null) {
final Intent intent = Intent.parseUri(mIntent, Intent.URI_INTENT_SCHEME);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
setOnClickListener(v -> {
- if (mBroadcastIntent) {
- mContext.sendBroadcast(intent);
- return;
+ try {
+ if (mBroadcastIntent) {
+ mContext.sendBroadcast(intent);
+ return;
+ }
+ mContext.startActivity(intent);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to launch intent", e);
}
- mContext.startActivity(intent);
});
}
} catch (URISyntaxException e) {
@@ -65,9 +80,13 @@
try {
if (mLongIntent != null) {
final Intent intent = Intent.parseUri(mLongIntent, Intent.URI_INTENT_SCHEME);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
setOnLongClickListener(v -> {
- mContext.startActivity(intent);
+ try {
+ mContext.startActivity(intent);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to launch intent", e);
+ }
+ // consume event either way
return true;
});
}
@@ -82,6 +101,7 @@
public void setSelected(boolean selected) {
super.setSelected(selected);
mSelected = selected;
- setAlpha(mSelected ? SELECTED_ALPHA : UNSELECTED_ALPHA);
+ setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
+ setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 3fb1137..008794c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -418,8 +418,7 @@
Dependency.get(UserSwitcherController.class);
if (userSwitcherController.useFullscreenUserSwitcher()) {
mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
- userSwitcherController,
- mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub));
+ mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
} else {
super.createUserSwitcher();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index bc353f2..fb525f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,14 +18,15 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.content.res.Resources;
+import android.content.Context;
import android.view.View;
import android.view.ViewStub;
import android.widget.ProgressBar;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
* Manages the fullscreen user switcher.
@@ -33,36 +34,25 @@
public class FullscreenUserSwitcher {
private final View mContainer;
private final View mParent;
- private final UserGridView mUserGridView;
- private final UserSwitcherController mUserSwitcherController;
+ private final UserGridRecyclerView mUserGridView;
private final ProgressBar mSwitchingUsers;
private final int mShortAnimDuration;
private boolean mShowing;
- public FullscreenUserSwitcher(StatusBar statusBar,
- UserSwitcherController userSwitcherController,
- ViewStub containerStub) {
- mUserSwitcherController = userSwitcherController;
+ public FullscreenUserSwitcher(StatusBar statusBar, ViewStub containerStub, Context context) {
mParent = containerStub.inflate();
mContainer = mParent.findViewById(R.id.container);
mUserGridView = mContainer.findViewById(R.id.user_grid);
- mUserGridView.init(statusBar, mUserSwitcherController, true /* overrideAlpha */);
- mUserGridView.setUserSelectionListener(record -> {
- if (!record.isCurrent) {
- toggleSwitchInProgress(true);
- }
- });
+ mUserGridView.setStatusBar(statusBar);
+ GridLayoutManager layoutManager = new GridLayoutManager(context,
+ context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
+ mUserGridView.setLayoutManager(layoutManager);
+ mUserGridView.buildAdapter();
+ mUserGridView.setUserSelectionListener(record -> toggleSwitchInProgress(true));
- PageIndicator pageIndicator = mContainer.findViewById(R.id.user_switcher_page_indicator);
- pageIndicator.setupWithViewPager(mUserGridView);
-
- Resources res = mContainer.getResources();
- mShortAnimDuration = res.getInteger(android.R.integer.config_shortAnimTime);
-
- mContainer.findViewById(R.id.start_driving).setOnClickListener(v -> {
- automaticallySelectUser();
- });
+ mShortAnimDuration = mContainer.getResources()
+ .getInteger(android.R.integer.config_shortAnimTime);
mSwitchingUsers = mParent.findViewById(R.id.switching_users);
}
@@ -115,10 +105,4 @@
toggleSwitchInProgress(false);
mParent.setVisibility(View.GONE);
}
-
- private void automaticallySelectUser() {
- // TODO: Switch according to some policy. This implementation just tries to drop the
- // keyguard for the current user.
- mUserGridView.showOfflineAuthUi();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
new file mode 100644
index 0000000..e09a360
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -0,0 +1,360 @@
+/*
+ * 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.systemui.statusbar.car;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.drawable.GradientDrawable;
+import android.os.AsyncTask;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settingslib.users.UserManagerHelper;
+import com.android.systemui.R;
+import com.android.systemui.qs.car.CarQSFragment;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Displays a GridLayout with icons for the users in the system to allow switching between users.
+ * One of the uses of this is for the lock screen in auto.
+ */
+public class UserGridRecyclerView extends RecyclerView implements
+ UserManagerHelper.OnUsersUpdateListener {
+
+ private StatusBar mStatusBar;
+ private UserSelectionListener mUserSelectionListener;
+ private UserAdapter mAdapter;
+ private UserManagerHelper mUserManagerHelper;
+ private Context mContext;
+
+ public UserGridRecyclerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ super.setHasFixedSize(true);
+ mContext = context;
+ mUserManagerHelper = new UserManagerHelper(mContext);
+ }
+
+ /**
+ * Register listener for any update to the users
+ */
+ @Override
+ public void onFinishInflate() {
+ mUserManagerHelper.registerOnUsersUpdateListener(this);
+ }
+
+ /**
+ * Unregisters listener checking for any change to the users
+ */
+ @Override
+ public void onDetachedFromWindow() {
+ mUserManagerHelper.unregisterOnUsersUpdateListener();
+ }
+
+ /**
+ * Initializes the adapter that populates the grid layout
+ *
+ * @return the adapter
+ */
+ public void buildAdapter() {
+ List<UserRecord> userRecords = createUserRecords(mUserManagerHelper
+ .getAllUsers());
+ mAdapter = new UserAdapter(mContext, userRecords);
+ super.setAdapter(mAdapter);
+ }
+
+ public void setStatusBar(@Nullable StatusBar statusBar) {
+ mStatusBar = statusBar;
+ }
+
+ private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
+ List<UserRecord> userRecords = new ArrayList<>();
+ for (UserInfo userInfo : userInfoList) {
+ boolean isCurrent = false;
+ if (ActivityManager.getCurrentUser() == userInfo.id) {
+ isCurrent = true;
+ }
+ UserRecord record = new UserRecord(userInfo, false /* isGuest */,
+ false /* isAddUser */, isCurrent);
+ userRecords.add(record);
+ }
+
+ // Add guest user record if the current user is not a guest
+ if (!mUserManagerHelper.isGuestUser()) {
+ userRecords.add(addGuestUserRecord());
+ }
+
+ // Add add user record if the current user can add users
+ if (mUserManagerHelper.canAddUsers()) {
+ userRecords.add(addUserRecord());
+ }
+
+ return userRecords;
+ }
+
+ /**
+ * Create guest user record
+ */
+ private UserRecord addGuestUserRecord() {
+ UserInfo userInfo = new UserInfo();
+ userInfo.name = mContext.getString(R.string.car_guest);
+ return new UserRecord(userInfo, true /* isGuest */,
+ false /* isAddUser */, false /* isCurrent */);
+ }
+
+ /**
+ * Create add user record
+ */
+ private UserRecord addUserRecord() {
+ UserInfo userInfo = new UserInfo();
+ userInfo.name = mContext.getString(R.string.car_add_user);
+ return new UserRecord(userInfo, false /* isGuest */,
+ true /* isAddUser */, false /* isCurrent */);
+ }
+
+ public void onUserSwitched(int newUserId) {
+ // Bring up security view after user switch is completed.
+ post(this::showOfflineAuthUi);
+ }
+
+ public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
+ mUserSelectionListener = userSelectionListener;
+ }
+
+ void showOfflineAuthUi() {
+ // TODO: Show keyguard UI in-place.
+ if (mStatusBar != null) {
+ mStatusBar.executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
+ true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
+ }
+ }
+
+ @Override
+ public void onUsersUpdate() {
+ mAdapter.clearUsers();
+ mAdapter.updateUsers(createUserRecords(mUserManagerHelper.getAllUsers()));
+ mAdapter.notifyDataSetChanged();
+ }
+
+ /**
+ * Adapter to populate the grid layout with the available user profiles
+ */
+ public final class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserAdapterViewHolder> {
+
+ private final Context mContext;
+ private List<UserRecord> mUsers;
+ private final int mPodImageAvatarWidth;
+ private final int mPodImageAvatarHeight;
+ private final Resources mRes;
+ private final String mGuestName;
+ private final String mNewUserName;
+
+ public UserAdapter(Context context, List<UserRecord> users) {
+ mRes = context.getResources();
+ mContext = context;
+ updateUsers(users);
+ mPodImageAvatarWidth = mRes.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_image_avatar_width);
+ mPodImageAvatarHeight = mRes.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_image_avatar_height);
+ mGuestName = mRes.getString(R.string.car_guest);
+ mNewUserName = mRes.getString(R.string.car_new_user);
+ }
+
+ public void clearUsers() {
+ mUsers.clear();
+ }
+
+ public void updateUsers(List<UserRecord> users) {
+ mUsers = users;
+ }
+
+ @Override
+ public UserAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(mContext)
+ .inflate(R.layout.car_fullscreen_user_pod, parent, false);
+ view.setAlpha(1f);
+ view.bringToFront();
+ return new UserAdapterViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
+ UserRecord userRecord = mUsers.get(position);
+ holder.mUserAvatarImageView.setImageBitmap(getDefaultUserIcon(userRecord));
+ holder.mUserNameTextView.setText(userRecord.mInfo.name);
+ holder.mView.setOnClickListener(v -> {
+ if (userRecord == null) {
+ return;
+ }
+
+ // Notify the listener which user was selected
+ if (mUserSelectionListener != null) {
+ mUserSelectionListener.onUserSelected(userRecord);
+ }
+
+ // If the user selects Guest, switch to Guest profile
+ if (userRecord.mIsGuest) {
+ mUserManagerHelper.switchToGuest(mGuestName);
+ return;
+ }
+
+ // If the user wants to add a user, start task to add new user
+ if (userRecord.mIsAddUser) {
+ new AddNewUserTask().execute(mNewUserName);
+ return;
+ }
+
+ // If the user doesn't want to be a guest or add a user, switch to the user selected
+ mUserManagerHelper.switchToUser(userRecord.mInfo);
+ });
+
+ }
+
+ private class AddNewUserTask extends AsyncTask<String, Void, UserInfo> {
+
+ @Override
+ protected UserInfo doInBackground(String... userNames) {
+ return mUserManagerHelper.createNewUser(userNames[0]);
+ }
+
+ @Override
+ protected void onPreExecute() {
+ }
+
+ @Override
+ protected void onPostExecute(UserInfo user) {
+ if (user != null) {
+ mUserManagerHelper.switchToUser(user);
+ }
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mUsers.size();
+ }
+
+ /**
+ * Returns the default user icon. This icon is a circle with a letter in it. The letter is
+ * the first character in the username.
+ *
+ * @param record the profile of the user for which the icon should be created
+ */
+ private Bitmap getDefaultUserIcon(UserRecord record) {
+ CharSequence displayText;
+ boolean isAddUserText = false;
+ if (record.mIsAddUser) {
+ displayText = "+";
+ isAddUserText = true;
+ } else {
+ displayText = record.mInfo.name.subSequence(0, 1);
+ }
+ Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(out);
+
+ // Draw the circle background.
+ GradientDrawable shape = new GradientDrawable();
+ shape.setShape(GradientDrawable.RADIAL_GRADIENT);
+ shape.setGradientRadius(1.0f);
+ shape.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
+ shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
+ shape.draw(canvas);
+
+ // Draw the letter in the center.
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_fgcolor));
+ paint.setTextAlign(Align.CENTER);
+ if (isAddUserText) {
+ paint.setTextSize(mRes.getDimensionPixelSize(
+ R.dimen.car_touch_target_size));
+ } else {
+ paint.setTextSize(mRes.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_icon_text_size));
+ }
+
+ Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
+ // The Y coordinate is measured by taking half the height of the pod, but that would
+ // draw the character putting the bottom of the font in the middle of the pod. To
+ // correct this, half the difference between the top and bottom distance metrics of the
+ // font gives the offset of the font. Bottom is a positive value, top is negative, so
+ // the different is actually a sum. The "half" operation is then factored out.
+ canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
+ (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
+
+ return out;
+ }
+
+ public class UserAdapterViewHolder extends RecyclerView.ViewHolder {
+
+ public ImageView mUserAvatarImageView;
+ public TextView mUserNameTextView;
+ public View mView;
+
+ public UserAdapterViewHolder(View view) {
+ super(view);
+ mView = view;
+ mUserAvatarImageView = (ImageView) view.findViewById(R.id.user_avatar);
+ mUserNameTextView = (TextView) view.findViewById(R.id.user_name);
+ }
+ }
+ }
+
+ /**
+ * Object wrapper class for the userInfo. Use it to distinguish if a profile is a
+ * guest profile, add user profile, or a current user.
+ */
+ public static final class UserRecord {
+
+ public final UserInfo mInfo;
+ public final boolean mIsGuest;
+ public final boolean mIsAddUser;
+ public final boolean mIsCurrent;
+
+ public UserRecord(UserInfo userInfo, boolean isGuest, boolean isAddUser,
+ boolean isCurrent) {
+ mInfo = userInfo;
+ mIsGuest = isGuest;
+ mIsAddUser = isAddUser;
+ mIsCurrent = isCurrent;
+ }
+ }
+
+ /**
+ * Listener used to notify when a user has been selected
+ */
+ interface UserSelectionListener {
+
+ void onUserSelected(UserRecord record);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
deleted file mode 100644
index 1bd820d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.car;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.qs.car.CarQSFragment;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Vector;
-
-/**
- * Displays a ViewPager with icons for the users in the system to allow switching between users.
- * One of the uses of this is for the lock screen in auto.
- */
-public class UserGridView extends ViewPager implements
- UserInfoController.OnUserInfoChangedListener {
- private StatusBar mStatusBar;
- private UserSwitcherController mUserSwitcherController;
- private Adapter mAdapter;
- private UserSelectionListener mUserSelectionListener;
- private UserInfoController mUserInfoController;
- private Vector mUserContainers;
- private int mContainerWidth;
- private boolean mOverrideAlpha;
- private CarQSFragment.UserSwitchCallback mUserSwitchCallback;
-
- public UserGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
- boolean overrideAlpha) {
- mStatusBar = statusBar;
- mUserSwitcherController = userSwitcherController;
- mAdapter = new Adapter(mUserSwitcherController);
- mUserInfoController = Dependency.get(UserInfoController.class);
- mOverrideAlpha = overrideAlpha;
- // Whenever the container width changes, the containers must be refreshed. Instead of
- // doing an initial refreshContainers() to populate the containers, this listener will
- // refresh them on layout change because that affects how the users are split into
- // containers. Furthermore, at this point, the container width is unknown, so
- // refreshContainers() cannot populate any containers.
- addOnLayoutChangeListener(
- (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
- int newWidth = Math.max(left - right, right - left);
- if (mContainerWidth != newWidth) {
- mContainerWidth = newWidth;
- refreshContainers();
- }
- });
- }
-
- private void refreshContainers() {
- mUserContainers = new Vector();
-
- Context context = getContext();
- LayoutInflater inflater = LayoutInflater.from(context);
-
- for (int i = 0; i < mAdapter.getCount(); i++) {
- ViewGroup pods = (ViewGroup) inflater.inflate(
- R.layout.car_fullscreen_user_pod_container, null);
-
- int iconsPerPage = mAdapter.getIconsPerPage();
- int limit = Math.min(mUserSwitcherController.getUsers().size(), (i + 1) * iconsPerPage);
- for (int j = i * iconsPerPage; j < limit; j++) {
- View v = mAdapter.makeUserPod(inflater, context, j, pods);
- if (mOverrideAlpha) {
- v.setAlpha(1f);
- }
- pods.addView(v);
- // This is hacky, but the dividers on the pod container LinearLayout don't seem
- // to work for whatever reason. Instead, set a right margin on the pod if it's not
- // the right-most pod and there is more than one pod in the container.
- if (i < limit - 1 && limit > 1) {
- ViewGroup.MarginLayoutParams params =
- (ViewGroup.MarginLayoutParams) v.getLayoutParams();
- params.setMargins(0, 0, getResources().getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_margin_between), 0);
- v.setLayoutParams(params);
- }
- }
- mUserContainers.add(pods);
- }
-
- mAdapter = new Adapter(mUserSwitcherController);
- setAdapter(mAdapter);
- }
-
- @Override
- public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
- refreshContainers();
- }
-
- public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) {
- mUserSwitchCallback = callback;
- }
-
- public void onUserSwitched(int newUserId) {
- // Bring up security view after user switch is completed.
- post(this::showOfflineAuthUi);
- }
-
- public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
- mUserSelectionListener = userSelectionListener;
- }
-
- public void setListening(boolean listening) {
- if (listening) {
- mUserInfoController.addCallback(this);
- } else {
- mUserInfoController.removeCallback(this);
- }
- }
-
- void showOfflineAuthUi() {
- // TODO: Show keyguard UI in-place.
- mStatusBar.executeRunnableDismissingKeyguard(null, null, true, true, true);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Wrap content doesn't work in ViewPagers, so simulate the behavior in code.
- int height = 0;
- if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
- height = MeasureSpec.getSize(heightMeasureSpec);
- } else {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- child.measure(widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- height = Math.max(child.getMeasuredHeight(), height);
- }
-
- // Respect the AT_MOST request from parent.
- if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
- height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
- }
- }
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
-
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- /**
- * This is a ViewPager.PagerAdapter which deletegates the work to a
- * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
- * to use composition instead to achieve the same goal since both the base classes are abstract
- * classes and not interfaces.
- */
- private final class Adapter extends PagerAdapter {
- private final int mPodWidth;
- private final int mPodMarginBetween;
- private final int mPodImageAvatarWidth;
- private final int mPodImageAvatarHeight;
-
- private final WrappedBaseUserAdapter mUserAdapter;
-
- public Adapter(UserSwitcherController controller) {
- super();
- mUserAdapter = new WrappedBaseUserAdapter(controller, this);
-
- Resources res = getResources();
- mPodWidth = res.getDimensionPixelSize(R.dimen.car_fullscreen_user_pod_width);
- mPodMarginBetween = res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_margin_between);
- mPodImageAvatarWidth = res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_image_avatar_width);
- mPodImageAvatarHeight = res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_image_avatar_height);
- }
-
- @Override
- public void destroyItem(ViewGroup container, int position, Object object) {
- container.removeView((View) object);
- }
-
- private int getIconsPerPage() {
- // We need to know how many pods we need in this page. Each pod has its own width and
- // a margin between them. We can then divide the measured width of the parent by the
- // sum of pod width and margin to get the number of pods that will completely fit.
- // There is one less margin than the number of pods (eg. for 5 pods, there are 4
- // margins), so need to add the margin to the measured width to account for that.
- return (mContainerWidth + mPodMarginBetween) /
- (mPodWidth + mPodMarginBetween);
- }
-
- @Override
- public void finishUpdate(ViewGroup container) {
- if (mUserSwitchCallback != null) {
- mUserSwitchCallback.resetShowing();
- }
- }
-
- @Override
- public Object instantiateItem(ViewGroup container, int position) {
- if (position < mUserContainers.size()) {
- container.addView((View) mUserContainers.get(position));
- return mUserContainers.get(position);
- } else {
- return null;
- }
- }
-
- /**
- * Returns the default user icon. This icon is a circle with a letter in it. The letter is
- * the first character in the username.
- *
- * @param userName the username of the user for which the icon is to be created
- */
- private Bitmap getDefaultUserIcon(CharSequence userName) {
- CharSequence displayText = userName.subSequence(0, 1);
- Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(out);
-
- // Draw the circle background.
- GradientDrawable shape = new GradientDrawable();
- shape.setShape(GradientDrawable.RADIAL_GRADIENT);
- shape.setGradientRadius(1.0f);
- shape.setColor(getContext().getColor(R.color.car_user_switcher_no_user_image_bgcolor));
- shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
- shape.draw(canvas);
-
- // Draw the letter in the center.
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(getContext().getColor(R.color.car_user_switcher_no_user_image_fgcolor));
- paint.setTextAlign(Align.CENTER);
- paint.setTextSize(getResources().getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_icon_text_size));
- Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
- // The Y coordinate is measured by taking half the height of the pod, but that would
- // draw the character putting the bottom of the font in the middle of the pod. To
- // correct this, half the difference between the top and bottom distance metrics of the
- // font gives the offset of the font. Bottom is a positive value, top is negative, so
- // the different is actually a sum. The "half" operation is then factored out.
- canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
- (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
-
- return out;
- }
-
- private View makeUserPod(LayoutInflater inflater, Context context,
- int position, ViewGroup parent) {
- final UserSwitcherController.UserRecord record = mUserAdapter.getItem(position);
- View view = inflater.inflate(R.layout.car_fullscreen_user_pod, parent, false);
-
- TextView nameView = view.findViewById(R.id.user_name);
- if (record != null) {
- nameView.setText(mUserAdapter.getName(context, record));
- view.setActivated(record.isCurrent);
- } else {
- nameView.setText(context.getString(R.string.unknown_user_label));
- }
-
- ImageView iconView = (ImageView) view.findViewById(R.id.user_avatar);
- if (record == null || (record.picture == null && !record.isAddUser)) {
- iconView.setImageBitmap(getDefaultUserIcon(nameView.getText()));
- } else if (record.isAddUser) {
- Drawable icon = context.getDrawable(R.drawable.ic_add_circle_qs);
- icon.setTint(context.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
- iconView.setImageDrawable(icon);
- } else {
- iconView.setImageBitmap(record.picture);
- }
-
- iconView.setOnClickListener(v -> {
- if (record == null) {
- return;
- }
-
- if (mUserSelectionListener != null) {
- mUserSelectionListener.onUserSelected(record);
- }
-
- if (record.isCurrent) {
- showOfflineAuthUi();
- } else {
- mUserSwitcherController.switchTo(record);
- }
- });
-
- return view;
- }
-
- @Override
- public int getCount() {
- int iconsPerPage = getIconsPerPage();
- if (iconsPerPage == 0) {
- return 0;
- }
- return (int) Math.ceil((double) mUserAdapter.getCount() / getIconsPerPage());
- }
-
- public void refresh() {
- mUserAdapter.refresh();
- }
-
- @Override
- public boolean isViewFromObject(View view, Object object) {
- return view == object;
- }
- }
-
- private final class WrappedBaseUserAdapter extends UserSwitcherController.BaseUserAdapter {
- private final Adapter mContainer;
-
- public WrappedBaseUserAdapter(UserSwitcherController controller, Adapter container) {
- super(controller);
- mContainer = container;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- throw new UnsupportedOperationException("unused");
- }
-
- @Override
- public void notifyDataSetChanged() {
- super.notifyDataSetChanged();
- mContainer.notifyDataSetChanged();
- }
- }
-
- interface UserSelectionListener {
- void onUserSelected(UserSwitcherController.UserRecord record);
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 3bbfe3c..b8bce95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -238,6 +238,7 @@
t.deferTransactionUntilSurface(app.leash, systemUiSurface,
systemUiSurface.getNextFrameNumber());
}
+ t.setEarlyWakeup();
t.apply();
}
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 3dbac51..cc143bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -111,7 +111,6 @@
private final Context mContext;
protected final ScrimView mScrimBehind;
protected final ScrimView mScrimInFront;
- private final LightBarController mLightBarController;
private final UnlockMethodCache mUnlockMethodCache;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final DozeParameters mDozeParameters;
@@ -145,6 +144,8 @@
private int mCurrentBehindTint;
private boolean mWallpaperVisibilityTimedOut;
private int mScrimsVisibility;
+ private final Consumer<GradientColors> mScrimInFrontColorListener;
+ private final Consumer<Float> mScrimBehindAlphaListener;
private final Consumer<Integer> mScrimVisibleListener;
private boolean mBlankScreen;
private boolean mScreenBlankingCallbackCalled;
@@ -161,17 +162,20 @@
private boolean mWakeLockHeld;
private boolean mKeyguardOccluded;
- public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
- ScrimView scrimInFront, Consumer<Integer> scrimVisibleListener,
- DozeParameters dozeParameters, AlarmManager alarmManager) {
+ public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
+ Consumer<Float> scrimBehindAlphaListener,
+ Consumer<GradientColors> scrimInFrontColorListener,
+ Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
+ AlarmManager alarmManager) {
mScrimBehind = scrimBehind;
mScrimInFront = scrimInFront;
+ mScrimBehindAlphaListener = scrimBehindAlphaListener;
+ mScrimInFrontColorListener = scrimInFrontColorListener;
mScrimVisibleListener = scrimVisibleListener;
mContext = scrimBehind.getContext();
mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
- mLightBarController = lightBarController;
mScrimBehindAlphaResValue = mContext.getResources().getFloat(R.dimen.scrim_behind_alpha);
mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout,
"hide_aod_wallpaper", new Handler());
@@ -196,6 +200,9 @@
}
mState = ScrimState.UNINITIALIZED;
+ mScrimBehind.setDefaultFocusHighlightEnabled(false);
+ mScrimInFront.setDefaultFocusHighlightEnabled(false);
+
updateScrims();
}
@@ -367,6 +374,8 @@
setOrAdaptCurrentAnimation(mScrimBehind);
setOrAdaptCurrentAnimation(mScrimInFront);
+
+ mScrimBehindAlphaListener.accept(mScrimBehind.getViewAlpha());
}
}
@@ -475,7 +484,7 @@
float minOpacity = ColorUtils.calculateMinimumBackgroundAlpha(textColor, mainColor,
4.5f /* minimumContrast */) / 255f;
mScrimBehindAlpha = Math.max(mScrimBehindAlphaResValue, minOpacity);
- mLightBarController.setScrimColor(mScrimInFront.getColors());
+ mScrimInFrontColorListener.accept(mScrimInFront.getColors());
}
// We want to override the back scrim opacity for the AOD state
@@ -702,9 +711,8 @@
}
}
- // TODO factor mLightBarController out of this class
if (scrim == mScrimBehind) {
- mLightBarController.setScrimAlpha(alpha);
+ mScrimBehindAlphaListener.accept(alpha);
}
final boolean wantsAlphaUpdate = alpha != currentAlpha;
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 d38c083..bbdaa99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -112,9 +112,9 @@
mCurrentInFrontTint = Color.BLACK;
mCurrentBehindTint = Color.BLACK;
mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
- // DisplayPowerManager will blank the screen for us, we just need
- // to set our state.
- mAnimateChange = !mDisplayRequiresBlanking;
+ // DisplayPowerManager may blank the screen for us,
+ // in this case we just need to set our state.
+ mAnimateChange = mDozeParameters.shouldControlScreenOff();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index c08d824..ab13678 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -916,8 +916,14 @@
ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front);
- mScrimController = SystemUIFactory.getInstance().createScrimController(mLightBarController,
+ mScrimController = SystemUIFactory.getInstance().createScrimController(
scrimBehind, scrimInFront, mLockscreenWallpaper,
+ scrimBehindAlpha -> {
+ mLightBarController.setScrimAlpha(scrimBehindAlpha);
+ },
+ scrimInFrontColor -> {
+ mLightBarController.setScrimColor(scrimInFrontColor);
+ },
scrimsVisible -> {
if (mStatusBarWindowManager != null) {
mStatusBarWindowManager.setScrimsVisibility(scrimsVisible);
@@ -1428,13 +1434,13 @@
}
public void addQsTile(ComponentName tile) {
- if (mQSPanel.getHost() != null) {
+ if (mQSPanel != null && mQSPanel.getHost() != null) {
mQSPanel.getHost().addTile(tile);
}
}
public void remQsTile(ComponentName tile) {
- if (mQSPanel.getHost() != null) {
+ if (mQSPanel != null && mQSPanel.getHost() != null) {
mQSPanel.getHost().removeTile(tile);
}
}
@@ -3901,7 +3907,11 @@
}
public boolean onBackPressed() {
- if (mStatusBarKeyguardViewManager.onBackPressed()) {
+ boolean isScrimmedBouncer = mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED;
+ if (mStatusBarKeyguardViewManager.onBackPressed(isScrimmedBouncer /* hideImmediately */)) {
+ if (!isScrimmedBouncer) {
+ mNotificationPanel.expandWithoutQs();
+ }
return true;
}
if (mNotificationPanel.isQsExpanded()) {
@@ -4996,6 +5006,14 @@
@Override
public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
+ RemoteInputController controller = mRemoteInputManager.getController();
+ if (controller.isRemoteInputActive(row.getEntry())
+ && !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
+ // We have an active remote input typed and the user clicked on the notification.
+ // this was probably unintentional, so we're closing the edit text instead.
+ controller.closeRemoteInputs();
+ return;
+ }
Notification notification = sbn.getNotification();
final PendingIntent intent = notification.contentIntent != null
? notification.contentIntent
@@ -5059,12 +5077,7 @@
Intent fillInIntent = null;
Entry entry = row.getEntry();
CharSequence remoteInputText = null;
- RemoteInputController controller = mRemoteInputManager.getController();
- if (controller.isRemoteInputActive(entry)) {
- remoteInputText = row.getActiveRemoteInputText();
- }
- if (TextUtils.isEmpty(remoteInputText)
- && !TextUtils.isEmpty(entry.remoteInputText)) {
+ if (!TextUtils.isEmpty(entry.remoteInputText)) {
remoteInputText = entry.remoteInputText;
}
if (!TextUtils.isEmpty(remoteInputText)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 2727b30..670c68f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -512,12 +512,15 @@
/**
* Notifies this manager that the back button has been pressed.
*
+ * @param hideImmediately Hide bouncer when {@code true}, keep it around otherwise.
+ * Non-scrimmed bouncers have a special animation tied to the expansion
+ * of the notification panel.
* @return whether the back press has been handled
*/
- public boolean onBackPressed() {
+ public boolean onBackPressed(boolean hideImmediately) {
if (mBouncer.isShowing()) {
mStatusBar.endAffordanceLaunch();
- reset(true /* hideBouncerWhenShowing */);
+ reset(hideImmediately);
return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index baeaaad..9aa8044 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -16,9 +16,6 @@
package com.android.systemui.statusbar.policy;
-import libcore.icu.LocaleData;
-
-import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -46,6 +43,7 @@
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -53,6 +51,8 @@
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import libcore.icu.LocaleData;
+
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
@@ -66,6 +66,9 @@
public static final String CLOCK_SECONDS = "clock_seconds";
+ private final CurrentUserTracker mCurrentUserTracker;
+ private int mCurrentUserId;
+
private boolean mClockVisibleByPolicy = true;
private boolean mClockVisibleByUser = true;
@@ -117,6 +120,12 @@
} finally {
a.recycle();
}
+ mCurrentUserTracker = new CurrentUserTracker(context) {
+ @Override
+ public void onUserSwitched(int newUserId) {
+ mCurrentUserId = newUserId;
+ }
+ };
}
@Override
@@ -141,6 +150,8 @@
if (mShowDark) {
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
}
+ mCurrentUserTracker.startTracking();
+ mCurrentUserId = mCurrentUserTracker.getCurrentUserId();
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
@@ -166,6 +177,7 @@
if (mShowDark) {
Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this);
}
+ mCurrentUserTracker.stopTracking();
}
}
@@ -302,7 +314,7 @@
private final CharSequence getSmallTime() {
Context context = getContext();
- boolean is24 = DateFormat.is24HourFormat(context, ActivityManager.getCurrentUser());
+ boolean is24 = DateFormat.is24HourFormat(context, mCurrentUserId);
LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
final char MAGIC1 = '\uEF00';
@@ -392,8 +404,7 @@
} else if (hhmm != null && hhmm.length() == 4) {
int hh = Integer.parseInt(hhmm.substring(0, 2));
int mm = Integer.parseInt(hhmm.substring(2));
- boolean is24 = DateFormat.is24HourFormat(
- getContext(), ActivityManager.getCurrentUser());
+ boolean is24 = DateFormat.is24HourFormat(getContext(), mCurrentUserId);
if (is24) {
mCalendar.set(Calendar.HOUR_OF_DAY, hh);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
index e1814098..a901e88 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
@@ -23,7 +23,7 @@
*/
public class DelayedWakeLock implements WakeLock {
- private static final long RELEASE_DELAY_MS = 240;
+ private static final long RELEASE_DELAY_MS = 140;
private final Handler mHandler;
private final WakeLock mInner;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 13157fe..a2d2615 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -212,7 +212,6 @@
.setDuration(300)
.setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
.withEndAction(() -> {
- mWindow.getDecorView().requestAccessibilityFocus();
if (!Prefs.getBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, false)) {
mRingerIcon.postOnAnimationDelayed(mSinglePress, 1500);
}
diff --git a/packages/SystemUI/tests/AndroidTest.xml b/packages/SystemUI/tests/AndroidTest.xml
index 53839a9b..fc353a1 100644
--- a/packages/SystemUI/tests/AndroidTest.xml
+++ b/packages/SystemUI/tests/AndroidTest.xml
@@ -24,5 +24,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.systemui.tests" />
<option name="runner" value="android.testing.TestableInstrumentation" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index d86e947..658ac73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -696,6 +696,29 @@
assertEquals(GONE, settingsLink.getVisibility());
}
+ @Test
+ public void testBindHeader_noSettingsLinkWhenIsForBlockingHelper() throws Exception {
+ final String settingsText = "work chats";
+ final ResolveInfo ri = new ResolveInfo();
+ ri.activityInfo = new ActivityInfo();
+ ri.activityInfo.packageName = TEST_PACKAGE_NAME;
+ ri.activityInfo.name = "something";
+ List<ResolveInfo> ris = new ArrayList<>();
+ ris.add(ri);
+ when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
+ .setSettingsText(settingsText).build();
+ StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
+ 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
+
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
+ true);
+ final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
+ assertEquals(GONE, settingsLink.getVisibility());
+ }
+
@Test
public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
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 1e8e14d..0416232 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
@@ -42,6 +42,7 @@
import android.testing.TestableLooper;
import android.view.View;
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.ScrimView;
@@ -65,9 +66,12 @@
private SynchronousScrimController mScrimController;
private ScrimView mScrimBehind;
private ScrimView mScrimInFront;
+ private Consumer<Float> mScrimBehindAlphaCallback;
+ private Consumer<GradientColors> mScrimInFrontColorCallback;
private Consumer<Integer> mScrimVisibilityCallback;
+ private float mScrimBehindAlpha;
+ private GradientColors mScrimInFrontColor;
private int mScrimVisibility;
- private LightBarController mLightBarController;
private DozeParameters mDozeParamenters;
private WakeLock mWakeLock;
private boolean mAlwaysOnEnabled;
@@ -75,19 +79,20 @@
@Before
public void setup() {
- mLightBarController = mock(LightBarController.class);
mScrimBehind = spy(new ScrimView(getContext()));
mScrimInFront = new ScrimView(getContext());
mWakeLock = mock(WakeLock.class);
mAlarmManager = mock(AlarmManager.class);
mAlwaysOnEnabled = true;
+ mScrimBehindAlphaCallback = (Float alpha) -> mScrimBehindAlpha = alpha;
+ mScrimInFrontColorCallback = (GradientColors color) -> mScrimInFrontColor = color;
mScrimVisibilityCallback = (Integer visible) -> mScrimVisibility = visible;
mDozeParamenters = mock(DozeParameters.class);
when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
- mScrimController = new SynchronousScrimController(mLightBarController, mScrimBehind,
- mScrimInFront, mScrimVisibilityCallback, mDozeParamenters,
- mAlarmManager);
+ mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
+ mScrimBehindAlphaCallback, mScrimInFrontColorCallback, mScrimVisibilityCallback,
+ mDozeParamenters, mAlarmManager);
}
@Test
@@ -206,6 +211,28 @@
}
@Test
+ public void panelExpansion() {
+ mScrimController.setPanelExpansion(0f);
+ mScrimController.setPanelExpansion(0.5f);
+ mScrimController.transitionTo(ScrimState.UNLOCKED);
+ mScrimController.finishAnimationsImmediately();
+
+ reset(mScrimBehind);
+ mScrimController.setPanelExpansion(0f);
+ mScrimController.setPanelExpansion(1.0f);
+ mScrimController.onPreDraw();
+
+ Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
+ mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
+
+ mScrimController.setPanelExpansion(0f);
+ mScrimController.onPreDraw();
+
+ Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
+ mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
+ }
+
+ @Test
public void panelExpansionAffectsAlpha() {
mScrimController.setPanelExpansion(0f);
mScrimController.setPanelExpansion(0.5f);
@@ -246,7 +273,7 @@
}
@Test
- public void scrimBlanksBeforeLeavingAoD() {
+ public void scrimBlanksBeforeLeavingAod() {
// Simulate unlock with fingerprint
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
@@ -455,6 +482,28 @@
}
}
+ @Test
+ public void testAnimatesTransitionToAod() {
+ when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
+ ScrimState.AOD.prepare(ScrimState.KEYGUARD);
+ Assert.assertFalse("No animation when ColorFade kicks in",
+ ScrimState.AOD.getAnimateChange());
+
+ reset(mDozeParamenters);
+ when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
+ ScrimState.AOD.prepare(ScrimState.KEYGUARD);
+ Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
+ ScrimState.AOD.getAnimateChange());
+ }
+
+ @Test
+ public void testViewsDontHaveFocusHighlight() {
+ Assert.assertFalse("Scrim shouldn't have focus highlight",
+ mScrimInFront.getDefaultFocusHighlightEnabled());
+ Assert.assertFalse("Scrim shouldn't have focus highlight",
+ mScrimBehind.getDefaultFocusHighlightEnabled());
+ }
+
/**
* Conserves old notification density after leaving state and coming back.
*
@@ -509,11 +558,12 @@
private boolean mAnimationCancelled;
boolean mOnPreDrawCalled;
- SynchronousScrimController(LightBarController lightBarController,
- ScrimView scrimBehind, ScrimView scrimInFront,
+ SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
+ Consumer<Float> scrimBehindAlphaListener,
+ Consumer<GradientColors> scrimInFrontColorListener,
Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
AlarmManager alarmManager) {
- super(lightBarController, scrimBehind, scrimInFront,
+ super(scrimBehind, scrimInFront, scrimBehindAlphaListener, scrimInFrontColorListener,
scrimVisibleListener, dozeParameters, alarmManager);
mHandler = new FakeHandler(Looper.myLooper());
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index a3dcd45..446c0a1 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -4779,7 +4779,7 @@
// CATEGORY: SETTINGS
ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK = 1210;
- // FIELD - Manually selected mobile network
+ // Not used anymore.
FIELD_MOBILE_NETWORK = 1211;
// OPEN: Settings > Network & Internet > Mobile network > Access Point Names
@@ -5578,6 +5578,41 @@
// OS: P
WIFI_SCANNING_NEEDED_DIALOG = 1373;
+ // OPEN: Settings > System > Gestures > Swipe up gesture
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_GESTURE_SWIPE_UP = 1374;
+
+ // OPEN: Settings > Storage > Dialog to format a storage volume
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_VOLUME_FORMAT = 1375;
+
+ // OPEN: DND onboarding activity > screen on checkbox
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ONBOARDING_SCREEN_ON = 1376;
+
+ // OPEN: DND onboarding activity > screen off checkbox
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ONBOARDING_SCREEN_OFF = 1377;
+
+ // OPEN: DND onboarding activity > Ok button
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ONBOARDING_OK = 1378;
+
+ // OPEN: DND onboarding activity > Settings link
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ONBOARDING_SETTINGS = 1379;
+
+ // OPEN: DND onboarding activity
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_ZEN_ONBOARDING = 1380;
+
// ---- End P Constants, all P 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 934ad88..595a1d9 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -422,6 +422,16 @@
// Indicates the number of times a scan request from an external background app was throttled.
optional int32 num_external_background_app_oneshot_scan_requests_throttled = 106;
+
+ // WifiLastResortWatchdog time milliseconds delta between trigger and first connection success
+ optional int64 watchdog_trigger_to_connection_success_duration_ms = 107 [default = -1];
+
+ // The number of times wifi experienced failures after watchdog has already been triggered and is
+ // waiting for a connection success
+ optional int64 watchdog_total_connection_failure_count_after_trigger = 108;
+
+ // Number of times DFS channel scans are requested in single scan requests.
+ optional int32 num_oneshot_has_dfs_channel_scans = 109;
}
// Information that gets logged for every WiFi connection.
@@ -1271,9 +1281,16 @@
// Start time of session in milliseconds.
optional int64 start_time_millis = 1;
- // The number of networks the lock was initialized with at start.
+ // The number of networks the lock was provided with at start.
optional int32 locked_networks_at_start = 2;
+ // The number of networks in the lock at the time of the initialize event. Only valid if
+ // initialize_event is recorded.
+ optional int32 locked_networks_at_initialize = 6;
+
+ // Event for fully initializing the WakeupLock (i.e. WakeupLock is "locked").
+ optional Event initialize_event = 7;
+
// Event for unlocking the WakeupLock. Does not occur if lock was initialized with 0 networks.
optional Event unlock_event = 3;
@@ -1289,4 +1306,10 @@
// Session information for every Wifi Wake session (up to a maximum of 10).
repeated Session sessions = 2;
+
+ // Number of ignored calls to start (due to WakeupController already being active).
+ optional int32 num_ignored_starts = 3;
+
+ // Number of Wifi Wake sessions that have recorded wakeup events.
+ optional int32 num_wakeups = 4;
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index e20c180..06707da 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -99,6 +99,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -1971,8 +1972,8 @@
return;
}
- if (value != null && !value.equals(viewState.getCurrentValue())) {
- if (value.isEmpty()
+ if (!Objects.equals(value, viewState.getCurrentValue())) {
+ if ((value == null || value.isEmpty())
&& viewState.getCurrentValue() != null
&& viewState.getCurrentValue().isText()
&& viewState.getCurrentValue().getTextValue() != null
@@ -1993,18 +1994,26 @@
// Must check if this update was caused by autofilling the view, in which
// case we just update the value, but not the UI.
final AutofillValue filledValue = viewState.getAutofilledValue();
- if (value.equals(filledValue)) {
+ if (filledValue != null && filledValue.equals(value)) {
+ if (sVerbose) {
+ Slog.v(TAG, "ignoring autofilled change on id " + id);
+ }
return;
}
// Update the internal state...
viewState.setState(ViewState.STATE_CHANGED);
//..and the UI
- if (value.isText()) {
- getUiForShowing().filterFillUi(value.getTextValue().toString(), this);
+ final String filterText;
+ if (value == null || !value.isText()) {
+ filterText = null;
} else {
- getUiForShowing().filterFillUi(null, this);
+ final CharSequence text = value.getTextValue();
+ // Text should never be null, but it doesn't hurt to check to avoid a
+ // system crash...
+ filterText = (text == null) ? null : text.toString();
}
+ getUiForShowing().filterFillUi(filterText, this);
}
break;
case ACTION_VIEW_ENTERED:
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a1ef1ed..6463bed 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -52,6 +52,8 @@
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.PacketKeepalive;
import android.net.IConnectivityManager;
+import android.net.IIpConnectivityMetrics;
+import android.net.INetdEventCallback;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
@@ -140,6 +142,7 @@
import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
+import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
@@ -155,6 +158,7 @@
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.connectivity.tethering.TetheringDependencies;
+import com.android.server.net.BaseNetdEventCallback;
import com.android.server.net.BaseNetworkObserver;
import com.android.server.net.LockdownVpnTracker;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -256,6 +260,7 @@
private INetworkStatsService mStatsService;
private INetworkPolicyManager mPolicyManager;
private NetworkPolicyManagerInternal mPolicyManagerInternal;
+ private IIpConnectivityMetrics mIpConnectivityMetrics;
private String mCurrentTcpBufferSizes;
@@ -414,6 +419,9 @@
// Handle changes in Private DNS settings.
private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37;
+ // Handle private DNS validation status updates.
+ private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38;
+
private static String eventName(int what) {
return sMagicDecoderRing.get(what, Integer.toString(what));
}
@@ -934,7 +942,7 @@
// Used only for testing.
// TODO: Delete this and either:
- // 1. Give Fake SettingsProvider the ability to send settings change notifications (requires
+ // 1. Give FakeSettingsProvider the ability to send settings change notifications (requires
// changing ContentResolver to make registerContentObserver non-final).
// 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
// by subclassing SettingsObserver.
@@ -943,6 +951,12 @@
mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
}
+ // See FakeSettingsProvider comment above.
+ @VisibleForTesting
+ void updatePrivateDnsSettings() {
+ mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
+ }
+
private void handleMobileDataAlwaysOn() {
final boolean enable = toBool(Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1));
@@ -972,8 +986,8 @@
}
private void registerPrivateDnsSettingsCallbacks() {
- for (Uri u : DnsManager.getPrivateDnsSettingsUris()) {
- mSettingsObserver.observe(u, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
+ for (Uri uri : DnsManager.getPrivateDnsSettingsUris()) {
+ mSettingsObserver.observe(uri, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
}
}
@@ -1026,8 +1040,12 @@
if (network == null) {
return null;
}
+ return getNetworkAgentInfoForNetId(network.netId);
+ }
+
+ private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
synchronized (mNetworkForNetId) {
- return mNetworkForNetId.get(network.netId);
+ return mNetworkForNetId.get(netId);
}
}
@@ -1167,9 +1185,7 @@
}
NetworkAgentInfo nai;
if (vpnNetId != NETID_UNSET) {
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(vpnNetId);
- }
+ nai = getNetworkAgentInfoForNetId(vpnNetId);
if (nai != null) return nai.network;
}
nai = getDefaultNetwork();
@@ -1545,6 +1561,41 @@
return true;
}
+ @VisibleForTesting
+ protected final INetdEventCallback mNetdEventCallback = new BaseNetdEventCallback() {
+ @Override
+ public void onPrivateDnsValidationEvent(int netId, String ipAddress,
+ String hostname, boolean validated) {
+ try {
+ mHandler.sendMessage(mHandler.obtainMessage(
+ EVENT_PRIVATE_DNS_VALIDATION_UPDATE,
+ new PrivateDnsValidationUpdate(netId,
+ InetAddress.parseNumericAddress(ipAddress),
+ hostname, validated)));
+ } catch (IllegalArgumentException e) {
+ loge("Error parsing ip address in validation event");
+ }
+ }
+ };
+
+ @VisibleForTesting
+ protected void registerNetdEventCallback() {
+ mIpConnectivityMetrics =
+ (IIpConnectivityMetrics) IIpConnectivityMetrics.Stub.asInterface(
+ ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
+ if (mIpConnectivityMetrics == null) {
+ Slog.wtf(TAG, "Missing IIpConnectivityMetrics");
+ }
+
+ try {
+ mIpConnectivityMetrics.addNetdEventCallback(
+ INetdEventCallback.CALLBACK_CALLER_CONNECTIVITY_SERVICE,
+ mNetdEventCallback);
+ } catch (Exception e) {
+ loge("Error registering netd callback: " + e);
+ }
+ }
+
private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() {
@Override
public void onUidRulesChanged(int uid, int uidRules) {
@@ -1730,6 +1781,7 @@
void systemReady() {
loadGlobalProxy();
+ registerNetdEventCallback();
synchronized (this) {
mSystemReady = true;
@@ -2155,41 +2207,21 @@
default:
return false;
case NetworkMonitor.EVENT_NETWORK_TESTED: {
- final NetworkAgentInfo nai;
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(msg.arg2);
- }
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
if (nai == null) break;
final boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
final boolean wasValidated = nai.lastValidated;
final boolean wasDefault = isDefaultNetwork(nai);
- final PrivateDnsConfig privateDnsCfg = (msg.obj instanceof PrivateDnsConfig)
- ? (PrivateDnsConfig) msg.obj : null;
final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";
- final boolean reevaluationRequired;
- final String logMsg;
- if (valid) {
- reevaluationRequired = updatePrivateDns(nai, privateDnsCfg);
- logMsg = (DBG && (privateDnsCfg != null))
- ? " with " + privateDnsCfg.toString() : "";
- } else {
- reevaluationRequired = false;
- logMsg = (DBG && !TextUtils.isEmpty(redirectUrl))
- ? " with redirect to " + redirectUrl : "";
- }
if (DBG) {
+ final String logMsg = !TextUtils.isEmpty(redirectUrl)
+ ? " with redirect to " + redirectUrl
+ : "";
log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg);
}
- // If there is a change in Private DNS configuration,
- // trigger reevaluation of the network to test it.
- if (reevaluationRequired) {
- nai.networkMonitor.sendMessage(
- NetworkMonitor.CMD_FORCE_REEVALUATION, Process.SYSTEM_UID);
- break;
- }
if (valid != nai.lastValidated) {
if (wasDefault) {
metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
@@ -2218,10 +2250,7 @@
case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
final int netId = msg.arg2;
final boolean visible = toBool(msg.arg1);
- final NetworkAgentInfo nai;
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(netId);
- }
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
// If captive portal status has changed, update capabilities or disconnect.
if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
final int oldScore = nai.getCurrentScore();
@@ -2252,18 +2281,10 @@
break;
}
case NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
- final NetworkAgentInfo nai;
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(msg.arg2);
- }
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
if (nai == null) break;
- final PrivateDnsConfig cfg = (PrivateDnsConfig) msg.obj;
- final boolean reevaluationRequired = updatePrivateDns(nai, cfg);
- if (nai.lastValidated && reevaluationRequired) {
- nai.networkMonitor.sendMessage(
- NetworkMonitor.CMD_FORCE_REEVALUATION, Process.SYSTEM_UID);
- }
+ updatePrivateDns(nai, (PrivateDnsConfig) msg.obj);
break;
}
}
@@ -2301,61 +2322,50 @@
}
}
+ private boolean networkRequiresValidation(NetworkAgentInfo nai) {
+ return NetworkMonitor.isValidationRequired(
+ mDefaultRequest.networkCapabilities, nai.networkCapabilities);
+ }
+
private void handlePrivateDnsSettingsChanged() {
final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- // Private DNS only ever applies to networks that might provide
- // Internet access and therefore also require validation.
- if (!NetworkMonitor.isValidationRequired(
- mDefaultRequest.networkCapabilities, nai.networkCapabilities)) {
- continue;
- }
-
- // Notify the NetworkMonitor thread in case it needs to cancel or
- // schedule DNS resolutions. If a DNS resolution is required the
- // result will be sent back to us.
- nai.networkMonitor.notifyPrivateDnsSettingsChanged(cfg);
-
- if (!cfg.inStrictMode()) {
- // No strict mode hostname DNS resolution needed, so just update
- // DNS settings directly. In opportunistic and "off" modes this
- // just reprograms netd with the network-supplied DNS servers
- // (and of course the boolean of whether or not to attempt TLS).
- //
- // TODO: Consider code flow parity with strict mode, i.e. having
- // NetworkMonitor relay the PrivateDnsConfig back to us and then
- // performing this call at that time.
- updatePrivateDns(nai, cfg);
+ handlePerNetworkPrivateDnsConfig(nai, cfg);
+ if (networkRequiresValidation(nai)) {
+ handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
}
}
}
- private boolean updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
- final boolean reevaluationRequired = true;
- final boolean dontReevaluate = false;
+ private void handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg) {
+ // Private DNS only ever applies to networks that might provide
+ // Internet access and therefore also require validation.
+ if (!networkRequiresValidation(nai)) return;
- final PrivateDnsConfig oldCfg = mDnsManager.updatePrivateDns(nai.network, newCfg);
+ // Notify the NetworkMonitor thread in case it needs to cancel or
+ // schedule DNS resolutions. If a DNS resolution is required the
+ // result will be sent back to us.
+ nai.networkMonitor.notifyPrivateDnsSettingsChanged(cfg);
+
+ // With Private DNS bypass support, we can proceed to update the
+ // Private DNS config immediately, even if we're in strict mode
+ // and have not yet resolved the provider name into a set of IPs.
+ updatePrivateDns(nai, cfg);
+ }
+
+ private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
+ mDnsManager.updatePrivateDns(nai.network, newCfg);
updateDnses(nai.linkProperties, null, nai.network.netId);
+ }
- if (newCfg == null) {
- if (oldCfg == null) return dontReevaluate;
- return oldCfg.useTls ? reevaluationRequired : dontReevaluate;
+ private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) {
+ NetworkAgentInfo nai = getNetworkAgentInfoForNetId(update.netId);
+ if (nai == null) {
+ return;
}
-
- if (oldCfg == null) {
- return newCfg.useTls ? reevaluationRequired : dontReevaluate;
- }
-
- if (oldCfg.useTls != newCfg.useTls) {
- return reevaluationRequired;
- }
-
- if (newCfg.inStrictMode() && !Objects.equals(oldCfg.hostname, newCfg.hostname)) {
- return reevaluationRequired;
- }
-
- return dontReevaluate;
+ mDnsManager.updatePrivateDnsValidation(update);
+ handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
}
private void updateLingerState(NetworkAgentInfo nai, long now) {
@@ -3048,6 +3058,10 @@
case EVENT_PRIVATE_DNS_SETTINGS_CHANGED:
handlePrivateDnsSettingsChanged();
break;
+ case EVENT_PRIVATE_DNS_VALIDATION_UPDATE:
+ handlePrivateDnsValidationUpdate(
+ (PrivateDnsValidationUpdate) msg.obj);
+ break;
}
}
}
@@ -3300,7 +3314,7 @@
if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
return;
}
- nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
+ nai.networkMonitor.forceReevaluation(uid);
}
private ProxyInfo getDefaultProxy() {
@@ -4621,6 +4635,11 @@
updateRoutes(newLp, oldLp, netId);
updateDnses(newLp, oldLp, netId);
+ // Make sure LinkProperties represents the latest private DNS status.
+ // This does not need to be done before updateDnses because the
+ // LinkProperties are not the source of the private DNS configuration.
+ // updateDnses will fetch the private DNS configuration from DnsManager.
+ mDnsManager.updatePrivateDnsStatus(netId, newLp);
// Start or stop clat accordingly to network state.
networkAgent.updateClat(mNetd);
@@ -4919,7 +4938,7 @@
}
public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
- if (mNetworkForNetId.get(nai.network.netId) != nai) {
+ if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) {
// Ignore updates for disconnected networks
return;
}
@@ -5495,6 +5514,7 @@
if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
networkAgent.everConnected = true;
+ handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
updateLinkProperties(networkAgent, null);
notifyIfacesChangedForNetworkStats();
@@ -5911,4 +5931,4 @@
pw.println(" Get airplane mode.");
}
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 45c9a71..48bb409 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -219,7 +219,7 @@
# DisplayManagerService.java
# ---------------------------
# Auto-brightness adjustments by the user.
-35000 auto_brightness_adj (old_adj|5),(old_lux|5),(old_brightness|5),(old_gamma|5),(new_adj|5),(new_lux|5),(new_brightness|5),(new_gamma|5)
+35000 auto_brightness_adj (old_lux|5),(old_brightness|5),(new_lux|5),(new_brightness|5)
# ---------------------------
# ConnectivityService.java
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 33f7769..80d7ac9 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -128,6 +128,30 @@
}
};
+ public static final class Lifecycle extends SystemService {
+ private final NetworkScoreService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ mService = new NetworkScoreService(context);
+ }
+
+ @Override
+ public void onStart() {
+ Log.i(TAG, "Registering " + Context.NETWORK_SCORE_SERVICE);
+ publishBinderService(Context.NETWORK_SCORE_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_SYSTEM_SERVICES_READY) {
+ mService.systemReady();
+ } else if (phase == PHASE_BOOT_COMPLETED) {
+ mService.systemRunning();
+ }
+ }
+ }
+
/**
* Clears scores when the active scorer package is no longer valid and
* manages the service connection.
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 752c44a..66c2b07 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -53,6 +53,7 @@
import android.provider.Settings.SettingNotFoundException;
import android.util.DebugUtils;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.InputDevice;
import android.media.AudioAttributes;
@@ -91,7 +92,7 @@
private final boolean mAllowPriorityVibrationsInLowPowerMode;
private final boolean mSupportsAmplitudeControl;
private final int mDefaultVibrationAmplitude;
- private final VibrationEffect[] mFallbackEffects;
+ private final SparseArray<VibrationEffect> mFallbackEffects;
private final WorkSource mTmpWorkSource = new WorkSource();
private final Handler mH = new Handler();
private final Object mLock = new Object();
@@ -177,6 +178,7 @@
switch (prebaked.getId()) {
case VibrationEffect.EFFECT_CLICK:
case VibrationEffect.EFFECT_DOUBLE_CLICK:
+ case VibrationEffect.EFFECT_HEAVY_CLICK:
case VibrationEffect.EFFECT_TICK:
return true;
default:
@@ -293,7 +295,11 @@
com.android.internal.R.array.config_clockTickVibePattern);
VibrationEffect tickEffect = createEffect(tickEffectTimings);
- mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect, tickEffect };
+ mFallbackEffects = new SparseArray<VibrationEffect>();
+ mFallbackEffects.put(VibrationEffect.EFFECT_CLICK, clickEffect);
+ mFallbackEffects.put(VibrationEffect.EFFECT_DOUBLE_CLICK, doubleClickEffect);
+ mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect);
+ mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, clickEffect);
}
private static VibrationEffect createEffect(long[] timings) {
@@ -960,10 +966,7 @@
}
private VibrationEffect getFallbackEffect(int effectId) {
- if (effectId < 0 || effectId >= mFallbackEffects.length) {
- return null;
- }
- return mFallbackEffects[effectId];
+ return mFallbackEffects.get(effectId);
}
/**
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 4a8bc87..fac3f92 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -16,7 +16,6 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -44,7 +43,6 @@
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.graphics.Point;
-import android.graphics.Rect;
import android.util.IntArray;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -702,57 +700,52 @@
}
/**
- * @return the stack currently above the home stack. Can be null if there is no home stack, or
- * the home stack is already on top.
+ * @return the stack currently above the {@param stack}. Can be null if the {@param stack} is
+ * already top-most.
*/
- ActivityStack getStackAboveHome() {
- if (mHomeStack == null) {
- // Skip if there is no home stack
- return null;
- }
-
- final int stackIndex = mStacks.indexOf(mHomeStack) + 1;
+ ActivityStack getStackAbove(ActivityStack stack) {
+ final int stackIndex = mStacks.indexOf(stack) + 1;
return (stackIndex < mStacks.size()) ? mStacks.get(stackIndex) : null;
}
/**
- * Adjusts the home stack behind the last visible stack in the display if necessary. Generally
- * used in conjunction with {@link #moveHomeStackBehindStack}.
+ * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
+ * Generally used in conjunction with {@link #moveStackBehindStack}.
*/
- void moveHomeStackBehindBottomMostVisibleStack() {
- if (mHomeStack == null || mHomeStack.shouldBeVisible(null)) {
- // Skip if there is no home stack, or if it is already visible
+ void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
+ if (stack.shouldBeVisible(null)) {
+ // Skip if the stack is already visible
return;
}
- // Move the home stack to the bottom to not affect the following visibility checks
- positionChildAtBottom(mHomeStack);
+ // Move the stack to the bottom to not affect the following visibility checks
+ positionChildAtBottom(stack);
- // Find the next position where the homes stack should be placed
+ // Find the next position where the stack should be placed
final int numStacks = mStacks.size();
for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (stack == mHomeStack) {
+ final ActivityStack s = mStacks.get(stackNdx);
+ if (s == stack) {
continue;
}
- final int winMode = stack.getWindowingMode();
+ final int winMode = s.getWindowingMode();
final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN ||
winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
- if (stack.shouldBeVisible(null) && isValidWindowingMode) {
- // Move the home stack to behind this stack
- positionChildAt(mHomeStack, Math.max(0, stackNdx - 1));
+ if (s.shouldBeVisible(null) && isValidWindowingMode) {
+ // Move the provided stack to behind this stack
+ positionChildAt(stack, Math.max(0, stackNdx - 1));
break;
}
}
}
/**
- * Moves the home stack behind the given {@param stack} if possible. If {@param stack} is not
- * currently in the display, then then the home stack is moved to the back. Generally used in
- * conjunction with {@link #moveHomeStackBehindBottomMostVisibleStack}.
+ * Moves the {@param stack} behind the given {@param behindStack} if possible. If
+ * {@param behindStack} is not currently in the display, then then the stack is moved to the
+ * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
*/
- void moveHomeStackBehindStack(ActivityStack behindStack) {
- if (behindStack == null || behindStack == mHomeStack) {
+ void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
+ if (behindStack == null || behindStack == stack) {
return;
}
@@ -760,11 +753,11 @@
// list, so we need to adjust the insertion index to account for the removed index
// TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
// position internally
- final int homeStackIndex = mStacks.indexOf(mHomeStack);
+ final int stackIndex = mStacks.indexOf(stack);
final int behindStackIndex = mStacks.indexOf(behindStack);
- final int insertIndex = homeStackIndex <= behindStackIndex
+ final int insertIndex = stackIndex <= behindStackIndex
? behindStackIndex - 1 : behindStackIndex;
- positionChildAt(mHomeStack, Math.max(0, insertIndex));
+ positionChildAt(stack, Math.max(0, insertIndex));
}
boolean isSleeping() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index adf3480..04d54e1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -39,6 +39,7 @@
import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
import static android.app.AppOpsManager.OP_NONE;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -51,6 +52,7 @@
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
+import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
@@ -117,6 +119,7 @@
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
+import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
import static android.provider.Settings.System.FONT_SCALE;
@@ -205,8 +208,8 @@
import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
-import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION;
-import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_HOME_IN_PLACE;
+import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
+import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -1281,17 +1284,24 @@
private final class FontScaleSettingObserver extends ContentObserver {
private final Uri mFontScaleUri = Settings.System.getUriFor(FONT_SCALE);
+ private final Uri mHideErrorDialogsUri = Settings.Global.getUriFor(HIDE_ERROR_DIALOGS);
public FontScaleSettingObserver() {
super(mHandler);
ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(mFontScaleUri, false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(mHideErrorDialogsUri, false, this,
+ UserHandle.USER_ALL);
}
@Override
public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
if (mFontScaleUri.equals(uri)) {
updateFontScaleIfNeeded(userId);
+ } else if (mHideErrorDialogsUri.equals(uri)) {
+ synchronized (ActivityManagerService.this) {
+ updateShouldShowDialogsLocked(getGlobalConfiguration());
+ }
}
}
}
@@ -1948,7 +1958,7 @@
final ActivityManagerConstants mConstants;
// Encapsulates the global setting "hidden_api_blacklist_exemptions"
- final HiddenApiBlacklist mHiddenApiBlacklist;
+ final HiddenApiSettings mHiddenApiBlacklist;
PackageManagerInternal mPackageManagerInt;
@@ -2883,17 +2893,19 @@
}
/**
- * Encapsulates the global setting "hidden_api_blacklist_exemptions", including tracking the
- * latest value via a content observer.
+ * Encapsulates global settings related to hidden API enforcement behaviour, including tracking
+ * the latest value via a content observer.
*/
- static class HiddenApiBlacklist extends ContentObserver {
+ static class HiddenApiSettings extends ContentObserver {
private final Context mContext;
private boolean mBlacklistDisabled;
private String mExemptionsStr;
private List<String> mExemptions = Collections.emptyList();
+ @HiddenApiEnforcementPolicy private int mPolicyPreP = HIDDEN_API_ENFORCEMENT_DEFAULT;
+ @HiddenApiEnforcementPolicy private int mPolicyP = HIDDEN_API_ENFORCEMENT_DEFAULT;
- public HiddenApiBlacklist(Handler handler, Context context) {
+ public HiddenApiSettings(Handler handler, Context context) {
super(handler);
mContext = context;
}
@@ -2903,6 +2915,14 @@
Settings.Global.getUriFor(Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS),
false,
this);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS),
+ false,
+ this);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_P_APPS),
+ false,
+ this);
update();
}
@@ -2922,13 +2942,32 @@
}
zygoteProcess.setApiBlacklistExemptions(mExemptions);
}
+ mPolicyPreP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS);
+ mPolicyP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_P_APPS);
+ }
+ private @HiddenApiEnforcementPolicy int getValidEnforcementPolicy(String settingsKey) {
+ int policy = Settings.Global.getInt(mContext.getContentResolver(), settingsKey,
+ ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT);
+ if (ApplicationInfo.isValidHiddenApiEnforcementPolicy(policy)) {
+ return policy;
+ } else {
+ return ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
+ }
}
boolean isDisabled() {
return mBlacklistDisabled;
}
+ @HiddenApiEnforcementPolicy int getPolicyForPrePApps() {
+ return mPolicyPreP;
+ }
+
+ @HiddenApiEnforcementPolicy int getPolicyForPApps() {
+ return mPolicyP;
+ }
+
public void onChange(boolean selfChange) {
update();
}
@@ -3101,7 +3140,7 @@
}
};
- mHiddenApiBlacklist = new HiddenApiBlacklist(mHandler, mContext);
+ mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
@@ -4217,6 +4256,9 @@
}
if (!disableHiddenApiChecks && !mHiddenApiBlacklist.isDisabled()) {
+ app.info.maybeUpdateHiddenApiEnforcementPolicy(
+ mHiddenApiBlacklist.getPolicyForPrePApps(),
+ mHiddenApiBlacklist.getPolicyForPApps());
@HiddenApiEnforcementPolicy int policy =
app.info.getHiddenApiEnforcementPolicy();
int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
@@ -5249,8 +5291,8 @@
try {
synchronized (this) {
mWindowManager.cancelRecentsAnimation(restoreHomeStackPosition
- ? REORDER_MOVE_HOME_TO_ORIGINAL_POSITION
- : REORDER_KEEP_HOME_IN_PLACE);
+ ? REORDER_MOVE_TO_ORIGINAL_POSITION
+ : REORDER_KEEP_IN_PLACE);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -12958,9 +13000,13 @@
} catch (RemoteException exc) {
// Ignore.
}
+ return isBackgroundRestrictedNoCheck(callingUid, packageName);
+ }
+
+ boolean isBackgroundRestrictedNoCheck(final int uid, final String packageName) {
final int mode = mAppOpsService.checkOperation(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
- callingUid, packageName);
- return (mode != AppOpsManager.MODE_ALLOWED);
+ uid, packageName);
+ return mode != AppOpsManager.MODE_ALLOWED;
}
@Override
@@ -21055,6 +21101,7 @@
}
}
+ final String action = intent.getAction();
BroadcastOptions brOptions = null;
if (bOptions != null) {
brOptions = new BroadcastOptions(bOptions);
@@ -21075,11 +21122,16 @@
throw new SecurityException(msg);
}
}
+ if (brOptions.isDontSendToRestrictedApps()
+ && isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
+ Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage
+ + " has background restrictions");
+ return ActivityManager.START_CANCELED;
+ }
}
// Verify that protected broadcasts are only being sent by system code,
// and that system code is only sending protected broadcasts.
- final String action = intent.getAction();
final boolean isProtectedBroadcast;
try {
isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
@@ -21901,8 +21953,6 @@
"com.android.frameworks.locationtests",
"com.android.frameworks.coretests.privacy",
"com.android.settings.ui",
- "com.android.perftests.core",
- "com.android.perftests.multiuser",
};
public boolean startInstrumentation(ComponentName className,
@@ -22440,7 +22490,7 @@
mUserController.getCurrentUserId());
// TODO: If our config changes, should we auto dismiss any currently showing dialogs?
- mShowDialogs = shouldShowDialogs(mTempConfig);
+ updateShouldShowDialogsLocked(mTempConfig);
AttributeCache ac = AttributeCache.instance();
if (ac != null) {
@@ -22695,7 +22745,7 @@
* A thought: SystemUI might also want to get told about this, the Power
* dialog / global actions also might want different behaviors.
*/
- private static boolean shouldShowDialogs(Configuration config) {
+ private void updateShouldShowDialogsLocked(Configuration config) {
final boolean inputMethodExists = !(config.keyboard == Configuration.KEYBOARD_NOKEYS
&& config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH
&& config.navigation == Configuration.NAVIGATION_NONAV);
@@ -22704,7 +22754,9 @@
&& !(modeType == Configuration.UI_MODE_TYPE_WATCH && Build.IS_USER)
&& modeType != Configuration.UI_MODE_TYPE_TELEVISION
&& modeType != Configuration.UI_MODE_TYPE_VR_HEADSET);
- return inputMethodExists && uiModeSupportsDialogs;
+ final boolean hideDialogsSet = Settings.Global.getInt(mContext.getContentResolver(),
+ HIDE_ERROR_DIALOGS, 0) != 0;
+ mShowDialogs = inputMethodExists && uiModeSupportsDialogs && !hideDialogsSet;
}
@Override
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 1d305fb..2b988d3 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -534,8 +534,8 @@
final TaskRecord tr = mTasks.get(i);
final String taskPackageName =
tr.getBaseIntent().getComponent().getPackageName();
- if (tr.userId != userId) return;
- if (!taskPackageName.equals(packageName)) return;
+ if (tr.userId != userId) continue;
+ if (!taskPackageName.equals(packageName)) continue;
mService.mStackSupervisor.removeTaskByIdLocked(tr.taskId, true, REMOVE_FROM_RECENTS,
"remove-package-task");
@@ -1255,7 +1255,7 @@
for (int i = 0; i < recentsCount; i++) {
final TaskRecord tr = mTasks.get(i);
if (task != tr) {
- if (!task.hasCompatibleActivityType(tr)) {
+ if (!task.hasCompatibleActivityType(tr) || task.userId != tr.userId) {
continue;
}
final Intent trIntent = tr.intent;
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index ad25099..17eeb5b 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -18,19 +18,20 @@
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.WindowManager.TRANSIT_NONE;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_HOME_IN_PLACE;
-import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION;
-import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_TOP;
+import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
+import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
+import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Intent;
-import android.os.Handler;
import android.os.RemoteException;
import android.os.Trace;
import android.util.Slog;
@@ -51,16 +52,20 @@
private final ActivityStartController mActivityStartController;
private final WindowManagerService mWindowManager;
private final UserController mUserController;
+ private final ActivityDisplay mDefaultDisplay;
private final int mCallingPid;
- // The stack to restore the home stack behind when the animation is finished
- private ActivityStack mRestoreHomeBehindStack;
+ private int mTargetActivityType;
+
+ // The stack to restore the target stack behind when the animation is finished
+ private ActivityStack mRestoreTargetBehindStack;
RecentsAnimation(ActivityManagerService am, ActivityStackSupervisor stackSupervisor,
ActivityStartController activityStartController, WindowManagerService wm,
UserController userController, int callingPid) {
mService = am;
mStackSupervisor = stackSupervisor;
+ mDefaultDisplay = stackSupervisor.getDefaultDisplay();
mActivityStartController = activityStartController;
mWindowManager = wm;
mUserController = userController;
@@ -76,23 +81,31 @@
return;
}
- // If the existing home activity is already on top, then cancel
- ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
- final boolean hasExistingHomeActivity = homeActivity != null;
- if (hasExistingHomeActivity) {
- final ActivityDisplay display = homeActivity.getDisplay();
- mRestoreHomeBehindStack = display.getStackAboveHome();
- if (mRestoreHomeBehindStack == null) {
+ // If the activity is associated with the recents stack, then try and get that first
+ mTargetActivityType = intent.getComponent() != null
+ && recentsComponent.equals(intent.getComponent())
+ ? ACTIVITY_TYPE_RECENTS
+ : ACTIVITY_TYPE_HOME;
+ final ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
+ mTargetActivityType);
+ ActivityRecord targetActivity = targetStack != null
+ ? targetStack.getTopActivity()
+ : null;
+ final boolean hasExistingActivity = targetActivity != null;
+ if (hasExistingActivity) {
+ final ActivityDisplay display = targetActivity.getDisplay();
+ mRestoreTargetBehindStack = display.getStackAbove(targetStack);
+ if (mRestoreTargetBehindStack == null) {
notifyAnimationCancelBeforeStart(recentsAnimationRunner);
return;
}
}
- // Send launch hint if we are actually launching home. If it's already visible (shouldn't
- // happen in general) we don't need to send it.
- if (homeActivity == null || !homeActivity.visible) {
+ // Send launch hint if we are actually launching the target. If it's already visible
+ // (shouldn't happen in general) we don't need to send it.
+ if (targetActivity == null || !targetActivity.visible) {
mStackSupervisor.sendPowerHintForLaunchStartIfNeeded(true /* forceSend */,
- homeActivity);
+ targetActivity);
}
mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
@@ -102,48 +115,49 @@
mWindowManager.deferSurfaceLayout();
try {
final ActivityDisplay display;
- if (hasExistingHomeActivity) {
- // Move the home activity into place for the animation if it is not already top most
- display = homeActivity.getDisplay();
- display.moveHomeStackBehindBottomMostVisibleStack();
+ if (hasExistingActivity) {
+ // Move the recents activity into place for the animation if it is not top most
+ display = targetActivity.getDisplay();
+ display.moveStackBehindBottomMostVisibleStack(targetStack);
} else {
- // No home activity
- final ActivityOptions opts = ActivityOptions.makeBasic();
- opts.setLaunchActivityType(ACTIVITY_TYPE_HOME);
- opts.setAvoidMoveToFront();
+ // No recents activity
+ ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchActivityType(mTargetActivityType);
+ options.setAvoidMoveToFront();
intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
mActivityStartController
- .obtainStarter(intent, "startRecentsActivity_noHomeActivity")
+ .obtainStarter(intent, "startRecentsActivity_noTargetActivity")
.setCallingUid(recentsUid)
.setCallingPackage(recentsComponent.getPackageName())
- .setActivityOptions(SafeActivityOptions.fromBundle(opts.toBundle()))
+ .setActivityOptions(SafeActivityOptions.fromBundle(options.toBundle()))
.setMayWait(mUserController.getCurrentUserId())
.execute();
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
- homeActivity = mStackSupervisor.getHomeActivity();
- display = homeActivity.getDisplay();
+ targetActivity = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
+ mTargetActivityType).getTopActivity();
+ display = targetActivity.getDisplay();
// TODO: Maybe wait for app to draw in this particular case?
}
- // Mark the home activity as launch-behind to bump its visibility for the
+ // Mark the target activity as launch-behind to bump its visibility for the
// duration of the gesture that is driven by the recents component
- homeActivity.mLaunchTaskBehind = true;
+ targetActivity.mLaunchTaskBehind = true;
// Fetch all the surface controls and pass them to the client to get the animation
// started
- mWindowManager.cancelRecentsAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
- mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this,
- display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds());
+ mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
+ mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
+ this, display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds());
// If we updated the launch-behind state, update the visibility of the activities after
// we fetch the visible tasks to be controlled by the animation
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(START_TASK_TO_FRONT,
- homeActivity);
+ targetActivity);
} finally {
mWindowManager.continueSurfaceLayout();
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
@@ -155,9 +169,9 @@
synchronized (mService) {
if (mWindowManager.getRecentsAnimationController() == null) return;
- // Just to be sure end the launch hint in case home was never launched. However, if
- // we're keeping home and making it visible, we can leave it on.
- if (reorderMode != REORDER_KEEP_HOME_IN_PLACE) {
+ // Just to be sure end the launch hint in case the target activity was never launched.
+ // However, if we're keeping the activity and making it visible, we can leave it on.
+ if (reorderMode != REORDER_KEEP_IN_PLACE) {
mStackSupervisor.sendPowerHintForLaunchEndIfNeeded();
}
@@ -170,26 +184,27 @@
try {
mWindowManager.cleanupRecentsAnimation(reorderMode);
- final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
- if (homeActivity == null) {
+ final ActivityStack targetStack = mDefaultDisplay.getStack(
+ WINDOWING_MODE_UNDEFINED, mTargetActivityType);
+ final ActivityRecord targetActivity = targetStack.getTopActivity();
+ if (targetActivity == null) {
return;
}
// Restore the launched-behind state
- homeActivity.mLaunchTaskBehind = false;
+ targetActivity.mLaunchTaskBehind = false;
- if (reorderMode == REORDER_MOVE_HOME_TO_TOP) {
- // Bring the home stack to the front
- final ActivityStack homeStack = homeActivity.getStack();
- mStackSupervisor.mNoAnimActivities.add(homeActivity);
- homeStack.moveToFront("RecentsAnimation.onAnimationFinished()");
- } else if (reorderMode == REORDER_MOVE_HOME_TO_ORIGINAL_POSITION){
- // Restore the home stack to its previous position
- final ActivityDisplay display = homeActivity.getDisplay();
- display.moveHomeStackBehindStack(mRestoreHomeBehindStack);
+ if (reorderMode == REORDER_MOVE_TO_TOP) {
+ // Bring the target stack to the front
+ mStackSupervisor.mNoAnimActivities.add(targetActivity);
+ targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
+ } else if (reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION){
+ // Restore the target stack to its previous position
+ final ActivityDisplay display = targetActivity.getDisplay();
+ display.moveStackBehindStack(targetStack, mRestoreTargetBehindStack);
} else {
- // Keep home stack in place, nothing changes, so ignore the transition logic
- // below
+ // Keep target stack in place, nothing changes, so ignore the transition
+ // logic below
return;
}
@@ -202,8 +217,9 @@
mWindowManager.executeAppTransition();
// After reordering the stacks, reset the minimized state. At this point, either
- // home is now top-most and we will stay minimized (if in split-screen), or we
- // will have returned to the app, and the minimized state should be reset
+ // the target activity is now top-most and we will stay minimized (if in
+ // split-screen), or we will have returned to the app, and the minimized state
+ // should be reset
mWindowManager.checkSplitScreenMinimizedChanged(true /* animate */);
} finally {
mWindowManager.continueSurfaceLayout();
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index a294334..b6e414a2 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1184,11 +1184,6 @@
Slog.w(TAG, "No user info for user #" + targetUserId);
return false;
}
- if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mInjector.getContext())) {
- Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId
- + " when device is in demo mode");
- return false;
- }
if (!targetUserInfo.supportsSwitchTo()) {
Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
return false;
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 5579849..7aaac06 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -37,10 +37,10 @@
import android.net.dns.ResolvUtil;
import android.os.Binder;
import android.os.INetworkManagementService;
-import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.Pair;
import android.util.Slog;
import com.android.server.connectivity.MockableSystemProperties;
@@ -50,8 +50,12 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Objects;
import java.util.stream.Collectors;
+import java.util.Set;
import java.util.StringJoiner;
@@ -61,10 +65,56 @@
* This class it NOT designed for concurrent access. Furthermore, all non-static
* methods MUST be called from ConnectivityService's thread.
*
+ * [ Private DNS ]
+ * The code handling Private DNS is spread across several components, but this
+ * seems like the least bad place to collect all the observations.
+ *
+ * Private DNS handling and updating occurs in response to several different
+ * events. Each is described here with its corresponding intended handling.
+ *
+ * [A] Event: A new network comes up.
+ * Mechanics:
+ * [1] ConnectivityService gets notifications from NetworkAgents.
+ * [2] in updateNetworkInfo(), the first time the NetworkAgent goes into
+ * into CONNECTED state, the Private DNS configuration is retrieved,
+ * programmed, and strict mode hostname resolution (if applicable) is
+ * enqueued in NetworkAgent's NetworkMonitor, via a call to
+ * handlePerNetworkPrivateDnsConfig().
+ * [3] Re-resolution of strict mode hostnames that fail to return any
+ * IP addresses happens inside NetworkMonitor; it sends itself a
+ * delayed CMD_EVALUATE_PRIVATE_DNS message in a simple backoff
+ * schedule.
+ * [4] Successfully resolved hostnames are sent to ConnectivityService
+ * inside an EVENT_PRIVATE_DNS_CONFIG_RESOLVED message. The resolved
+ * IP addresses are programmed into netd via:
+ *
+ * updatePrivateDns() -> updateDnses()
+ *
+ * both of which make calls into DnsManager.
+ * [5] Upon a successful hostname resolution NetworkMonitor initiates a
+ * validation attempt in the form of a lookup for a one-time hostname
+ * that uses Private DNS.
+ *
+ * [B] Event: Private DNS settings are changed.
+ * Mechanics:
+ * [1] ConnectivityService gets notifications from its SettingsObserver.
+ * [2] handlePrivateDnsSettingsChanged() is called, which calls
+ * handlePerNetworkPrivateDnsConfig() and the process proceeds
+ * as if from A.3 above.
+ *
+ * [C] Event: An application calls ConnectivityManager#reportBadNetwork().
+ * Mechanics:
+ * [1] NetworkMonitor is notified and initiates a reevaluation, which
+ * always bypasses Private DNS.
+ * [2] Once completed, NetworkMonitor checks if strict mode is in operation
+ * and if so enqueues another evaluation of Private DNS, as if from
+ * step A.5 above.
+ *
* @hide
*/
public class DnsManager {
private static final String TAG = DnsManager.class.getSimpleName();
+ private static final PrivateDnsConfig PRIVATE_DNS_OFF = new PrivateDnsConfig();
/* Defaults for resolver parameters. */
private static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
@@ -138,11 +188,89 @@
};
}
+ public static class PrivateDnsValidationUpdate {
+ final public int netId;
+ final public InetAddress ipAddress;
+ final public String hostname;
+ final public boolean validated;
+
+ public PrivateDnsValidationUpdate(int netId, InetAddress ipAddress,
+ String hostname, boolean validated) {
+ this.netId = netId;
+ this.ipAddress = ipAddress;
+ this.hostname = hostname;
+ this.validated = validated;
+ }
+ }
+
+ private static class PrivateDnsValidationStatuses {
+ enum ValidationStatus {
+ IN_PROGRESS,
+ FAILED,
+ SUCCEEDED
+ }
+
+ // Validation statuses of <hostname, ipAddress> pairs for a single netId
+ private Map<Pair<String, InetAddress>, ValidationStatus> mValidationMap;
+
+ private PrivateDnsValidationStatuses() {
+ mValidationMap = new HashMap<>();
+ }
+
+ private boolean hasValidatedServer() {
+ for (ValidationStatus status : mValidationMap.values()) {
+ if (status == ValidationStatus.SUCCEEDED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void updateTrackedDnses(String[] ipAddresses, String hostname) {
+ Set<Pair<String, InetAddress>> latestDnses = new HashSet<>();
+ for (String ipAddress : ipAddresses) {
+ try {
+ latestDnses.add(new Pair(hostname,
+ InetAddress.parseNumericAddress(ipAddress)));
+ } catch (IllegalArgumentException e) {}
+ }
+ // Remove <hostname, ipAddress> pairs that should not be tracked.
+ for (Iterator<Map.Entry<Pair<String, InetAddress>, ValidationStatus>> it =
+ mValidationMap.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry<Pair<String, InetAddress>, ValidationStatus> entry = it.next();
+ if (!latestDnses.contains(entry.getKey())) {
+ it.remove();
+ }
+ }
+ // Add new <hostname, ipAddress> pairs that should be tracked.
+ for (Pair<String, InetAddress> p : latestDnses) {
+ if (!mValidationMap.containsKey(p)) {
+ mValidationMap.put(p, ValidationStatus.IN_PROGRESS);
+ }
+ }
+ }
+
+ private void updateStatus(PrivateDnsValidationUpdate update) {
+ Pair<String, InetAddress> p = new Pair(update.hostname,
+ update.ipAddress);
+ if (!mValidationMap.containsKey(p)) {
+ return;
+ }
+ if (update.validated) {
+ mValidationMap.put(p, ValidationStatus.SUCCEEDED);
+ } else {
+ mValidationMap.put(p, ValidationStatus.FAILED);
+ }
+ }
+ }
+
private final Context mContext;
private final ContentResolver mContentResolver;
private final INetworkManagementService mNMS;
private final MockableSystemProperties mSystemProperties;
+ // TODO: Replace these Maps with SparseArrays.
private final Map<Integer, PrivateDnsConfig> mPrivateDnsMap;
+ private final Map<Integer, PrivateDnsValidationStatuses> mPrivateDnsValidationMap;
private int mNumDnsEntries;
private int mSampleValidity;
@@ -158,6 +286,7 @@
mNMS = nms;
mSystemProperties = sp;
mPrivateDnsMap = new HashMap<>();
+ mPrivateDnsValidationMap = new HashMap<>();
// TODO: Create and register ContentObservers to track every setting
// used herein, posting messages to respond to changes.
@@ -169,6 +298,7 @@
public void removeNetwork(Network network) {
mPrivateDnsMap.remove(network.netId);
+ mPrivateDnsValidationMap.remove(network.netId);
}
public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
@@ -178,6 +308,40 @@
: mPrivateDnsMap.remove(network.netId);
}
+ public void updatePrivateDnsStatus(int netId, LinkProperties lp) {
+ // Use the PrivateDnsConfig data pushed to this class instance
+ // from ConnectivityService.
+ final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId,
+ PRIVATE_DNS_OFF);
+
+ final boolean useTls = privateDnsCfg.useTls;
+ final boolean strictMode = privateDnsCfg.inStrictMode();
+ final String tlsHostname = strictMode ? privateDnsCfg.hostname : "";
+
+ if (strictMode) {
+ lp.setUsePrivateDns(true);
+ lp.setPrivateDnsServerName(tlsHostname);
+ } else if (useTls) {
+ // We are in opportunistic mode. Private DNS should be used if there
+ // is a known DNS-over-TLS validated server.
+ boolean validated = mPrivateDnsValidationMap.containsKey(netId) &&
+ mPrivateDnsValidationMap.get(netId).hasValidatedServer();
+ lp.setUsePrivateDns(validated);
+ lp.setPrivateDnsServerName(null);
+ } else {
+ // Private DNS is disabled.
+ lp.setUsePrivateDns(false);
+ lp.setPrivateDnsServerName(null);
+ }
+ }
+
+ public void updatePrivateDnsValidation(PrivateDnsValidationUpdate update) {
+ final PrivateDnsValidationStatuses statuses =
+ mPrivateDnsValidationMap.get(update.netId);
+ if (statuses == null) return;
+ statuses.updateStatus(update);
+ }
+
public void setDnsConfigurationForNetwork(
int netId, LinkProperties lp, boolean isDefaultNetwork) {
final String[] assignedServers = NetworkUtils.makeStrings(lp.getDnsServers());
@@ -193,10 +357,11 @@
//
// At this time we do not attempt to enable Private DNS on non-Internet
// networks like IMS.
- final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.get(netId);
+ final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId,
+ PRIVATE_DNS_OFF);
- final boolean useTls = (privateDnsCfg != null) && privateDnsCfg.useTls;
- final boolean strictMode = (privateDnsCfg != null) && privateDnsCfg.inStrictMode();
+ final boolean useTls = privateDnsCfg.useTls;
+ final boolean strictMode = privateDnsCfg.inStrictMode();
final String tlsHostname = strictMode ? privateDnsCfg.hostname : "";
final String[] tlsServers =
strictMode ? NetworkUtils.makeStrings(
@@ -206,6 +371,17 @@
: useTls ? assignedServers // Opportunistic
: new String[0]; // Off
+ // Prepare to track the validation status of the DNS servers in the
+ // resolver config when private DNS is in opportunistic or strict mode.
+ if (useTls) {
+ if (!mPrivateDnsValidationMap.containsKey(netId)) {
+ mPrivateDnsValidationMap.put(netId, new PrivateDnsValidationStatuses());
+ }
+ mPrivateDnsValidationMap.get(netId).updateTrackedDnses(tlsServers, tlsHostname);
+ } else {
+ mPrivateDnsValidationMap.remove(netId);
+ }
+
Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %s, %s, %s)",
netId, Arrays.toString(assignedServers), Arrays.toString(domainStrs),
Arrays.toString(params), tlsHostname, Arrays.toString(tlsServers)));
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 3868ea6..906a6a3 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -57,6 +57,7 @@
import android.telephony.TelephonyManager;
import android.util.DebugUtils;
import android.util.Pair;
+import android.util.Range;
import android.util.Slog;
import com.android.internal.R;
@@ -266,9 +267,9 @@
}
private long getRemainingDailyBudget(long limitBytes,
- Pair<ZonedDateTime, ZonedDateTime> cycle) {
- final long start = cycle.first.toInstant().toEpochMilli();
- final long end = cycle.second.toInstant().toEpochMilli();
+ Range<ZonedDateTime> cycle) {
+ final long start = cycle.getLower().toInstant().toEpochMilli();
+ final long end = cycle.getUpper().toInstant().toEpochMilli();
final long totalBytes = getNetworkTotalBytes(start, end);
final long remainingBytes = totalBytes == -1 ? 0 : Math.max(0, limitBytes - totalBytes);
// 1 + ((end - now - 1) / millisInDay with integers is equivalent to:
@@ -389,7 +390,7 @@
private static boolean hasActiveCycle(NetworkPolicy policy) {
return policy.hasCycle() && policy.lastLimitSnooze <
- policy.cycleIterator().next().first.toInstant().toEpochMilli();
+ policy.cycleIterator().next().getLower().toInstant().toEpochMilli();
}
// Only ever updated on the handler thread. Accessed from other binder threads to retrieve
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 8a2e71c..2845383 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -34,6 +34,7 @@
import android.net.ProxyInfo;
import android.net.TrafficStats;
import android.net.Uri;
+import android.net.dns.ResolvUtil;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.metrics.ValidationProbeEvent;
@@ -64,6 +65,7 @@
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
import java.io.IOException;
import java.net.HttpURLConnection;
@@ -77,6 +79,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Random;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -165,7 +168,7 @@
* Force evaluation even if it has succeeded in the past.
* arg1 = UID responsible for requesting this reeval. Will be billed for data.
*/
- public static final int CMD_FORCE_REEVALUATION = BASE + 8;
+ private static final int CMD_FORCE_REEVALUATION = BASE + 8;
/**
* Message to self indicating captive portal app finished.
@@ -205,9 +208,15 @@
* Private DNS. If a DNS resolution is required, e.g. for DNS-over-TLS in
* strict mode, then an event is sent back to ConnectivityService with the
* result of the resolution attempt.
+ *
+ * A separate message is used to trigger (re)evaluation of the Private DNS
+ * configuration, so that the message can be handled as needed in different
+ * states, including being ignored until after an ongoing captive portal
+ * validation phase is completed.
*/
private static final int CMD_PRIVATE_DNS_SETTINGS_CHANGED = BASE + 13;
public static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = BASE + 14;
+ private static final int CMD_EVALUATE_PRIVATE_DNS = BASE + 15;
// Start mReevaluateDelayMs at this value and double.
private static final int INITIAL_REEVALUATE_DELAY_MS = 1000;
@@ -215,6 +224,7 @@
// Before network has been evaluated this many times, ignore repeated reevaluate requests.
private static final int IGNORE_REEVALUATE_ATTEMPTS = 5;
private int mReevaluateToken = 0;
+ private static final int NO_UID = 0;
private static final int INVALID_UID = -1;
private int mUidResponsibleForReeval = INVALID_UID;
// Stop blaming UID that requested re-evaluation after this many attempts.
@@ -224,6 +234,8 @@
private static final int NUM_VALIDATION_LOG_LINES = 20;
+ private String mPrivateDnsProviderHostname = "";
+
public static boolean isValidationRequired(
NetworkCapabilities dfltNetCap, NetworkCapabilities nc) {
// TODO: Consider requiring validation for DUN networks.
@@ -261,13 +273,12 @@
public boolean systemReady = false;
- private DnsManager.PrivateDnsConfig mPrivateDnsCfg = null;
-
private final State mDefaultState = new DefaultState();
private final State mValidatedState = new ValidatedState();
private final State mMaybeNotifyState = new MaybeNotifyState();
private final State mEvaluatingState = new EvaluatingState();
private final State mCaptivePortalState = new CaptivePortalState();
+ private final State mEvaluatingPrivateDnsState = new EvaluatingPrivateDnsState();
private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null;
@@ -293,6 +304,10 @@
// Add suffix indicating which NetworkMonitor we're talking about.
super(TAG + networkAgentInfo.name());
+ // Logs with a tag of the form given just above, e.g.
+ // <timestamp> 862 2402 D NetworkMonitor/NetworkAgentInfo [WIFI () - 100]: ...
+ setDbg(VDBG);
+
mContext = context;
mMetricsLog = logger;
mConnectivityServiceHandler = handler;
@@ -305,10 +320,11 @@
mDefaultRequest = defaultRequest;
addState(mDefaultState);
- addState(mValidatedState, mDefaultState);
addState(mMaybeNotifyState, mDefaultState);
addState(mEvaluatingState, mMaybeNotifyState);
addState(mCaptivePortalState, mMaybeNotifyState);
+ addState(mEvaluatingPrivateDnsState, mDefaultState);
+ addState(mValidatedState, mDefaultState);
setInitialState(mDefaultState);
mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled();
@@ -321,6 +337,17 @@
start();
}
+ public void forceReevaluation(int responsibleUid) {
+ sendMessage(CMD_FORCE_REEVALUATION, responsibleUid, 0);
+ }
+
+ public void notifyPrivateDnsSettingsChanged(PrivateDnsConfig newCfg) {
+ // Cancel any outstanding resolutions.
+ removeMessages(CMD_PRIVATE_DNS_SETTINGS_CHANGED);
+ // Send the update to the proper thread.
+ sendMessage(CMD_PRIVATE_DNS_SETTINGS_CHANGED, newCfg);
+ }
+
@Override
protected void log(String s) {
if (DBG) Log.d(TAG + "/" + mNetworkAgentInfo.name(), s);
@@ -349,6 +376,12 @@
mDefaultRequest.networkCapabilities, mNetworkAgentInfo.networkCapabilities);
}
+
+ private void notifyNetworkTestResultInvalid(Object obj) {
+ mConnectivityServiceHandler.sendMessage(obtainMessage(
+ EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId, obj));
+ }
+
// DefaultState is the parent of all States. It exists only to handle CMD_* messages but
// does not entail any real state (hence no enter() or exit() routines).
private class DefaultState extends State {
@@ -392,41 +425,66 @@
switch (message.arg1) {
case APP_RETURN_DISMISSED:
- sendMessage(CMD_FORCE_REEVALUATION, 0 /* no UID */, 0);
+ sendMessage(CMD_FORCE_REEVALUATION, NO_UID, 0);
break;
case APP_RETURN_WANTED_AS_IS:
mDontDisplaySigninNotification = true;
// TODO: Distinguish this from a network that actually validates.
- // Displaying the "!" on the system UI icon may still be a good idea.
- transitionTo(mValidatedState);
+ // Displaying the "x" on the system UI icon may still be a good idea.
+ transitionTo(mEvaluatingPrivateDnsState);
break;
case APP_RETURN_UNWANTED:
mDontDisplaySigninNotification = true;
mUserDoesNotWant = true;
- mConnectivityServiceHandler.sendMessage(obtainMessage(
- EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID,
- mNetId, null));
+ notifyNetworkTestResultInvalid(null);
// TODO: Should teardown network.
mUidResponsibleForReeval = 0;
transitionTo(mEvaluatingState);
break;
}
return HANDLED;
- case CMD_PRIVATE_DNS_SETTINGS_CHANGED:
- if (isValidationRequired()) {
- // This performs a blocking DNS resolution of the
- // strict mode hostname, if required.
- resolvePrivateDnsConfig((DnsManager.PrivateDnsConfig) message.obj);
- if ((mPrivateDnsCfg != null) && mPrivateDnsCfg.inStrictMode()) {
- mConnectivityServiceHandler.sendMessage(obtainMessage(
- EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0, mNetId,
- new DnsManager.PrivateDnsConfig(mPrivateDnsCfg)));
- }
+ case CMD_PRIVATE_DNS_SETTINGS_CHANGED: {
+ final PrivateDnsConfig cfg = (PrivateDnsConfig) message.obj;
+ if (!isValidationRequired() || cfg == null || !cfg.inStrictMode()) {
+ // No DNS resolution required.
+ //
+ // We don't force any validation in opportunistic mode
+ // here. Opportunistic mode nameservers are validated
+ // separately within netd.
+ //
+ // Reset Private DNS settings state.
+ mPrivateDnsProviderHostname = "";
+ break;
}
- return HANDLED;
+
+ mPrivateDnsProviderHostname = cfg.hostname;
+
+ // DNS resolutions via Private DNS strict mode block for a
+ // few seconds (~4.2) checking for any IP addresses to
+ // arrive and validate. Initiating a (re)evaluation now
+ // should not significantly alter the validation outcome.
+ //
+ // No matter what: enqueue a validation request; one of
+ // three things can happen with this request:
+ // [1] ignored (EvaluatingState or CaptivePortalState)
+ // [2] transition to EvaluatingPrivateDnsState
+ // (DefaultState and ValidatedState)
+ // [3] handled (EvaluatingPrivateDnsState)
+ //
+ // The Private DNS configuration to be evaluated will:
+ // [1] be skipped (not in strict mode), or
+ // [2] validate (huzzah), or
+ // [3] encounter some problem (invalid hostname,
+ // no resolved IP addresses, IPs unreachable,
+ // port 853 unreachable, port 853 is not running a
+ // DNS-over-TLS server, et cetera).
+ sendMessage(CMD_EVALUATE_PRIVATE_DNS);
+ break;
+ }
default:
- return HANDLED;
+ break;
}
+ return HANDLED;
}
}
@@ -440,7 +498,7 @@
maybeLogEvaluationResult(
networkEventType(validationStage(), EvaluationResult.VALIDATED));
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
- NETWORK_TEST_RESULT_VALID, mNetId, mPrivateDnsCfg));
+ NETWORK_TEST_RESULT_VALID, mNetId, null));
mValidations++;
}
@@ -449,10 +507,14 @@
switch (message.what) {
case CMD_NETWORK_CONNECTED:
transitionTo(mValidatedState);
- return HANDLED;
+ break;
+ case CMD_EVALUATE_PRIVATE_DNS:
+ transitionTo(mEvaluatingPrivateDnsState);
+ break;
default:
return NOT_HANDLED;
}
+ return HANDLED;
}
}
@@ -569,11 +631,11 @@
case CMD_REEVALUATE:
if (message.arg1 != mReevaluateToken || mUserDoesNotWant)
return HANDLED;
- // Don't bother validating networks that don't satisify the default request.
+ // Don't bother validating networks that don't satisfy the default request.
// This includes:
// - VPNs which can be considered explicitly desired by the user and the
// user's desire trumps whether the network validates.
- // - Networks that don't provide internet access. It's unclear how to
+ // - Networks that don't provide Internet access. It's unclear how to
// validate such networks.
// - Untrusted networks. It's unsafe to prompt the user to sign-in to
// such networks and the user didn't express interest in connecting to
@@ -588,7 +650,6 @@
// expensive metered network, or unwanted leaking of the User Agent string.
if (!isValidationRequired()) {
validationLog("Network would not satisfy default request, not validating");
- mPrivateDnsCfg = null;
transitionTo(mValidatedState);
return HANDLED;
}
@@ -601,20 +662,18 @@
// if this is found to cause problems.
CaptivePortalProbeResult probeResult = isCaptivePortal();
if (probeResult.isSuccessful()) {
- resolvePrivateDnsConfig();
- transitionTo(mValidatedState);
+ // Transit EvaluatingPrivateDnsState to get to Validated
+ // state (even if no Private DNS validation required).
+ transitionTo(mEvaluatingPrivateDnsState);
} else if (probeResult.isPortal()) {
- mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
- NETWORK_TEST_RESULT_INVALID, mNetId, probeResult.redirectUrl));
+ notifyNetworkTestResultInvalid(probeResult.redirectUrl);
mLastPortalProbeResult = probeResult;
transitionTo(mCaptivePortalState);
} else {
final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
sendMessageDelayed(msg, mReevaluateDelayMs);
logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
- mConnectivityServiceHandler.sendMessage(obtainMessage(
- EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId,
- probeResult.redirectUrl));
+ notifyNetworkTestResultInvalid(probeResult.redirectUrl);
if (mAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
// Don't continue to blame UID forever.
TrafficStats.clearThreadStatsUid();
@@ -700,6 +759,110 @@
}
}
+ private class EvaluatingPrivateDnsState extends State {
+ private int mPrivateDnsReevalDelayMs;
+ private PrivateDnsConfig mPrivateDnsConfig;
+
+ @Override
+ public void enter() {
+ mPrivateDnsReevalDelayMs = INITIAL_REEVALUATE_DELAY_MS;
+ mPrivateDnsConfig = null;
+ sendMessage(CMD_EVALUATE_PRIVATE_DNS);
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_EVALUATE_PRIVATE_DNS:
+ if (inStrictMode()) {
+ if (!isStrictModeHostnameResolved()) {
+ resolveStrictModeHostname();
+
+ if (isStrictModeHostnameResolved()) {
+ notifyPrivateDnsConfigResolved();
+ } else {
+ handlePrivateDnsEvaluationFailure();
+ break;
+ }
+ }
+
+ // Look up a one-time hostname, to bypass caching.
+ //
+ // Note that this will race with ConnectivityService
+ // code programming the DNS-over-TLS server IP addresses
+ // into netd (if invoked, above). If netd doesn't know
+ // the IP addresses yet, or if the connections to the IP
+ // addresses haven't yet been validated, netd will block
+ // for up to a few seconds before failing the lookup.
+ if (!sendPrivateDnsProbe()) {
+ handlePrivateDnsEvaluationFailure();
+ break;
+ }
+ }
+
+ // All good!
+ transitionTo(mValidatedState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+
+ private boolean inStrictMode() {
+ return !TextUtils.isEmpty(mPrivateDnsProviderHostname);
+ }
+
+ private boolean isStrictModeHostnameResolved() {
+ return (mPrivateDnsConfig != null) &&
+ mPrivateDnsConfig.hostname.equals(mPrivateDnsProviderHostname) &&
+ (mPrivateDnsConfig.ips.length > 0);
+ }
+
+ private void resolveStrictModeHostname() {
+ try {
+ // Do a blocking DNS resolution using the network-assigned nameservers.
+ mPrivateDnsConfig = new PrivateDnsConfig(
+ mPrivateDnsProviderHostname,
+ mNetwork.getAllByName(mPrivateDnsProviderHostname));
+ } catch (UnknownHostException uhe) {
+ mPrivateDnsConfig = null;
+ }
+ }
+
+ private void notifyPrivateDnsConfigResolved() {
+ mConnectivityServiceHandler.sendMessage(obtainMessage(
+ EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0, mNetId, mPrivateDnsConfig));
+ }
+
+ private void handlePrivateDnsEvaluationFailure() {
+ notifyNetworkTestResultInvalid(null);
+
+ // Queue up a re-evaluation with backoff.
+ //
+ // TODO: Consider abandoning this state after a few attempts and
+ // transitioning back to EvaluatingState, to perhaps give ourselves
+ // the opportunity to (re)detect a captive portal or something.
+ sendMessageDelayed(CMD_EVALUATE_PRIVATE_DNS, mPrivateDnsReevalDelayMs);
+ mPrivateDnsReevalDelayMs *= 2;
+ if (mPrivateDnsReevalDelayMs > MAX_REEVALUATE_DELAY_MS) {
+ mPrivateDnsReevalDelayMs = MAX_REEVALUATE_DELAY_MS;
+ }
+ }
+
+ private boolean sendPrivateDnsProbe() {
+ // q.v. system/netd/server/dns/DnsTlsTransport.cpp
+ final String ONE_TIME_HOSTNAME_SUFFIX = "-dnsotls-ds.metric.gstatic.com";
+ final String host = UUID.randomUUID().toString().substring(0, 8) +
+ ONE_TIME_HOSTNAME_SUFFIX;
+ try {
+ final InetAddress[] ips = mNetworkAgentInfo.network().getAllByName(host);
+ return (ips != null && ips.length > 0);
+ } catch (UnknownHostException uhe) {}
+ return false;
+ }
+ }
+
// Limits the list of IP addresses returned by getAllByName or tried by openConnection to at
// most one per address family. This ensures we only wait up to 20 seconds for TCP connections
// to complete, regardless of how many IP addresses a host has.
@@ -710,7 +873,9 @@
@Override
public InetAddress[] getAllByName(String host) throws UnknownHostException {
- List<InetAddress> addrs = Arrays.asList(super.getAllByName(host));
+ // Always bypass Private DNS.
+ final List<InetAddress> addrs = Arrays.asList(
+ ResolvUtil.blockingResolveAllLocally(this, host));
// Ensure the address family of the first address is tried first.
LinkedHashMap<Class, InetAddress> addressByFamily = new LinkedHashMap<>();
@@ -1065,44 +1230,6 @@
return null;
}
- public void notifyPrivateDnsSettingsChanged(DnsManager.PrivateDnsConfig newCfg) {
- // Cancel any outstanding resolutions.
- removeMessages(CMD_PRIVATE_DNS_SETTINGS_CHANGED);
- // Send the update to the proper thread.
- sendMessage(CMD_PRIVATE_DNS_SETTINGS_CHANGED, newCfg);
- }
-
- private void resolvePrivateDnsConfig() {
- resolvePrivateDnsConfig(DnsManager.getPrivateDnsConfig(mContext.getContentResolver()));
- }
-
- private void resolvePrivateDnsConfig(DnsManager.PrivateDnsConfig cfg) {
- // Nothing to do.
- if (cfg == null) {
- mPrivateDnsCfg = null;
- return;
- }
-
- // No DNS resolution required.
- if (!cfg.inStrictMode()) {
- mPrivateDnsCfg = cfg;
- return;
- }
-
- if ((mPrivateDnsCfg != null) && mPrivateDnsCfg.inStrictMode() &&
- (mPrivateDnsCfg.ips.length > 0) && mPrivateDnsCfg.hostname.equals(cfg.hostname)) {
- // We have already resolved this strict mode hostname. Assume that
- // Private DNS services won't be changing serving IP addresses very
- // frequently and save ourselves one re-resolve.
- return;
- }
-
- mPrivateDnsCfg = cfg;
- final DnsManager.PrivateDnsConfig resolvedCfg = DnsManager.tryBlockingResolveOf(
- mNetwork, mPrivateDnsCfg.hostname);
- if (resolvedCfg != null) mPrivateDnsCfg = resolvedCfg;
- }
-
/**
* @param responseReceived - whether or not we received a valid HTTP response to our request.
* If false, isCaptivePortal and responseTimestampMs are ignored
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index b7bbb3b..e3d0bdd 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -79,7 +79,7 @@
*/
public final class ContentService extends IContentService.Stub {
static final String TAG = "ContentService";
- static final boolean DEBUG = true;
+ static final boolean DEBUG = false;
public static class Lifecycle extends SystemService {
private ContentService mService;
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 5e1afeb..f403953 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -169,16 +169,6 @@
// Use -1 if there is no current auto-brightness value available.
private int mScreenAutoBrightness = -1;
- // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter)
- private float mScreenAutoBrightnessAdjustment = 0.0f;
-
- // The maximum range of gamma adjustment possible using the screen
- // auto-brightness adjustment setting.
- private float mScreenAutoBrightnessAdjustmentMaxGamma;
-
- // The last screen auto-brightness gamma. (For printing in dump() only.)
- private float mLastScreenAutoBrightnessGamma = 1.0f;
-
// The current display policy. This is useful, for example, for knowing when we're dozing,
// where the light sensor may not be available.
private int mDisplayPolicy = DisplayPowerRequest.POLICY_OFF;
@@ -186,10 +176,8 @@
// True if we are collecting a brightness adjustment sample, along with some data
// for the initial state of the sample.
private boolean mBrightnessAdjustmentSamplePending;
- private float mBrightnessAdjustmentSampleOldAdjustment;
private float mBrightnessAdjustmentSampleOldLux;
private int mBrightnessAdjustmentSampleOldBrightness;
- private float mBrightnessAdjustmentSampleOldGamma;
// When the short term model is invalidated, we don't necessarily reset it (i.e. clear the
// user's adjustment) immediately, but wait for a drastic enough change in the ambient light.
@@ -200,12 +188,11 @@
private float SHORT_TERM_MODEL_THRESHOLD_RATIO = 0.6f;
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
- SensorManager sensorManager, BrightnessMappingStrategy mapper, int lightSensorWarmUpTime,
- int brightnessMin, int brightnessMax, float dozeScaleFactor,
+ SensorManager sensorManager, BrightnessMappingStrategy mapper,
+ int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor,
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
- int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma,
- HysteresisLevels dynamicHysteresis) {
+ int ambientLightHorizon, HysteresisLevels dynamicHysteresis) {
mCallbacks = callbacks;
mSensorManager = sensorManager;
mBrightnessMapper = mapper;
@@ -221,7 +208,6 @@
mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
mAmbientLightHorizon = ambientLightHorizon;
mWeightingIntercept = ambientLightHorizon;
- mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma;
mDynamicHysteresis = dynamicHysteresis;
mShortTermModelValid = true;
mShortTermModelAnchor = -1;
@@ -236,6 +222,9 @@
}
public int getAutomaticScreenBrightness() {
+ if (!mAmbientLuxValid) {
+ return -1;
+ }
if (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE) {
return (int) (mScreenAutoBrightness * mDozeScaleFactor);
}
@@ -243,7 +232,7 @@
}
public float getAutomaticScreenBrightnessAdjustment() {
- return mScreenAutoBrightnessAdjustment;
+ return mBrightnessMapper.getAutoBrightnessAdjustment();
}
public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,
@@ -257,7 +246,9 @@
boolean dozing = (displayPolicy == DisplayPowerRequest.POLICY_DOZE);
boolean changed = setBrightnessConfiguration(configuration);
changed |= setDisplayPolicy(displayPolicy);
- changed |= setScreenAutoBrightnessAdjustment(adjustment);
+ if (userChangedAutoBrightnessAdjustment) {
+ changed |= setAutoBrightnessAdjustment(adjustment);
+ }
if (userChangedBrightness && enable) {
// Update the brightness curve with the new user control point. It's critical this
// happens after we update the autobrightness adjustment since it may reset it.
@@ -322,9 +313,6 @@
if (DEBUG) {
Slog.d(TAG, "ShortTermModel: anchor=" + mShortTermModelAnchor);
}
- // Reset the brightness adjustment so that the next time we're queried for brightness we
- // return the value the user set.
- mScreenAutoBrightnessAdjustment = 0.0f;
return true;
}
@@ -361,6 +349,7 @@
pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
pw.println(" mLightSensorEnableTime=" + TimeUtils.formatUptime(mLightSensorEnableTime));
pw.println(" mAmbientLux=" + mAmbientLux);
+ pw.println(" mAmbientLuxValid=" + mAmbientLuxValid);
pw.println(" mAmbientLightHorizon=" + mAmbientLightHorizon);
pw.println(" mBrighteningLuxThreshold=" + mBrighteningLuxThreshold);
pw.println(" mDarkeningLuxThreshold=" + mDarkeningLuxThreshold);
@@ -369,10 +358,6 @@
pw.println(" mRecentLightSamples=" + mRecentLightSamples);
pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer);
pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
- pw.println(" mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment);
- pw.println(" mScreenAutoBrightnessAdjustmentMaxGamma="
- + mScreenAutoBrightnessAdjustmentMaxGamma);
- pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
pw.println(" mDisplayPolicy=" + mDisplayPolicy);
pw.println(" mShortTermModelAnchor=" + mShortTermModelAnchor);
@@ -429,8 +414,8 @@
if (lightSensorRate != mCurrentLightSensorRate) {
if (DEBUG) {
Slog.d(TAG, "adjustLightSensorRate: " +
- "previousRate=" + mCurrentLightSensorRate + ", " +
- "currentRate=" + lightSensorRate);
+ "previousRate=" + mCurrentLightSensorRate + ", " +
+ "currentRate=" + lightSensorRate);
}
mCurrentLightSensorRate = lightSensorRate;
mSensorManager.unregisterListener(mLightSensorListener);
@@ -439,12 +424,8 @@
}
}
- private boolean setScreenAutoBrightnessAdjustment(float adjustment) {
- if (adjustment != mScreenAutoBrightnessAdjustment) {
- mScreenAutoBrightnessAdjustment = adjustment;
- return true;
- }
- return false;
+ private boolean setAutoBrightnessAdjustment(float adjustment) {
+ return mBrightnessMapper.setAutoBrightnessAdjustment(adjustment);
}
private void setAmbientLux(float lux) {
@@ -466,12 +447,14 @@
final float maxAmbientLux =
mShortTermModelAnchor + mShortTermModelAnchor * SHORT_TERM_MODEL_THRESHOLD_RATIO;
if (minAmbientLux < mAmbientLux && mAmbientLux < maxAmbientLux) {
- Slog.d(TAG, "ShortTermModel: re-validate user data, ambient lux is " +
- minAmbientLux + " < " + mAmbientLux + " < " + maxAmbientLux);
+ if (DEBUG) {
+ Slog.d(TAG, "ShortTermModel: re-validate user data, ambient lux is " +
+ minAmbientLux + " < " + mAmbientLux + " < " + maxAmbientLux);
+ }
mShortTermModelValid = true;
} else {
Slog.d(TAG, "ShortTermModel: reset data, ambient lux is " + mAmbientLux +
- "(" + minAmbientLux + ", " + maxAmbientLux + ")");
+ "(" + minAmbientLux + ", " + maxAmbientLux + ")");
resetShortTermModel();
}
}
@@ -498,9 +481,9 @@
}
}
if (DEBUG) {
- Slog.d(TAG, "calculateAmbientLux: selected endIndex=" + endIndex + ", point=("
- + mAmbientLightRingBuffer.getTime(endIndex) + ", "
- + mAmbientLightRingBuffer.getLux(endIndex) + ")");
+ Slog.d(TAG, "calculateAmbientLux: selected endIndex=" + endIndex + ", point=(" +
+ mAmbientLightRingBuffer.getTime(endIndex) + ", " +
+ mAmbientLightRingBuffer.getLux(endIndex) + ")");
}
float sum = 0;
float totalWeight = 0;
@@ -517,8 +500,8 @@
float lux = mAmbientLightRingBuffer.getLux(i);
if (DEBUG) {
Slog.d(TAG, "calculateAmbientLux: [" + startTime + ", " + endTime + "]: " +
- "lux=" + lux + ", " +
- "weight=" + weight);
+ "lux=" + lux + ", " +
+ "weight=" + weight);
}
totalWeight += weight;
sum += lux * weight;
@@ -526,8 +509,8 @@
}
if (DEBUG) {
Slog.d(TAG, "calculateAmbientLux: " +
- "totalWeight=" + totalWeight + ", " +
- "newAmbientLux=" + (sum / totalWeight));
+ "totalWeight=" + totalWeight + ", " +
+ "newAmbientLux=" + (sum / totalWeight));
}
return sum / totalWeight;
}
@@ -581,8 +564,8 @@
if (time < timeWhenSensorWarmedUp) {
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: Sensor not ready yet: " +
- "time=" + time + ", " +
- "timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp);
+ "time=" + time + ", " +
+ "timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp);
}
mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX,
timeWhenSensorWarmedUp);
@@ -621,10 +604,10 @@
setAmbientLux(fastAmbientLux);
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: " +
- ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " +
- "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold + ", " +
- "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", " +
- "mAmbientLux=" + mAmbientLux);
+ ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " +
+ "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold + ", " +
+ "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", " +
+ "mAmbientLux=" + mAmbientLux);
}
updateAutoBrightness(true);
nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
@@ -641,7 +624,7 @@
nextTransitionTime > time ? nextTransitionTime : time + mNormalLightSensorRate;
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for " +
- nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
+ nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
}
mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime);
}
@@ -652,40 +635,17 @@
}
float value = mBrightnessMapper.getBrightness(mAmbientLux);
- float gamma = 1.0f;
-
- if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
- && mScreenAutoBrightnessAdjustment != 0.0f) {
- final float adjGamma = MathUtils.pow(mScreenAutoBrightnessAdjustmentMaxGamma,
- Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment)));
- gamma *= adjGamma;
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
- }
- }
-
- if (gamma != 1.0f) {
- final float in = value;
- value = MathUtils.pow(value, gamma);
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: " +
- "gamma=" + gamma + ", " +
- "in=" + in + ", " +
- "out=" + value);
- }
- }
int newScreenAutoBrightness =
clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));
if (mScreenAutoBrightness != newScreenAutoBrightness) {
if (DEBUG) {
Slog.d(TAG, "updateAutoBrightness: " +
- "mScreenAutoBrightness=" + mScreenAutoBrightness + ", " +
- "newScreenAutoBrightness=" + newScreenAutoBrightness);
+ "mScreenAutoBrightness=" + mScreenAutoBrightness + ", " +
+ "newScreenAutoBrightness=" + newScreenAutoBrightness);
}
mScreenAutoBrightness = newScreenAutoBrightness;
- mLastScreenAutoBrightnessGamma = gamma;
if (sendUpdate) {
mCallbacks.updateBrightness();
}
@@ -700,10 +660,8 @@
private void prepareBrightnessAdjustmentSample() {
if (!mBrightnessAdjustmentSamplePending) {
mBrightnessAdjustmentSamplePending = true;
- mBrightnessAdjustmentSampleOldAdjustment = mScreenAutoBrightnessAdjustment;
mBrightnessAdjustmentSampleOldLux = mAmbientLuxValid ? mAmbientLux : -1;
mBrightnessAdjustmentSampleOldBrightness = mScreenAutoBrightness;
- mBrightnessAdjustmentSampleOldGamma = mLastScreenAutoBrightnessGamma;
} else {
mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE);
}
@@ -725,22 +683,16 @@
if (mAmbientLuxValid && mScreenAutoBrightness >= 0) {
if (DEBUG) {
Slog.d(TAG, "Auto-brightness adjustment changed by user: " +
- "adj=" + mScreenAutoBrightnessAdjustment + ", " +
- "lux=" + mAmbientLux + ", " +
- "brightness=" + mScreenAutoBrightness + ", " +
- "gamma=" + mLastScreenAutoBrightnessGamma + ", " +
- "ring=" + mAmbientLightRingBuffer);
+ "lux=" + mAmbientLux + ", " +
+ "brightness=" + mScreenAutoBrightness + ", " +
+ "ring=" + mAmbientLightRingBuffer);
}
EventLog.writeEvent(EventLogTags.AUTO_BRIGHTNESS_ADJ,
- mBrightnessAdjustmentSampleOldAdjustment,
mBrightnessAdjustmentSampleOldLux,
mBrightnessAdjustmentSampleOldBrightness,
- mBrightnessAdjustmentSampleOldGamma,
- mScreenAutoBrightnessAdjustment,
mAmbientLux,
- mScreenAutoBrightness,
- mLastScreenAutoBrightnessGamma);
+ mScreenAutoBrightness);
}
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 4313d17..f74daf2 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -28,6 +28,7 @@
import com.android.internal.util.Preconditions;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.utils.Plog;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -46,6 +47,8 @@
private static final float LUX_GRAD_SMOOTHING = 0.25f;
private static final float MAX_GRAD = 1.0f;
+ private static final Plog PLOG = Plog.createSystemPlog(TAG);
+
@Nullable
public static BrightnessMappingStrategy create(Resources resources) {
float[] luxLevels = getLuxLevels(resources.getIntArray(
@@ -54,6 +57,9 @@
com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
float[] brightnessLevelsNits = getFloatArray(resources.obtainTypedArray(
com.android.internal.R.array.config_autoBrightnessDisplayValuesNits));
+ float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
+ com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
+ 1, 1);
float[] nitsRange = getFloatArray(resources.obtainTypedArray(
com.android.internal.R.array.config_screenBrightnessNits));
@@ -68,14 +74,16 @@
com.android.internal.R.integer.config_screenBrightnessSettingMaximum);
if (backlightRange[0] > minimumBacklight
|| backlightRange[backlightRange.length - 1] < maximumBacklight) {
- Slog.w(TAG, "Screen brightness mapping does not cover whole range of available"
- + " backlight values, autobrightness functionality may be impaired.");
+ Slog.w(TAG, "Screen brightness mapping does not cover whole range of available " +
+ "backlight values, autobrightness functionality may be impaired.");
}
BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
builder.setCurve(luxLevels, brightnessLevelsNits);
- return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange);
+ return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
+ autoBrightnessAdjustmentMaxGamma);
} else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
- return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight);
+ return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
+ autoBrightnessAdjustmentMaxGamma);
} else {
return null;
}
@@ -173,6 +181,26 @@
public abstract float getBrightness(float lux);
/**
+ * Returns the current auto-brightness adjustment.
+ *
+ * The returned adjustment is a value in the range [-1.0, 1.0] such that
+ * {@code config_autoBrightnessAdjustmentMaxGamma<sup>-adjustment</sup>} is used to gamma
+ * correct the brightness curve.
+ */
+ public abstract float getAutoBrightnessAdjustment();
+
+ /**
+ * Sets the auto-brightness adjustment.
+ *
+ * @param adjustment The desired auto-brightness adjustment.
+ * @return Whether the auto-brightness adjustment has changed.
+ *
+ * @Deprecated The auto-brightness adjustment should not be set directly, but rather inferred
+ * from user data points.
+ */
+ public abstract boolean setAutoBrightnessAdjustment(float adjustment);
+
+ /**
* Converts the provided backlight value to nits if possible.
*
* Returns -1.0f if there's no available mapping for the backlight to nits.
@@ -200,12 +228,13 @@
*/
public abstract void clearUserDataPoints();
- /** @return true if there are any short term adjustments applied to the curve */
+ /** @return True if there are any short term adjustments applied to the curve. */
public abstract boolean hasUserDataPoints();
- /** @return true if the current brightness config is the default one */
+ /** @return True if the current brightness configuration is the default one. */
public abstract boolean isDefaultConfig();
+ /** @return The default brightness configuration. */
public abstract BrightnessConfiguration getDefaultConfig();
public abstract void dump(PrintWriter pw);
@@ -216,22 +245,8 @@
return (float) brightness / PowerManager.BRIGHTNESS_ON;
}
- private static Spline createSpline(float[] x, float[] y) {
- Spline spline = Spline.createSpline(x, y);
- if (DEBUG) {
- Slog.d(TAG, "Spline: " + spline);
- for (float v = 1f; v < x[x.length - 1] * 1.25f; v *= 1.25f) {
- Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v)));
- }
- }
- return spline;
- }
-
private static Pair<float[], float[]> insertControlPoint(
float[] luxLevels, float[] brightnessLevels, float lux, float brightness) {
- if (DEBUG) {
- Slog.d(TAG, "Inserting new control point at (" + lux + ", " + brightness + ")");
- }
final int idx = findInsertionPoint(luxLevels, lux);
final float[] newLuxLevels;
final float[] newBrightnessLevels;
@@ -274,9 +289,7 @@
private static void smoothCurve(float[] lux, float[] brightness, int idx) {
if (DEBUG) {
- Slog.d(TAG, "smoothCurve(lux=" + Arrays.toString(lux)
- + ", brightness=" + Arrays.toString(brightness)
- + ", idx=" + idx + ")");
+ PLOG.logCurve("unsmoothed curve", lux, brightness);
}
float prevLux = lux[idx];
float prevBrightness = brightness[idx];
@@ -294,7 +307,6 @@
prevBrightness = newBrightness;
brightness[i] = newBrightness;
}
-
// Smooth curve for data points below the newly introduced point
prevLux = lux[idx];
prevBrightness = brightness[idx];
@@ -312,8 +324,7 @@
brightness[i] = newBrightness;
}
if (DEBUG) {
- Slog.d(TAG, "Smoothed Curve: lux=" + Arrays.toString(lux)
- + ", brightness=" + Arrays.toString(brightness));
+ PLOG.logCurve("smoothed curve", lux, brightness);
}
}
@@ -323,6 +334,72 @@
- MathUtils.log(prevLux + LUX_GRAD_SMOOTHING)));
}
+ private static float inferAutoBrightnessAdjustment(float maxGamma,
+ float desiredBrightness, float currentBrightness) {
+ float adjustment = 0;
+ float gamma = Float.NaN;
+ // Extreme edge cases: use a simpler heuristic, as proper gamma correction around the edges
+ // affects the curve rather drastically.
+ if (currentBrightness <= 0.1f || currentBrightness >= 0.9f) {
+ adjustment = (desiredBrightness - currentBrightness) * 2;
+ // Edge case: darkest adjustment possible.
+ } else if (desiredBrightness == 0) {
+ adjustment = -1;
+ // Edge case: brightest adjustment possible.
+ } else if (desiredBrightness == 1) {
+ adjustment = +1;
+ } else {
+ // current^gamma = desired => gamma = log[current](desired)
+ gamma = MathUtils.log(desiredBrightness) / MathUtils.log(currentBrightness);
+ // max^-adjustment = gamma => adjustment = -log[max](gamma)
+ adjustment = -MathUtils.constrain(
+ MathUtils.log(gamma) / MathUtils.log(maxGamma), -1, 1);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "inferAutoBrightnessAdjustment: " + maxGamma + "^" + -adjustment + "=" +
+ MathUtils.pow(maxGamma, -adjustment) + " == " + gamma);
+ Slog.d(TAG, "inferAutoBrightnessAdjustment: " + currentBrightness + "^" + gamma + "=" +
+ MathUtils.pow(currentBrightness, gamma) + " == " + desiredBrightness);
+ }
+ return adjustment;
+ }
+
+ private static Pair<float[], float[]> getAdjustedCurve(float[] lux, float[] brightness,
+ float userLux, float userBrightness, float adjustment, float maxGamma) {
+ float[] newLux = lux;
+ float[] newBrightness = Arrays.copyOf(brightness, brightness.length);
+ if (DEBUG) {
+ PLOG.logCurve("unadjusted curve", newLux, newBrightness);
+ }
+ adjustment = MathUtils.constrain(adjustment, -1, 1);
+ float gamma = MathUtils.pow(maxGamma, -adjustment);
+ if (DEBUG) {
+ Slog.d(TAG, "getAdjustedCurve: " + maxGamma + "^" + -adjustment + "=" +
+ MathUtils.pow(maxGamma, -adjustment) + " == " + gamma);
+ }
+ if (gamma != 1) {
+ for (int i = 0; i < newBrightness.length; i++) {
+ newBrightness[i] = MathUtils.pow(newBrightness[i], gamma);
+ }
+ }
+ if (DEBUG) {
+ PLOG.logCurve("gamma adjusted curve", newLux, newBrightness);
+ }
+ if (userLux != -1) {
+ Pair<float[], float[]> curve = insertControlPoint(newLux, newBrightness, userLux,
+ userBrightness);
+ newLux = curve.first;
+ newBrightness = curve.second;
+ if (DEBUG) {
+ PLOG.logCurve("gamma and user adjusted curve", newLux, newBrightness);
+ // This is done for comparison.
+ curve = insertControlPoint(lux, brightness, userLux, userBrightness);
+ PLOG.logCurve("user adjusted curve", curve.first ,curve.second);
+ }
+ }
+ return Pair.create(newLux, newBrightness);
+ }
+
/**
* A {@link BrightnessMappingStrategy} that maps from ambient room brightness directly to the
* backlight of the display.
@@ -337,10 +414,12 @@
private final float[] mBrightness;
private Spline mSpline;
+ private float mMaxGamma;
+ private float mAutoBrightnessAdjustment;
private float mUserLux;
private float mUserBrightness;
- public SimpleMappingStrategy(float[] lux, int[] brightness) {
+ public SimpleMappingStrategy(float[] lux, int[] brightness, float maxGamma) {
Preconditions.checkArgument(lux.length != 0 && brightness.length != 0,
"Lux and brightness arrays must not be empty!");
Preconditions.checkArgument(lux.length == brightness.length,
@@ -357,9 +436,14 @@
mBrightness[i] = normalizeAbsoluteBrightness(brightness[i]);
}
- mSpline = createSpline(mLux, mBrightness);
+ mMaxGamma = maxGamma;
+ mAutoBrightnessAdjustment = 0;
mUserLux = -1;
mUserBrightness = -1;
+ if (DEBUG) {
+ PLOG.start("simple mapping strategy");
+ }
+ computeSpline();
}
@Override
@@ -373,27 +457,65 @@
}
@Override
+ public float getAutoBrightnessAdjustment() {
+ return mAutoBrightnessAdjustment;
+ }
+
+ @Override
+ public boolean setAutoBrightnessAdjustment(float adjustment) {
+ adjustment = MathUtils.constrain(adjustment, -1, 1);
+ if (adjustment == mAutoBrightnessAdjustment) {
+ return false;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "setAutoBrightnessAdjustment: " + mAutoBrightnessAdjustment + " => " +
+ adjustment);
+ PLOG.start("auto-brightness adjustment");
+ }
+ mAutoBrightnessAdjustment = adjustment;
+ computeSpline();
+ return true;
+ }
+
+ @Override
public float convertToNits(int backlight) {
return -1.0f;
}
@Override
public void addUserDataPoint(float lux, float brightness) {
+ float unadjustedBrightness = getUnadjustedBrightness(lux);
if (DEBUG){
- Slog.d(TAG, "addUserDataPoint(lux=" + lux + ", brightness=" + brightness + ")");
+ Slog.d(TAG, "addUserDataPoint: (" + lux + "," + brightness + ")");
+ PLOG.start("add user data point")
+ .logPoint("user data point", lux, brightness)
+ .logPoint("current brightness", lux, unadjustedBrightness);
}
- Pair<float[], float[]> curve = insertControlPoint(mLux, mBrightness, lux, brightness);
- mSpline = createSpline(curve.first, curve.second);
+ float adjustment = inferAutoBrightnessAdjustment(mMaxGamma,
+ brightness /* desiredBrightness */,
+ unadjustedBrightness /* currentBrightness */);
+ if (DEBUG) {
+ Slog.d(TAG, "addUserDataPoint: " + mAutoBrightnessAdjustment + " => " +
+ adjustment);
+ }
+ mAutoBrightnessAdjustment = adjustment;
mUserLux = lux;
mUserBrightness = brightness;
+ computeSpline();
}
@Override
public void clearUserDataPoints() {
if (mUserLux != -1) {
- mSpline = createSpline(mLux, mBrightness);
+ if (DEBUG) {
+ Slog.d(TAG, "clearUserDataPoints: " + mAutoBrightnessAdjustment + " => 0");
+ PLOG.start("clear user data points")
+ .logPoint("user data point", mUserLux, mUserBrightness);
+ }
+ mAutoBrightnessAdjustment = 0;
mUserLux = -1;
mUserBrightness = -1;
+ computeSpline();
}
}
@@ -408,15 +530,30 @@
}
@Override
- public BrightnessConfiguration getDefaultConfig() { return null; }
+ public BrightnessConfiguration getDefaultConfig() {
+ return null;
+ }
@Override
public void dump(PrintWriter pw) {
pw.println("SimpleMappingStrategy");
pw.println(" mSpline=" + mSpline);
+ pw.println(" mMaxGamma=" + mMaxGamma);
+ pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
pw.println(" mUserLux=" + mUserLux);
pw.println(" mUserBrightness=" + mUserBrightness);
}
+
+ private void computeSpline() {
+ Pair<float[], float[]> curve = getAdjustedCurve(mLux, mBrightness, mUserLux,
+ mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma);
+ mSpline = Spline.createSpline(curve.first, curve.second);
+ }
+
+ private float getUnadjustedBrightness(float lux) {
+ Spline spline = Spline.createSpline(mLux, mBrightness);
+ return spline.interpolate(lux);
+ }
}
/** A {@link BrightnessMappingStrategy} that maps from ambient room brightness to the physical
@@ -445,11 +582,13 @@
// a brightness in nits.
private Spline mBacklightToNitsSpline;
+ private float mMaxGamma;
+ private float mAutoBrightnessAdjustment;
private float mUserLux;
private float mUserBrightness;
- public PhysicalMappingStrategy(BrightnessConfiguration config,
- float[] nits, int[] backlight) {
+ public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
+ int[] backlight, float maxGamma) {
Preconditions.checkArgument(nits.length != 0 && backlight.length != 0,
"Nits and backlight arrays must not be empty!");
Preconditions.checkArgument(nits.length == backlight.length,
@@ -459,6 +598,8 @@
Preconditions.checkArrayElementsInRange(backlight,
PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight");
+ mMaxGamma = maxGamma;
+ mAutoBrightnessAdjustment = 0;
mUserLux = -1;
mUserBrightness = -1;
@@ -469,11 +610,15 @@
normalizedBacklight[i] = normalizeAbsoluteBrightness(backlight[i]);
}
- mNitsToBacklightSpline = createSpline(nits, normalizedBacklight);
- mBacklightToNitsSpline = createSpline(normalizedBacklight, nits);
+ mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight);
+ mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits);
mDefaultConfig = config;
- setBrightnessConfiguration(config);
+ if (DEBUG) {
+ PLOG.start("physical mapping strategy");
+ }
+ mConfig = config;
+ computeSpline();
}
@Override
@@ -484,10 +629,11 @@
if (config.equals(mConfig)) {
return false;
}
-
- Pair<float[], float[]> curve = config.getCurve();
- mBrightnessSpline = createSpline(curve.first /*lux*/, curve.second /*nits*/);
+ if (DEBUG) {
+ PLOG.start("brightness configuration");
+ }
mConfig = config;
+ computeSpline();
return true;
}
@@ -499,31 +645,65 @@
}
@Override
+ public float getAutoBrightnessAdjustment() {
+ return mAutoBrightnessAdjustment;
+ }
+
+ @Override
+ public boolean setAutoBrightnessAdjustment(float adjustment) {
+ adjustment = MathUtils.constrain(adjustment, -1, 1);
+ if (adjustment == mAutoBrightnessAdjustment) {
+ return false;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "setAutoBrightnessAdjustment: " + mAutoBrightnessAdjustment + " => " +
+ adjustment);
+ PLOG.start("auto-brightness adjustment");
+ }
+ mAutoBrightnessAdjustment = adjustment;
+ computeSpline();
+ return true;
+ }
+
+ @Override
public float convertToNits(int backlight) {
return mBacklightToNitsSpline.interpolate(normalizeAbsoluteBrightness(backlight));
}
@Override
- public void addUserDataPoint(float lux, float backlight) {
+ public void addUserDataPoint(float lux, float brightness) {
+ float unadjustedBrightness = getUnadjustedBrightness(lux);
if (DEBUG){
- Slog.d(TAG, "addUserDataPoint(lux=" + lux + ", backlight=" + backlight + ")");
+ Slog.d(TAG, "addUserDataPoint: (" + lux + "," + brightness + ")");
+ PLOG.start("add user data point")
+ .logPoint("user data point", lux, brightness)
+ .logPoint("current brightness", lux, unadjustedBrightness);
}
- float brightness = mBacklightToNitsSpline.interpolate(backlight);
- Pair<float[], float[]> defaultCurve = mConfig.getCurve();
- Pair<float[], float[]> newCurve =
- insertControlPoint(defaultCurve.first, defaultCurve.second, lux, brightness);
- mBrightnessSpline = createSpline(newCurve.first, newCurve.second);
+ float adjustment = inferAutoBrightnessAdjustment(mMaxGamma,
+ brightness /* desiredBrightness */,
+ unadjustedBrightness /* currentBrightness */);
+ if (DEBUG) {
+ Slog.d(TAG, "addUserDataPoint: " + mAutoBrightnessAdjustment + " => " +
+ adjustment);
+ }
+ mAutoBrightnessAdjustment = adjustment;
mUserLux = lux;
mUserBrightness = brightness;
+ computeSpline();
}
@Override
public void clearUserDataPoints() {
if (mUserLux != -1) {
- Pair<float[], float[]> defaultCurve = mConfig.getCurve();
- mBrightnessSpline = createSpline(defaultCurve.first, defaultCurve.second);
+ if (DEBUG) {
+ Slog.d(TAG, "clearUserDataPoints: " + mAutoBrightnessAdjustment + " => 0");
+ PLOG.start("clear user data points")
+ .logPoint("user data point", mUserLux, mUserBrightness);
+ }
+ mAutoBrightnessAdjustment = 0;
mUserLux = -1;
mUserBrightness = -1;
+ computeSpline();
}
}
@@ -538,7 +718,9 @@
}
@Override
- public BrightnessConfiguration getDefaultConfig() { return mDefaultConfig; }
+ public BrightnessConfiguration getDefaultConfig() {
+ return mDefaultConfig;
+ }
@Override
public void dump(PrintWriter pw) {
@@ -546,8 +728,35 @@
pw.println(" mConfig=" + mConfig);
pw.println(" mBrightnessSpline=" + mBrightnessSpline);
pw.println(" mNitsToBacklightSpline=" + mNitsToBacklightSpline);
+ pw.println(" mMaxGamma=" + mMaxGamma);
+ pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
pw.println(" mUserLux=" + mUserLux);
pw.println(" mUserBrightness=" + mUserBrightness);
}
+
+ private void computeSpline() {
+ Pair<float[], float[]> defaultCurve = mConfig.getCurve();
+ float[] defaultLux = defaultCurve.first;
+ float[] defaultNits = defaultCurve.second;
+ float[] defaultBacklight = new float[defaultNits.length];
+ for (int i = 0; i < defaultBacklight.length; i++) {
+ defaultBacklight[i] = mNitsToBacklightSpline.interpolate(defaultNits[i]);
+ }
+ Pair<float[], float[]> curve = getAdjustedCurve(defaultLux, defaultBacklight, mUserLux,
+ mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma);
+ float[] lux = curve.first;
+ float[] backlight = curve.second;
+ float[] nits = new float[backlight.length];
+ for (int i = 0; i < nits.length; i++) {
+ nits[i] = mBacklightToNitsSpline.interpolate(backlight[i]);
+ }
+ mBrightnessSpline = Spline.createSpline(lux, nits);
+ }
+
+ private float getUnadjustedBrightness(float lux) {
+ Pair<float[], float[]> curve = mConfig.getCurve();
+ Spline spline = Spline.createSpline(curve.first, curve.second);
+ return mNitsToBacklightSpline.interpolate(spline.interpolate(lux));
+ }
}
}
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index b3d309d..37035c3 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -300,6 +300,11 @@
dtm.setColorMode(mode, mIsActivated ? mMatrixNight : MATRIX_IDENTITY);
}
+ @Override
+ public void onAccessibilityTransformChanged(boolean state) {
+ onDisplayColorModeChanged(mController.getColorMode());
+ }
+
/**
* Set coefficients based on native mode. Use DisplayTransformManager#isNativeModeEnabled while
* setting is stable; when setting is changing, pass native mode selection directly.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 93e0bd5..0f531a8 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -36,11 +36,13 @@
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Point;
import android.hardware.SensorManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
import android.hardware.display.BrightnessConfiguration;
+import android.hardware.display.Curve;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayViewport;
@@ -72,8 +74,10 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.IntArray;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.Spline;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -276,6 +280,11 @@
private final Injector mInjector;
+ // The minimum brightness curve, which guarantess that any brightness curve that dips below it
+ // is rejected by the system.
+ private final Curve mMinimumBrightnessCurve;
+ private final Spline mMinimumBrightnessSpline;
+
public DisplayManagerService(Context context) {
this(context, new Injector());
}
@@ -289,8 +298,15 @@
mUiHandler = UiThread.getHandler();
mDisplayAdapterListener = new DisplayAdapterListener();
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
+ Resources resources = mContext.getResources();
mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
+ float[] lux = getFloatArray(resources.obtainTypedArray(
+ com.android.internal.R.array.config_minimumBrightnessCurveLux));
+ float[] nits = getFloatArray(resources.obtainTypedArray(
+ com.android.internal.R.array.config_minimumBrightnessCurveNits));
+ mMinimumBrightnessCurve = new Curve(lux, nits);
+ mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
@@ -1032,9 +1048,15 @@
}
}
+ @VisibleForTesting
+ Curve getMinimumBrightnessCurveInternal() {
+ return mMinimumBrightnessCurve;
+ }
+
private void setBrightnessConfigurationForUserInternal(
@Nullable BrightnessConfiguration c, @UserIdInt int userId,
@Nullable String packageName) {
+ validateBrightnessConfiguration(c);
final int userSerial = getUserManager().getUserSerialNumber(userId);
synchronized (mSyncRoot) {
try {
@@ -1049,6 +1071,28 @@
}
}
+ @VisibleForTesting
+ void validateBrightnessConfiguration(BrightnessConfiguration config) {
+ if (config == null) {
+ return;
+ }
+ if (isBrightnessConfigurationTooDark(config)) {
+ throw new IllegalArgumentException("brightness curve is too dark");
+ }
+ }
+
+ private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) {
+ Pair<float[], float[]> curve = config.getCurve();
+ float[] lux = curve.first;
+ float[] nits = curve.second;
+ for (int i = 0; i < lux.length; i++) {
+ if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void loadBrightnessConfiguration() {
synchronized (mSyncRoot) {
final int userSerial = getUserManager().getUserSerialNumber(mCurrentUserId);
@@ -1369,6 +1413,16 @@
}
}
+ private static float[] getFloatArray(TypedArray array) {
+ int length = array.length();
+ float[] floatArray = new float[length];
+ for (int i = 0; i < length; i++) {
+ floatArray[i] = array.getFloat(i, Float.NaN);
+ }
+ array.recycle();
+ return floatArray;
+ }
+
/**
* This is the object that everything in the display manager locks on.
* We make it an inner class within the {@link DisplayManagerService} to so that it is
@@ -1999,6 +2053,16 @@
}
}
+ @Override // Binder call
+ public Curve getMinimumBrightnessCurve() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getMinimumBrightnessCurveInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
void setBrightness(int brightness) {
Settings.System.putIntForUser(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1784ef1..5f4c8ef 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -424,9 +424,6 @@
com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
int ambientLightHorizon = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);
- float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
- com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
- 1, 1);
int lightSensorWarmUpTimeConfig = resources.getInteger(
com.android.internal.R.integer.config_lightSensorWarmupTime);
@@ -450,7 +447,7 @@
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
autoBrightnessResetAmbientLuxAfterWarmUp, ambientLightHorizon,
- autoBrightnessAdjustmentMaxGamma, dynamicHysteresis);
+ dynamicHysteresis);
} else {
mUseSoftwareAutoBrightnessConfig = false;
}
diff --git a/services/core/java/com/android/server/display/utils/Plog.java b/services/core/java/com/android/server/display/utils/Plog.java
new file mode 100644
index 0000000..3a18387
--- /dev/null
+++ b/services/core/java/com/android/server/display/utils/Plog.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 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.display.utils;
+
+
+import java.lang.StringBuilder;
+import java.lang.System;
+
+import android.util.Slog;
+
+/**
+ * A utility to log multiple points and curves in a structured way so they can be easily consumed
+ * by external tooling
+ *
+ * To start a plot, call {@link Plog.start} with the plot's title; to add a point to it, call
+ * {@link Plog.logPoint} with the point name (that will appear in the legend) and coordinates; and
+ * to log a curve, call {@link Plog.logCurve} with its name and points.
+ */
+public abstract class Plog {
+ // A unique identifier used to group points and curves that belong on the same plot.
+ private long mId;
+
+ /**
+ * Returns a Plog instance that emits messages to the system log.
+ *
+ * @param tag The tag of the emitted messages in the system log.
+ * @return A plog instance that emits messages to the system log.
+ */
+ public static Plog createSystemPlog(String tag) {
+ return new SystemPlog(tag);
+ }
+
+ /**
+ * Start a new plot.
+ *
+ * @param title The plot title.
+ * @return The Plog instance (for chaining).
+ */
+ public Plog start(String title) {
+ mId = System.currentTimeMillis();
+ write(formatTitle(title));
+ return this;
+ }
+
+ /**
+ * Adds a point to the current plot.
+ *
+ * @param name The point name (that will appear in the legend).
+ * @param x The point x coordinate.
+ * @param y The point y coordinate.
+ * @return The Plog instance (for chaining).
+ */
+ public Plog logPoint(String name, float x, float y) {
+ write(formatPoint(name, x, y));
+ return this;
+ }
+
+ /**
+ * Adds a curve to the current plot.
+ *
+ * @param name The curve name (that will appear in the legend).
+ * @param xs The curve x coordinates.
+ * @param ys The curve y coordinates.
+ * @return The Plog instance (for chaining).
+ */
+ public Plog logCurve(String name, float[] xs, float[] ys) {
+ write(formatCurve(name, xs, ys));
+ return this;
+ }
+
+ private String formatTitle(String title) {
+ return "title: " + title;
+ }
+
+ private String formatPoint(String name, float x, float y) {
+ return "point: " + name + ": (" + x + "," + y + ")";
+ }
+
+ private String formatCurve(String name, float[] xs, float[] ys) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("curve: " + name + ": [");
+ int n = xs.length <= ys.length ? xs.length : ys.length;
+ for (int i = 0; i < n; i++) {
+ sb.append("(" + xs[i] + "," + ys[i] + "),");
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ private void write(String message) {
+ emit("[PLOG " + mId + "] " + message);
+ }
+
+ /**
+ * Emits a message (depending on the concrete Plog implementation).
+ *
+ * @param message The message.
+ */
+ protected abstract void emit(String message);
+
+ /**
+ * A Plog that emits messages to the system log.
+ */
+ public static class SystemPlog extends Plog {
+ // The tag of the emitted messages in the system log.
+ private final String mTag;
+
+ /**
+ * Returns a Plog instance that emits messages to the system log.
+ *
+ * @param tag The tag of the emitted messages in the system log.
+ * @return A Plog instance that emits messages to the system log.
+ */
+ public SystemPlog(String tag) {
+ mTag = tag;
+ }
+
+ /**
+ * Emits a message to the system log.
+ *
+ * @param message The message.
+ */
+ protected void emit(String message) {
+ Slog.d(mTag, message);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 66817fa..736aa46 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -127,7 +127,7 @@
* Any function with the suffix 'Locked' also needs to lock on {@link #mJobs}.
* @hide
*/
-public final class JobSchedulerService extends com.android.server.SystemService
+public class JobSchedulerService extends com.android.server.SystemService
implements StateChangedListener, JobCompletedListener {
public static final String TAG = "JobScheduler";
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -781,6 +781,10 @@
}
};
+ public Context getTestableContext() {
+ return getContext();
+ }
+
public Object getLock() {
return mLock;
}
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 8365fd2..0c66c5b 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -30,12 +30,12 @@
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.TrafficStats;
-import android.os.Process;
import android.os.UserHandle;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -46,6 +46,7 @@
import com.android.server.job.JobServiceContext;
import com.android.server.job.StateControllerProto;
+import java.util.Objects;
import java.util.function.Predicate;
/**
@@ -63,7 +64,6 @@
private final ConnectivityManager mConnManager;
private final NetworkPolicyManager mNetPolicyManager;
- private boolean mConnected;
@GuardedBy("mLock")
private final ArraySet<JobStatus> mTrackedJobs = new ArraySet<>();
@@ -74,9 +74,11 @@
mConnManager = mContext.getSystemService(ConnectivityManager.class);
mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
- mConnected = false;
+ // We're interested in all network changes; internally we match these
+ // network changes against the active network for each UID with jobs.
+ final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
+ mConnManager.registerNetworkCallback(request, mNetworkCallback);
- mConnManager.registerDefaultNetworkCallback(mNetworkCallback);
mNetPolicyManager.registerListener(mNetPolicyListener);
}
@@ -198,14 +200,18 @@
}
private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
+ final Network network = mConnManager.getActiveNetworkForUid(jobStatus.getSourceUid());
+ final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+ return updateConstraintsSatisfied(jobStatus, network, capabilities);
+ }
+
+ private boolean updateConstraintsSatisfied(JobStatus jobStatus, Network network,
+ NetworkCapabilities capabilities) {
// TODO: consider matching against non-active networks
- final int jobUid = jobStatus.getSourceUid();
final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
-
- final Network network = mConnManager.getActiveNetworkForUid(jobUid, ignoreBlocked);
- final NetworkInfo info = mConnManager.getNetworkInfoForUid(network, jobUid, ignoreBlocked);
- final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+ final NetworkInfo info = mConnManager.getNetworkInfoForUid(network,
+ jobStatus.getSourceUid(), ignoreBlocked);
final boolean connected = (info != null) && info.isConnected();
final boolean satisfied = isSatisfied(jobStatus, network, capabilities, mConstants);
@@ -218,12 +224,6 @@
// using non-default routes.
jobStatus.network = network;
- // Track system-uid connected/validated as a general reportable proxy for the
- // overall state of connectivity constraint satisfiability.
- if (jobUid == Process.SYSTEM_UID) {
- mConnected = connected;
- }
-
if (DEBUG) {
Slog.i(TAG, "Connectivity " + (changed ? "CHANGED" : "unchanged")
+ " for " + jobStatus + ": connected=" + connected
@@ -233,18 +233,48 @@
}
/**
- * Update all jobs tracked by this controller.
+ * Update any jobs tracked by this controller that match given filters.
*
- * @param uid only update jobs belonging to this UID, or {@code -1} to
+ * @param filterUid only update jobs belonging to this UID, or {@code -1} to
* update all tracked jobs.
+ * @param filterNetwork only update jobs that would use this
+ * {@link Network}, or {@code null} to update all tracked jobs.
*/
- private void updateTrackedJobs(int uid) {
+ private void updateTrackedJobs(int filterUid, Network filterNetwork) {
synchronized (mLock) {
+ // Since this is a really hot codepath, temporarily cache any
+ // answers that we get from ConnectivityManager.
+ final SparseArray<Network> uidToNetwork = new SparseArray<>();
+ final SparseArray<NetworkCapabilities> networkToCapabilities = new SparseArray<>();
+
boolean changed = false;
- for (int i = mTrackedJobs.size()-1; i >= 0; i--) {
+ for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
final JobStatus js = mTrackedJobs.valueAt(i);
- if (uid == -1 || uid == js.getSourceUid()) {
- changed |= updateConstraintsSatisfied(js);
+ final int uid = js.getSourceUid();
+
+ final boolean uidMatch = (filterUid == -1 || filterUid == uid);
+ if (uidMatch) {
+ Network network = uidToNetwork.get(uid);
+ if (network == null) {
+ network = mConnManager.getActiveNetworkForUid(uid);
+ uidToNetwork.put(uid, network);
+ }
+
+ // Update either when we have a network match, or when the
+ // job hasn't yet been evaluated against the currently
+ // active network; typically when we just lost a network.
+ final boolean networkMatch = (filterNetwork == null
+ || Objects.equals(filterNetwork, network));
+ final boolean forceUpdate = !Objects.equals(js.network, network);
+ if (networkMatch || forceUpdate) {
+ final int netId = network != null ? network.netId : -1;
+ NetworkCapabilities capabilities = networkToCapabilities.get(netId);
+ if (capabilities == null) {
+ capabilities = mConnManager.getNetworkCapabilities(network);
+ networkToCapabilities.put(netId, capabilities);
+ }
+ changed |= updateConstraintsSatisfied(js, network, capabilities);
+ }
}
}
if (changed) {
@@ -273,19 +303,19 @@
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
@Override
- public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) {
if (DEBUG) {
- Slog.v(TAG, "onCapabilitiesChanged() : " + networkCapabilities);
+ Slog.v(TAG, "onCapabilitiesChanged: " + network);
}
- updateTrackedJobs(-1);
+ updateTrackedJobs(-1, network);
}
@Override
public void onLost(Network network) {
if (DEBUG) {
- Slog.v(TAG, "Network lost");
+ Slog.v(TAG, "onLost: " + network);
}
- updateTrackedJobs(-1);
+ updateTrackedJobs(-1, network);
}
};
@@ -293,25 +323,9 @@
@Override
public void onUidRulesChanged(int uid, int uidRules) {
if (DEBUG) {
- Slog.v(TAG, "Uid rules changed for " + uid);
+ Slog.v(TAG, "onUidRulesChanged: " + uid);
}
- updateTrackedJobs(uid);
- }
-
- @Override
- public void onRestrictBackgroundChanged(boolean restrictBackground) {
- if (DEBUG) {
- Slog.v(TAG, "Background restriction change to " + restrictBackground);
- }
- updateTrackedJobs(-1);
- }
-
- @Override
- public void onUidPoliciesChanged(int uid, int uidPolicies) {
- if (DEBUG) {
- Slog.v(TAG, "Uid policy changed for " + uid);
- }
- updateTrackedJobs(uid);
+ updateTrackedJobs(uid, null);
}
};
@@ -319,9 +333,6 @@
@Override
public void dumpControllerStateLocked(IndentingPrintWriter pw,
Predicate<JobStatus> predicate) {
- pw.println("System connected: " + mConnected);
- pw.println();
-
for (int i = 0; i < mTrackedJobs.size(); i++) {
final JobStatus js = mTrackedJobs.valueAt(i);
if (predicate.test(js)) {
@@ -343,8 +354,6 @@
final long token = proto.start(fieldId);
final long mToken = proto.start(StateControllerProto.CONNECTIVITY);
- proto.write(StateControllerProto.ConnectivityController.IS_CONNECTED, mConnected);
-
for (int i = 0; i < mTrackedJobs.size(); i++) {
final JobStatus js = mTrackedJobs.valueAt(i);
if (!predicate.test(js)) {
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 495109d..c2be283 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -41,7 +41,7 @@
StateController(JobSchedulerService service) {
mService = service;
mStateChangedListener = service;
- mContext = service.getContext();
+ mContext = service.getTestableContext();
mLock = service.getLock();
mConstants = service.getConstants();
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 88b2a36..0700ab3 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -534,17 +534,33 @@
private void destroyWeaverSlot(long handle, int userId) {
int slot = loadWeaverSlot(handle, userId);
+ destroyState(WEAVER_SLOT_NAME, handle, userId);
if (slot != INVALID_WEAVER_SLOT) {
- try {
- weaverEnroll(slot, null, null);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to destroy slot", e);
+ Set<Integer> usedSlots = getUsedWeaverSlots();
+ if (!usedSlots.contains(slot)) {
+ Log.i(TAG, "Destroy weaver slot " + slot + " for user " + userId);
+ try {
+ weaverEnroll(slot, null, null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to destroy slot", e);
+ }
+ } else {
+ Log.w(TAG, "Skip destroying reused weaver slot " + slot + " for user " + userId);
}
}
- destroyState(WEAVER_SLOT_NAME, handle, userId);
}
- private int getNextAvailableWeaverSlot() {
+ /**
+ * Return the set of weaver slots that are currently in use by all users on the device.
+ * <p>
+ * <em>Note:</em> Users who are in the process of being deleted are not tracked here
+ * (due to them being marked as partial in UserManager so not visible from
+ * {@link UserManager#getUsers}). As a result their weaver slots will not be considered
+ * taken and can be reused by new users. Care should be taken when cleaning up the
+ * deleted user in {@link #removeUser}, to prevent a reused slot from being erased
+ * unintentionally.
+ */
+ private Set<Integer> getUsedWeaverSlots() {
Map<Integer, List<Long>> slotHandles = mStorage.listSyntheticPasswordHandlesForAllUsers(
WEAVER_SLOT_NAME);
HashSet<Integer> slots = new HashSet<>();
@@ -554,8 +570,13 @@
slots.add(slot);
}
}
+ return slots;
+ }
+
+ private int getNextAvailableWeaverSlot() {
+ Set<Integer> usedSlots = getUsedWeaverSlots();
for (int i = 0; i < mWeaverConfig.slots; i++) {
- if (!slots.contains(i)) {
+ if (!usedSlots.contains(i)) {
return i;
}
}
@@ -592,6 +613,7 @@
if (isWeaverAvailable()) {
// Weaver based user password
int weaverSlot = getNextAvailableWeaverSlot();
+ Log.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
byte[] weaverSecret = weaverEnroll(weaverSlot, passwordTokenToWeaverKey(pwdToken), null);
if (weaverSecret == null) {
Log.e(TAG, "Fail to enroll user password under weaver " + userId);
@@ -749,6 +771,7 @@
if (isWeaverAvailable()) {
int slot = getNextAvailableWeaverSlot();
try {
+ Log.i(TAG, "Weaver enroll token to slot " + slot + " for user " + userId);
weaverEnroll(slot, null, tokenData.weaverSecret);
} catch (RemoteException e) {
Log.e(TAG, "Failed to enroll weaver secret when activating token", e);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 224d085..8e77373 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -39,6 +39,7 @@
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
@@ -70,6 +71,12 @@
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.provider.Settings.Global.NETPOLICY_OVERRIDE_ENABLED;
+import static android.provider.Settings.Global.NETPOLICY_QUOTA_ENABLED;
+import static android.provider.Settings.Global.NETPOLICY_QUOTA_FRAC_JOBS;
+import static android.provider.Settings.Global.NETPOLICY_QUOTA_FRAC_MULTIPATH;
+import static android.provider.Settings.Global.NETPOLICY_QUOTA_LIMITED;
+import static android.provider.Settings.Global.NETPOLICY_QUOTA_UNLIMITED;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
@@ -115,6 +122,7 @@
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -188,6 +196,7 @@
import android.util.DataUnit;
import android.util.Log;
import android.util.Pair;
+import android.util.Range;
import android.util.RecurrenceRule;
import android.util.Slog;
import android.util.SparseArray;
@@ -351,6 +360,11 @@
*/
private static final long WAIT_FOR_ADMIN_DATA_TIMEOUT_MS = 10_000;
+ private static final long QUOTA_UNLIMITED_DEFAULT = DataUnit.MEBIBYTES.toBytes(20);
+ private static final float QUOTA_LIMITED_DEFAULT = 0.1f;
+ private static final float QUOTA_FRAC_JOBS_DEFAULT = 0.5f;
+ private static final float QUOTA_FRAC_MULTIPATH_DEFAULT = 0.5f;
+
private static final int MSG_RULES_CHANGED = 1;
private static final int MSG_METERED_IFACES_CHANGED = 2;
private static final int MSG_LIMIT_REACHED = 5;
@@ -491,6 +505,10 @@
@GuardedBy("mNetworkPoliciesSecondLock")
private final SparseBooleanArray mNetworkMetered = new SparseBooleanArray();
+ /** Map from network ID to last observed roaming state */
+ @GuardedBy("mNetworkPoliciesSecondLock")
+ private final SparseBooleanArray mNetworkRoaming = new SparseBooleanArray();
+
/** Map from netId to subId as of last update */
@GuardedBy("mNetworkPoliciesSecondLock")
private final SparseIntArray mNetIdToSubId = new SparseIntArray();
@@ -1006,6 +1024,16 @@
}
};
+ private static boolean updateCapabilityChange(SparseBooleanArray lastValues, boolean newValue,
+ Network network) {
+ final boolean lastValue = lastValues.get(network.netId, false);
+ final boolean changed = (lastValue != newValue) || lastValues.indexOfKey(network.netId) < 0;
+ if (changed) {
+ lastValues.put(network.netId, newValue);
+ }
+ return changed;
+ }
+
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
@Override
public void onCapabilitiesChanged(Network network,
@@ -1013,13 +1041,18 @@
if (network == null || networkCapabilities == null) return;
synchronized (mNetworkPoliciesSecondLock) {
- final boolean oldMetered = mNetworkMetered.get(network.netId, false);
final boolean newMetered = !networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ final boolean meteredChanged = updateCapabilityChange(
+ mNetworkMetered, newMetered, network);
- if ((oldMetered != newMetered) || mNetworkMetered.indexOfKey(network.netId) < 0) {
+ final boolean newRoaming = !networkCapabilities
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
+ final boolean roamingChanged = updateCapabilityChange(
+ mNetworkRoaming, newRoaming, network);
+
+ if (meteredChanged || roamingChanged) {
mLogger.meterednessChanged(network.netId, newMetered);
- mNetworkMetered.put(network.netId, newMetered);
updateNetworkRulesNL();
}
}
@@ -1739,10 +1772,18 @@
}
mMeteredIfaces = newMeteredIfaces;
+ final ContentResolver cr = mContext.getContentResolver();
+ final boolean quotaEnabled = Settings.Global.getInt(cr,
+ NETPOLICY_QUOTA_ENABLED, 1) != 0;
+ final long quotaUnlimited = Settings.Global.getLong(cr,
+ NETPOLICY_QUOTA_UNLIMITED, QUOTA_UNLIMITED_DEFAULT);
+ final float quotaLimited = Settings.Global.getFloat(cr,
+ NETPOLICY_QUOTA_LIMITED, QUOTA_LIMITED_DEFAULT);
+
// Finally, calculate our opportunistic quotas
- // TODO: add experiments support to disable or tweak ratios
mSubscriptionOpportunisticQuota.clear();
for (NetworkState state : states) {
+ if (!quotaEnabled) continue;
if (state.network == null) continue;
final int subId = getSubIdLocked(state.network);
final SubscriptionPlan plan = getPrimarySubscriptionPlanLocked(subId);
@@ -1750,18 +1791,21 @@
final long quotaBytes;
final long limitBytes = plan.getDataLimitBytes();
- if (limitBytes == SubscriptionPlan.BYTES_UNKNOWN) {
+ if (!state.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING)) {
+ // Clamp to 0 when roaming
+ quotaBytes = 0;
+ } else if (limitBytes == SubscriptionPlan.BYTES_UNKNOWN) {
quotaBytes = OPPORTUNISTIC_QUOTA_UNKNOWN;
} else if (limitBytes == SubscriptionPlan.BYTES_UNLIMITED) {
// Unlimited data; let's use 20MiB/day (600MiB/month)
- quotaBytes = DataUnit.MEBIBYTES.toBytes(20);
+ quotaBytes = quotaUnlimited;
} else {
// Limited data; let's only use 10% of remaining budget
- final Pair<ZonedDateTime, ZonedDateTime> cycle = plan.cycleIterator().next();
- final long start = cycle.first.toInstant().toEpochMilli();
- final long end = cycle.second.toInstant().toEpochMilli();
+ final Range<ZonedDateTime> cycle = plan.cycleIterator().next();
+ final long start = cycle.getLower().toInstant().toEpochMilli();
+ final long end = cycle.getUpper().toInstant().toEpochMilli();
final Instant now = mClock.instant();
- final long startOfDay = ZonedDateTime.ofInstant(now, cycle.first.getZone())
+ final long startOfDay = ZonedDateTime.ofInstant(now, cycle.getLower().getZone())
.truncatedTo(ChronoUnit.DAYS)
.toInstant().toEpochMilli();
final long totalBytes = getTotalBytes(
@@ -1772,7 +1816,7 @@
final long remainingDays =
1 + ((end - now.toEpochMilli() - 1) / TimeUnit.DAYS.toMillis(1));
- quotaBytes = Math.max(0, (remainingBytes / remainingDays) / 10);
+ quotaBytes = Math.max(0, (long) ((remainingBytes / remainingDays) * quotaLimited));
}
mSubscriptionOpportunisticQuota.put(subId, quotaBytes);
@@ -3048,11 +3092,17 @@
}
}
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
- overrideMask, overrideValue, subId));
- if (timeoutMillis > 0) {
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
- overrideMask, 0, subId), timeoutMillis);
+ // Only allow overrides when feature is enabled. However, we always
+ // allow disabling of overrides for safety reasons.
+ final boolean overrideEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+ NETPOLICY_OVERRIDE_ENABLED, 1) != 0;
+ if (overrideEnabled || overrideValue == 0) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
+ overrideMask, overrideValue, subId));
+ if (timeoutMillis > 0) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
+ overrideMask, 0, subId), timeoutMillis);
+ }
}
}
@@ -4695,11 +4745,24 @@
@Override
public long getSubscriptionOpportunisticQuota(Network network, int quotaType) {
+ final long quotaBytes;
synchronized (mNetworkPoliciesSecondLock) {
- // TODO: handle splitting quota between use-cases
- return mSubscriptionOpportunisticQuota.get(getSubIdLocked(network),
+ quotaBytes = mSubscriptionOpportunisticQuota.get(getSubIdLocked(network),
OPPORTUNISTIC_QUOTA_UNKNOWN);
}
+ if (quotaBytes == OPPORTUNISTIC_QUOTA_UNKNOWN) {
+ return OPPORTUNISTIC_QUOTA_UNKNOWN;
+ }
+
+ if (quotaType == QUOTA_TYPE_JOBS) {
+ return (long) (quotaBytes * Settings.Global.getFloat(mContext.getContentResolver(),
+ NETPOLICY_QUOTA_FRAC_JOBS, QUOTA_FRAC_JOBS_DEFAULT));
+ } else if (quotaType == QUOTA_TYPE_MULTIPATH) {
+ return (long) (quotaBytes * Settings.Global.getFloat(mContext.getContentResolver(),
+ NETPOLICY_QUOTA_FRAC_MULTIPATH, QUOTA_FRAC_MULTIPATH_DEFAULT));
+ } else {
+ return OPPORTUNISTIC_QUOTA_UNKNOWN;
+ }
}
@Override
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 2ef754e..ab52523 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -47,7 +47,7 @@
import android.util.AtomicFile;
import android.util.IntArray;
import android.util.MathUtils;
-import android.util.Pair;
+import android.util.Range;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -266,11 +266,11 @@
long collectEnd = end;
if (augmentEnd != SubscriptionPlan.TIME_UNKNOWN) {
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = augmentPlan.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = augmentPlan.cycleIterator();
while (it.hasNext()) {
- final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next();
- final long cycleStart = cycle.first.toInstant().toEpochMilli();
- final long cycleEnd = cycle.second.toInstant().toEpochMilli();
+ final Range<ZonedDateTime> cycle = it.next();
+ final long cycleStart = cycle.getLower().toInstant().toEpochMilli();
+ final long cycleEnd = cycle.getUpper().toInstant().toEpochMilli();
if (cycleStart <= augmentEnd && augmentEnd < cycleEnd) {
augmentStart = cycleStart;
collectStart = Long.min(collectStart, augmentStart);
diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
index 17c5868..766d8ca 100644
--- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
@@ -91,7 +91,7 @@
final long ident = Binder.clearCallingIdentity();
try {
// Reset last report time
- if (!WatchlistConfig.getInstance().isConfigSecure()) {
+ if (WatchlistConfig.getInstance().isConfigSecure()) {
pw.println("Error: Cannot force generate report under production config");
return -1;
}
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index 6cf8f86..639cc70 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.app.Notification;
+import android.app.Person;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
@@ -332,8 +333,8 @@
return array;
}
- if (arrayList.get(0) instanceof Notification.Person) {
- ArrayList<Notification.Person> list = (ArrayList<Notification.Person>) arrayList;
+ if (arrayList.get(0) instanceof Person) {
+ ArrayList<Person> list = (ArrayList<Person>) arrayList;
final int N = list.size();
String[] array = new String[N];
for (int i = 0; i < N; i++) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 586abc1..156f702 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -32,6 +32,7 @@
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
+import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
@@ -1198,8 +1199,6 @@
@VisibleForTesting
protected Notification createZenUpgradeNotification() {
- Intent intent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
mContext.getResources().getString(R.string.global_action_settings));
@@ -1210,15 +1209,20 @@
title = R.string.zen_upgrade_notification_visd_title;
content = R.string.zen_upgrade_notification_visd_content;
}
+ Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
+ onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
+ .setAutoCancel(true)
.setSmallIcon(R.drawable.ic_settings_24dp)
+ .setLargeIcon(Icon.createWithResource(mContext, R.drawable.ic_zen_24dp))
.setContentTitle(mContext.getResources().getString(title))
.setContentText(mContext.getResources().getString(content))
+ .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT))
.setAutoCancel(true)
.setLocalOnly(true)
.addExtras(extras)
.setStyle(new Notification.BigTextStyle())
- .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0, null))
.build();
}
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index bc9fa4b..dbf0940 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -256,8 +256,6 @@
int flags = origIntent.getFlags();
final Intent intent = new Intent();
intent.setFlags(flags
- | Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
if (token != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 26d4037..5b45cbe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5305,7 +5305,7 @@
synchronized (mPackages) {
final String[] packageNames = getPackagesForUid(uid);
final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
- ? mPackages.get(packageNames[0])
+ ? mSettings.getPackageLPr(packageNames[0]).getPackage()
: null;
return mPermissionManager.checkUidPermission(permName, pkg, uid, getCallingUid());
}
@@ -8071,7 +8071,6 @@
callingUid = mIsolatedOwners.get(callingUid);
}
final PackageSetting ps = mSettings.mPackages.get(packageName);
- PackageParser.Package pkg = mPackages.get(packageName);
final boolean returnAllowed =
ps != null
&& (isCallerSameApp(packageName, callingUid)
@@ -8142,7 +8141,7 @@
}
private boolean isCallerSameApp(String packageName, int uid) {
- PackageParser.Package pkg = mPackages.get(packageName);
+ PackageParser.Package pkg = mSettings.getPackageLPr(packageName).getPackage();
return pkg != null
&& UserHandle.getAppId(uid) == pkg.applicationInfo.uid;
}
@@ -23625,6 +23624,13 @@
}
@Override
+ public Object getPackageSetting(String packageName) {
+ synchronized (mPackages) {
+ return mSettings.getPackageLPr(packageName);
+ }
+ }
+
+ @Override
public PackageList getPackageList(PackageListObserver observer) {
synchronized (mPackages) {
final int N = mPackages.size();
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 f5b52fc..065133b 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -212,12 +212,11 @@
return PackageManager.PERMISSION_DENIED;
}
- final PackageParser.Package pkg = mPackageManagerInt.getPackage(pkgName);
- if (pkg != null && pkg.mExtras != null) {
- if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+ final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(pkgName);
+ if (ps != null && ps.getPackage() != null) {
+ if (mPackageManagerInt.filterAppAccess(ps.getPackage(), callingUid, userId)) {
return PackageManager.PERMISSION_DENIED;
}
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
final boolean instantApp = ps.getInstantApp(userId);
final PermissionsState permissionsState = ps.getPermissionsState();
if (permissionsState.hasPermission(permName, userId)) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 9a25dcc..46a636c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -87,6 +87,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -618,6 +619,7 @@
boolean mTranslucentDecorEnabled = true;
boolean mUseTvRouting;
int mVeryLongPressTimeout;
+ boolean mAllowStartActivityForLongPressOnPowerDuringSetup;
private boolean mHandleVolumeKeysInWM;
@@ -1622,7 +1624,11 @@
: mKeyguardDelegate.isShowing();
if (!keyguardActive) {
Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
- startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ if (mAllowStartActivityForLongPressOnPowerDuringSetup) {
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ } else {
+ startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ }
}
break;
}
@@ -2134,6 +2140,8 @@
com.android.internal.R.integer.config_shortPressOnSleepBehavior);
mVeryLongPressTimeout = mContext.getResources().getInteger(
com.android.internal.R.integer.config_veryLongPressTimeout);
+ mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);
mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
@@ -5404,6 +5412,12 @@
final boolean attachedInParent = attached != null && !layoutInScreen;
final boolean requestedHideNavigation =
(requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
+
+ // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
+ // cropped / shifted to the displayFrame in WindowState.
+ final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
+ && type != TYPE_BASE_APPLICATION;
+
// Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
// the cutout safe zone.
if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
@@ -5438,7 +5452,10 @@
}
// Windows that are attached to a parent and laid out in said parent already avoid
// the cutout according to that parent and don't need to be further constrained.
- if (!attachedInParent) {
+ // Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
+ // They will later be cropped or shifted using the displayFrame in WindowState,
+ // which prevents overlap with the DisplayCutout.
+ if (!attachedInParent && !floatingInScreenWindow) {
mTmpRect.set(pf);
pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
parentFrameWasClippedByDisplayCutout |= !mTmpRect.equals(pf);
@@ -8013,29 +8030,35 @@
private VibrationEffect getVibrationEffect(int effectId) {
long[] pattern;
switch (effectId) {
- case HapticFeedbackConstants.LONG_PRESS:
- pattern = mLongPressVibePattern;
- break;
case HapticFeedbackConstants.CLOCK_TICK:
+ case HapticFeedbackConstants.CONTEXT_CLICK:
return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
+ case HapticFeedbackConstants.KEYBOARD_RELEASE:
+ case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
+ case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
+ case HapticFeedbackConstants.ENTRY_BUMP:
+ case HapticFeedbackConstants.DRAG_CROSSING:
+ case HapticFeedbackConstants.GESTURE_END:
+ return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
+ case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS
+ case HapticFeedbackConstants.VIRTUAL_KEY:
+ case HapticFeedbackConstants.EDGE_RELEASE:
+ case HapticFeedbackConstants.CONFIRM:
+ case HapticFeedbackConstants.GESTURE_START:
+ return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
+ case HapticFeedbackConstants.LONG_PRESS:
+ case HapticFeedbackConstants.EDGE_SQUEEZE:
+ return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
+ case HapticFeedbackConstants.REJECT:
+ return VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
+
case HapticFeedbackConstants.CALENDAR_DATE:
pattern = mCalendarDateVibePattern;
break;
case HapticFeedbackConstants.SAFE_MODE_ENABLED:
pattern = mSafeModeEnabledVibePattern;
break;
- case HapticFeedbackConstants.CONTEXT_CLICK:
- return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
- case HapticFeedbackConstants.VIRTUAL_KEY:
- return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
- case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
- return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
- case HapticFeedbackConstants.KEYBOARD_PRESS: // == HapticFeedbackConstants.KEYBOARD_TAP
- return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
- case HapticFeedbackConstants.KEYBOARD_RELEASE:
- return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
- case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
- return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
+
default:
return null;
}
@@ -8655,6 +8678,9 @@
pw.print("mShortPressOnWindowBehavior=");
pw.println(shortPressOnWindowBehaviorToString(mShortPressOnWindowBehavior));
pw.print(prefix);
+ pw.print("mAllowStartActivityForLongPressOnPowerDuringSetup=");
+ pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup);
+ pw.print(prefix);
pw.print("mHasSoftInput="); pw.print(mHasSoftInput);
pw.print(" mDismissImeOnBackKeyPressed="); pw.println(mDismissImeOnBackKeyPressed);
pw.print(prefix);
diff --git a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java b/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
index 416469b..9c00d1a 100644
--- a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
+++ b/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
@@ -37,6 +37,8 @@
private ArrayList<Runnable> mTmpRunnableList = new ArrayList<>();
+ private boolean mEndingDeferredFinish;
+
/**
* Notifies that an {@link AppWindowToken} has started animating.
*/
@@ -50,6 +52,11 @@
void notifyFinished(AppWindowToken token) {
mAnimatingTokens.remove(token);
mFinishedTokens.remove(token);
+
+ // If we were the last token, make sure the end all deferred finishes.
+ if (mAnimatingTokens.isEmpty()) {
+ endDeferringFinished();
+ }
}
/**
@@ -78,16 +85,28 @@
}
private void endDeferringFinished() {
- // Copy it into a separate temp list to avoid modifying the collection while iterating as
- // calling the callback may call back into notifyFinished.
- for (int i = mFinishedTokens.size() - 1; i >= 0; i--) {
- mTmpRunnableList.add(mFinishedTokens.valueAt(i));
+
+ // Don't start recursing. Running the finished listener invokes notifyFinished, which may
+ // invoked us again.
+ if (mEndingDeferredFinish) {
+ return;
}
- mFinishedTokens.clear();
- for (int i = mTmpRunnableList.size() - 1; i >= 0; i--) {
- mTmpRunnableList.get(i).run();
+ try {
+ mEndingDeferredFinish = true;
+
+ // Copy it into a separate temp list to avoid modifying the collection while iterating
+ // as calling the callback may call back into notifyFinished.
+ for (int i = mFinishedTokens.size() - 1; i >= 0; i--) {
+ mTmpRunnableList.add(mFinishedTokens.valueAt(i));
+ }
+ mFinishedTokens.clear();
+ for (int i = mTmpRunnableList.size() - 1; i >= 0; i--) {
+ mTmpRunnableList.get(i).run();
+ }
+ mTmpRunnableList.clear();
+ } finally {
+ mEndingDeferredFinish = false;
}
- mTmpRunnableList.clear();
}
void dump(PrintWriter pw, String header, String prefix) {
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 1575694..165a409 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -113,63 +113,73 @@
mListener.onWindowsGone();
};
- private final Runnable mAddStartingWindow = () -> {
- final StartingData startingData;
- final AppWindowToken container;
+ private final Runnable mAddStartingWindow = new Runnable() {
- synchronized (mWindowMap) {
- if (mContainer == null) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
- + " add starting window");
+ @Override
+ public void run() {
+ final StartingData startingData;
+ final AppWindowToken container;
+
+ synchronized (mWindowMap) {
+ if (mContainer == null) {
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
+ + " add starting window");
+ return;
+ }
+
+ // There can only be one adding request, silly caller!
+ mService.mAnimationHandler.removeCallbacks(this);
+
+ startingData = mContainer.startingData;
+ container = mContainer;
+ }
+
+ if (startingData == null) {
+ // Animation has been canceled... do nothing.
+ if (DEBUG_STARTING_WINDOW)
+ Slog.v(TAG_WM, "startingData was nulled out before handling"
+ + " mAddStartingWindow: " + mContainer);
return;
}
- startingData = mContainer.startingData;
- container = mContainer;
- }
- if (startingData == null) {
- // Animation has been canceled... do nothing.
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "startingData was nulled out before handling"
- + " mAddStartingWindow: " + mContainer);
- return;
- }
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
+ + AppWindowContainerController.this + ": startingData="
+ + container.startingData);
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
- + this + ": startingData=" + container.startingData);
-
- StartingSurface surface = null;
- try {
- surface = startingData.createStartingSurface(container);
- } catch (Exception e) {
- Slog.w(TAG_WM, "Exception when adding starting window", e);
- }
- if (surface != null) {
- boolean abort = false;
- synchronized(mWindowMap) {
- // If the window was successfully added, then
- // we need to remove it.
- if (container.removed || container.startingData == null) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
- "Aborted starting " + container
- + ": removed=" + container.removed
- + " startingData=" + container.startingData);
- container.startingWindow = null;
- container.startingData = null;
- abort = true;
- } else {
- container.startingSurface = surface;
+ StartingSurface surface = null;
+ try {
+ surface = startingData.createStartingSurface(container);
+ } catch (Exception e) {
+ Slog.w(TAG_WM, "Exception when adding starting window", e);
+ }
+ if (surface != null) {
+ boolean abort = false;
+ synchronized (mWindowMap) {
+ // If the window was successfully added, then
+ // we need to remove it.
+ if (container.removed || container.startingData == null) {
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
+ "Aborted starting " + container
+ + ": removed=" + container.removed
+ + " startingData=" + container.startingData);
+ container.startingWindow = null;
+ container.startingData = null;
+ abort = true;
+ } else {
+ container.startingSurface = surface;
+ }
+ if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
+ "Added starting " + mContainer
+ + ": startingWindow="
+ + container.startingWindow + " startingView="
+ + container.startingSurface);
}
- if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
- "Added starting " + mContainer
- + ": startingWindow="
- + container.startingWindow + " startingView="
- + container.startingSurface);
+ if (abort) {
+ surface.remove();
+ }
+ } else if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG_WM, "Surface returned was null: " + mContainer);
}
- if (abort) {
- surface.remove();
- }
- } else if (DEBUG_STARTING_WINDOW) {
- Slog.v(TAG_WM, "Surface returned was null: " + mContainer);
}
};
@@ -558,8 +568,10 @@
// Note: we really want to do sendMessageAtFrontOfQueue() because we
// want to process the message ASAP, before any other queued
// messages.
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
- mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
+ if (!mService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
+ mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
+ }
}
private boolean createSnapshot(TaskSnapshot snapshot) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 8fa94fb..9a4db65 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1714,7 +1714,8 @@
adapter = new LocalAnimationAdapter(
new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
mService.mAppTransition.canSkipFirstFrame(),
- mService.mAppTransition.getAppStackClipMode()),
+ mService.mAppTransition.getAppStackClipMode(),
+ true /* isAppAnimation */),
mService.mSurfaceAnimationRunner);
if (a.getZAdjustment() == Animation.ZORDER_TOP) {
mNeedsZBoost = true;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0771b53..79eb2c9 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3728,8 +3728,12 @@
mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
- if (policy.isKeyguardShowingAndNotOccluded()
- || mService.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
+ // Only allow force setting the orientation when all unknown visibilities have been
+ // resolved, as otherwise we just may be starting another occluding activity.
+ final boolean isUnoccluding =
+ mService.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
+ && mService.mUnknownAppVisibilityController.allResolved();
+ if (policy.isKeyguardShowingAndNotOccluded() || isUnoccluding) {
return mLastKeyguardForcedOrientation;
}
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
index 529aacc..d89d6f0 100644
--- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -146,6 +146,13 @@
return false;
}
+ /**
+ * @return {@code true} if we need to wake-up SurfaceFlinger earlier during this animation.
+ *
+ * @see Transaction#setEarlyWakeup
+ */
+ default boolean needsEarlyWakeup() { return false; }
+
void dump(PrintWriter pw, String prefix);
default void writeToProto(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index c4f5197..bae93f3 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -18,8 +18,10 @@
import static android.app.ActivityManagerInternal.APP_TRANSITION_RECENTS_ANIM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -49,6 +51,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import com.android.internal.annotations.VisibleForTesting;
import com.google.android.collect.Sets;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
@@ -68,14 +71,14 @@
private static final boolean DEBUG = false;
private static final long FAILSAFE_DELAY = 1000;
- public static final int REORDER_KEEP_HOME_IN_PLACE = 0;
- public static final int REORDER_MOVE_HOME_TO_TOP = 1;
- public static final int REORDER_MOVE_HOME_TO_ORIGINAL_POSITION = 2;
+ public static final int REORDER_KEEP_IN_PLACE = 0;
+ public static final int REORDER_MOVE_TO_TOP = 1;
+ public static final int REORDER_MOVE_TO_ORIGINAL_POSITION = 2;
@IntDef(prefix = { "REORDER_MODE_" }, value = {
- REORDER_KEEP_HOME_IN_PLACE,
- REORDER_MOVE_HOME_TO_TOP,
- REORDER_MOVE_HOME_TO_ORIGINAL_POSITION
+ REORDER_KEEP_IN_PLACE,
+ REORDER_MOVE_TO_TOP,
+ REORDER_MOVE_TO_ORIGINAL_POSITION
})
public @interface ReorderMode {}
@@ -85,11 +88,11 @@
private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
private final int mDisplayId;
private final Runnable mFailsafeRunnable = () -> {
- cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
+ cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
};
// The recents component app token that is shown behind the visibile tasks
- private AppWindowToken mHomeAppToken;
+ private AppWindowToken mTargetAppToken;
private Rect mMinimizedHomeBounds = new Rect();
// We start the RecentsAnimationController in a pending-start state since we need to wait for
@@ -108,7 +111,9 @@
// minimized
private boolean mSplitScreenMinimized;
- private Rect mTmpRect = new Rect();
+ private final Rect mTmpRect = new Rect();
+
+ private boolean mLinkedToDeathOfRunner;
public interface RecentsAnimationCallbacks {
void onAnimationFinished(@ReorderMode int reorderMode);
@@ -160,8 +165,8 @@
// Note, the callback will handle its own synchronization, do not lock on WM lock
// prior to calling the callback
mCallbacks.onAnimationFinished(moveHomeToTop
- ? REORDER_MOVE_HOME_TO_TOP
- : REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
+ ? REORDER_MOVE_TO_TOP
+ : REORDER_MOVE_TO_ORIGINAL_POSITION);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -240,7 +245,7 @@
* because it may call cancelAnimation() which needs to properly clean up the controller
* in the window manager.
*/
- public void initialize(SparseBooleanArray recentTaskIds) {
+ public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) {
// Make leashes for each of the visible tasks and add it to the recents animation to be
// started
final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
@@ -251,7 +256,7 @@
final WindowConfiguration config = task.getWindowConfiguration();
if (config.tasksAreFloating()
|| config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || config.getActivityType() == ACTIVITY_TYPE_HOME) {
+ || config.getActivityType() == targetActivityType) {
continue;
}
addAnimation(task, !recentTaskIds.get(task.mTaskId));
@@ -259,23 +264,23 @@
// Skip the animation if there is nothing to animate
if (mPendingAnimations.isEmpty()) {
- cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
+ cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
return;
}
try {
- mRunner.asBinder().linkToDeath(this, 0);
+ linkToDeathOfRunner();
} catch (RemoteException e) {
- cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
+ cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
return;
}
- // Adjust the wallpaper visibility for the showing home activity
- final AppWindowToken recentsComponentAppToken =
- dc.getHomeStack().getTopChild().getTopFullscreenAppToken();
+ // Adjust the wallpaper visibility for the showing target activity
+ final AppWindowToken recentsComponentAppToken = dc.getStack(WINDOWING_MODE_UNDEFINED,
+ targetActivityType).getTopChild().getTopFullscreenAppToken();
if (recentsComponentAppToken != null) {
if (DEBUG) Log.d(TAG, "setHomeApp(" + recentsComponentAppToken.getName() + ")");
- mHomeAppToken = recentsComponentAppToken;
+ mTargetAppToken = recentsComponentAppToken;
if (recentsComponentAppToken.windowsCanBeWallpaperTarget()) {
dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
dc.setLayoutNeeded();
@@ -288,8 +293,10 @@
mService.mWindowPlacerLocked.performSurfacePlacement();
}
- private void addAnimation(Task task, boolean isRecentTaskInvisible) {
+ @VisibleForTesting
+ AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible) {
if (DEBUG) Log.d(TAG, "addAnimation(" + task.getName() + ")");
+ // TODO: Refactor this to use the task's animator
final SurfaceAnimator anim = new SurfaceAnimator(task, null /* animationFinishedCallback */,
mService);
final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task,
@@ -297,6 +304,15 @@
anim.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
task.commitPendingTransaction();
mPendingAnimations.add(taskAdapter);
+ return taskAdapter;
+ }
+
+ @VisibleForTesting
+ void removeAnimation(TaskAnimationAdapter taskAdapter) {
+ if (DEBUG) Log.d(TAG, "removeAnimation(" + taskAdapter.mTask.getName() + ")");
+ taskAdapter.mTask.setCanAffectSystemUiFlags(true);
+ taskAdapter.mCapturedFinishCallback.onAnimationFinished(taskAdapter);
+ mPendingAnimations.remove(taskAdapter);
}
void startAnimation() {
@@ -309,22 +325,33 @@
try {
final ArrayList<RemoteAnimationTarget> appAnimations = new ArrayList<>();
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
- final RemoteAnimationTarget target =
- mPendingAnimations.get(i).createRemoteAnimationApp();
+ final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
+ final RemoteAnimationTarget target = taskAdapter.createRemoteAnimationApp();
if (target != null) {
appAnimations.add(target);
+ } else {
+ removeAnimation(taskAdapter);
}
}
+
+ // Skip the animation if there is nothing to animate
+ if (appAnimations.isEmpty()) {
+ cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
+ return;
+ }
+
final RemoteAnimationTarget[] appTargets = appAnimations.toArray(
new RemoteAnimationTarget[appAnimations.size()]);
mPendingStart = false;
- final Rect minimizedHomeBounds =
- mHomeAppToken != null && mHomeAppToken.inSplitScreenSecondaryWindowingMode()
- ? mMinimizedHomeBounds : null;
- final Rect contentInsets =
- mHomeAppToken != null && mHomeAppToken.findMainWindow() != null
- ? mHomeAppToken.findMainWindow().mContentInsets : null;
+ final Rect minimizedHomeBounds = mTargetAppToken != null
+ && mTargetAppToken.inSplitScreenSecondaryWindowingMode()
+ ? mMinimizedHomeBounds
+ : null;
+ final Rect contentInsets = mTargetAppToken != null
+ && mTargetAppToken.findMainWindow() != null
+ ? mTargetAppToken.findMainWindow().mContentInsets
+ : null;
mRunner.onAnimationStart_New(mController, appTargets, contentInsets,
minimizedHomeBounds);
} catch (RemoteException e) {
@@ -361,17 +388,14 @@
if (DEBUG) Log.d(TAG, "cleanupAnimation(): mPendingAnimations="
+ mPendingAnimations.size());
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
- final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
- adapter.mTask.setCanAffectSystemUiFlags(true);
- if (reorderMode == REORDER_MOVE_HOME_TO_TOP
- || reorderMode == REORDER_KEEP_HOME_IN_PLACE) {
- adapter.mTask.dontAnimateDimExit();
+ final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
+ if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
+ taskAdapter.mTask.dontAnimateDimExit();
}
- adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
+ removeAnimation(taskAdapter);
}
- mPendingAnimations.clear();
- mRunner.asBinder().unlinkToDeath(this, 0);
+ unlinkToDeathOfRunner();
// Clear associated input consumers
mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
mService.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
@@ -381,14 +405,28 @@
mService.mH.postDelayed(mFailsafeRunnable, FAILSAFE_DELAY);
}
+ private void linkToDeathOfRunner() throws RemoteException {
+ if (!mLinkedToDeathOfRunner) {
+ mRunner.asBinder().linkToDeath(this, 0);
+ mLinkedToDeathOfRunner = true;
+ }
+ }
+
+ private void unlinkToDeathOfRunner() {
+ if (mLinkedToDeathOfRunner) {
+ mRunner.asBinder().unlinkToDeath(this, 0);
+ mLinkedToDeathOfRunner = false;
+ }
+ }
+
@Override
public void binderDied() {
- cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
+ cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
}
void checkAnimationReady(WallpaperController wallpaperController) {
if (mPendingStart) {
- final boolean wallpaperReady = !isHomeAppOverWallpaper()
+ final boolean wallpaperReady = !isTargetOverWallpaper()
|| (wallpaperController.getWallpaperTarget() != null
&& wallpaperController.wallpaperTransitionReady());
if (wallpaperReady) {
@@ -402,8 +440,8 @@
}
boolean isWallpaperVisible(WindowState w) {
- return w != null && w.mAppToken != null && mHomeAppToken == w.mAppToken
- && isHomeAppOverWallpaper();
+ return w != null && w.mAppToken != null && mTargetAppToken == w.mAppToken
+ && isTargetOverWallpaper();
}
boolean hasInputConsumerForApp(AppWindowToken appToken) {
@@ -412,12 +450,12 @@
boolean updateInputConsumerForApp(InputConsumerImpl recentsAnimationInputConsumer,
boolean hasFocus) {
- // Update the input consumer touchable region to match the home app main window
- final WindowState homeAppMainWindow = mHomeAppToken != null
- ? mHomeAppToken.findMainWindow()
+ // Update the input consumer touchable region to match the target app main window
+ final WindowState targetAppMainWindow = mTargetAppToken != null
+ ? mTargetAppToken.findMainWindow()
: null;
- if (homeAppMainWindow != null) {
- homeAppMainWindow.getBounds(mTmpRect);
+ if (targetAppMainWindow != null) {
+ targetAppMainWindow.getBounds(mTmpRect);
recentsAnimationInputConsumer.mWindowHandle.hasFocus = hasFocus;
recentsAnimationInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
return true;
@@ -425,11 +463,11 @@
return false;
}
- private boolean isHomeAppOverWallpaper() {
- if (mHomeAppToken == null) {
+ private boolean isTargetOverWallpaper() {
+ if (mTargetAppToken == null) {
return false;
}
- return mHomeAppToken.windowsCanBeWallpaperTarget();
+ return mTargetAppToken.windowsCanBeWallpaperTarget();
}
boolean isAnimatingTask(Task task) {
@@ -454,7 +492,8 @@
return false;
}
- private class TaskAnimationAdapter implements AnimationAdapter {
+ @VisibleForTesting
+ class TaskAnimationAdapter implements AnimationAdapter {
private final Task mTask;
private SurfaceControl mCapturedLeash;
@@ -511,7 +550,7 @@
@Override
public void onAnimationCancelled(SurfaceControl animationLeash) {
- cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
+ cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
}
@Override
@@ -549,6 +588,6 @@
final String innerPrefix = prefix + " ";
pw.print(prefix); pw.println(RecentsAnimationController.class.getSimpleName() + ":");
pw.print(innerPrefix); pw.println("mPendingStart=" + mPendingStart);
- pw.print(innerPrefix); pw.println("mHomeAppToken=" + mHomeAppToken);
+ pw.print(innerPrefix); pw.println("mTargetAppToken=" + mTargetAppToken);
}
}
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 3be7b235..16f4cd0 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -61,6 +61,7 @@
private FinishedCallback mFinishedCallback;
private boolean mCanceled;
+ private boolean mLinkedToDeathOfRunner;
RemoteAnimationController(WindowManagerService service,
RemoteAnimationAdapter remoteAnimationAdapter, Handler handler) {
@@ -106,7 +107,7 @@
}
mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
try {
- mRemoteAnimationAdapter.getRunner().asBinder().linkToDeath(this, 0);
+ linkToDeathOfRunner();
mRemoteAnimationAdapter.getRunner().onAnimationStart(animations, mFinishedCallback);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to start remote animation", e);
@@ -164,8 +165,8 @@
private void onAnimationFinished() {
mHandler.removeCallbacks(mTimeoutRunnable);
- mRemoteAnimationAdapter.getRunner().asBinder().unlinkToDeath(this, 0);
synchronized (mService.mWindowMap) {
+ unlinkToDeathOfRunner();
releaseFinishedCallback();
mService.openSurfaceTransaction();
try {
@@ -204,6 +205,20 @@
mService.sendSetRunningRemoteAnimation(pid, running);
}
+ private void linkToDeathOfRunner() throws RemoteException {
+ if (!mLinkedToDeathOfRunner) {
+ mRemoteAnimationAdapter.getRunner().asBinder().linkToDeath(this, 0);
+ mLinkedToDeathOfRunner = true;
+ }
+ }
+
+ private void unlinkToDeathOfRunner() {
+ if (mLinkedToDeathOfRunner) {
+ mRemoteAnimationAdapter.getRunner().asBinder().unlinkToDeath(this, 0);
+ mLinkedToDeathOfRunner = false;
+ }
+ }
+
@Override
public void binderDied() {
cancelAnimation();
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 98fcb0b..7211533 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -220,6 +220,9 @@
}
private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
+ if (a.mAnimSpec.needsEarlyWakeup()) {
+ t.setEarlyWakeup();
+ }
a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index a9e53a1..597b39e 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -173,6 +173,8 @@
windowFlags = topFullscreenWindow.getAttrs().flags;
windowPrivateFlags = topFullscreenWindow.getAttrs().privateFlags;
+ layoutParams.packageName = mainWindow.getAttrs().packageName;
+ layoutParams.windowAnimations = mainWindow.getAttrs().windowAnimations;
layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
layoutParams.type = TYPE_APPLICATION_STARTING;
layoutParams.format = snapshot.getSnapshot().getFormat();
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 6de1579..7eaca5d 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -26,7 +26,7 @@
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
-import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION;
+import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
@@ -620,7 +620,7 @@
// If there was a recents animation in progress, cancel that animation
if (mService.getRecentsAnimationController() != null) {
mService.getRecentsAnimationController().cancelAnimation(
- REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
+ REORDER_MOVE_TO_ORIGINAL_POSITION);
}
return true;
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 7b7cb30..548e23a 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -47,21 +47,24 @@
private final Point mPosition = new Point();
private final ThreadLocal<TmpValues> mThreadLocalTmps = ThreadLocal.withInitial(TmpValues::new);
private final boolean mCanSkipFirstFrame;
+ private final boolean mIsAppAnimation;
private final Rect mStackBounds = new Rect();
private int mStackClipMode;
private final Rect mTmpRect = new Rect();
public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame) {
- this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE);
+ this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE,
+ false /* isAppAnimation */);
}
public WindowAnimationSpec(Animation animation, Point position, Rect stackBounds,
- boolean canSkipFirstFrame, int stackClipMode) {
+ boolean canSkipFirstFrame, int stackClipMode, boolean isAppAnimation) {
mAnimation = animation;
if (position != null) {
mPosition.set(position.x, position.y);
}
mCanSkipFirstFrame = canSkipFirstFrame;
+ mIsAppAnimation = isAppAnimation;
mStackClipMode = stackClipMode;
if (stackBounds != null) {
mStackBounds.set(stackBounds);
@@ -135,6 +138,11 @@
}
@Override
+ public boolean needsEarlyWakeup() {
+ return mIsAppAnimation;
+ }
+
+ @Override
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.println(mAnimation);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0c9504f..2b5620c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1243,6 +1243,10 @@
Slog.w(TAG_WM, "Attempted to add window with exiting application token "
+ token + ". Aborting.");
return WindowManagerGlobal.ADD_APP_EXITING;
+ } else if (type == TYPE_APPLICATION_STARTING && atoken.startingWindow != null) {
+ Slog.w(TAG_WM, "Attempted to add starting window to token with already existing"
+ + " starting window");
+ return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
} else if (rootType == TYPE_INPUT_METHOD) {
if (token.windowType != TYPE_INPUT_METHOD) {
@@ -1930,7 +1934,15 @@
winAnimator.setOpaqueLocked(false);
}
- boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
+ final int oldVisibility = win.mViewVisibility;
+
+ // If the window is becoming visible, visibleOrAdding may change which may in turn
+ // change the IME target.
+ final boolean becameVisible =
+ (oldVisibility == View.INVISIBLE || oldVisibility == View.GONE)
+ && viewVisibility == View.VISIBLE;
+ boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0
+ || becameVisible;
final boolean isDefaultDisplay = win.isDefaultDisplay();
boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
|| ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
@@ -1946,7 +1958,6 @@
win.mRelayoutCalled = true;
win.mInRelayout = true;
- final int oldVisibility = win.mViewVisibility;
win.mViewVisibility = viewVisibility;
if (DEBUG_SCREEN_ON) {
RuntimeException stack = new RuntimeException();
@@ -2689,7 +2700,7 @@
}
}
- public void initializeRecentsAnimation(
+ public void initializeRecentsAnimation(int targetActivityType,
IRecentsAnimationRunner recentsAnimationRunner,
RecentsAnimationController.RecentsAnimationCallbacks callbacks, int displayId,
SparseBooleanArray recentTaskIds) {
@@ -2697,7 +2708,7 @@
mRecentsAnimationController = new RecentsAnimationController(this,
recentsAnimationRunner, callbacks, displayId);
mAppTransition.updateBooster();
- mRecentsAnimationController.initialize(recentTaskIds);
+ mRecentsAnimationController.initialize(targetActivityType, recentTaskIds);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 84df128..c5269e1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2001,6 +2001,11 @@
// Try starting an animation.
if (mWinAnimator.applyAnimationLocked(transit, false)) {
mAnimatingExit = true;
+
+ // mAnimatingExit affects canAffectSystemUiFlags(). Run layout such that
+ // any change from that is performed immediately.
+ setDisplayLayoutNeeded();
+ mService.requestTraversal();
}
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9bc5fca..82d2f3c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8481,6 +8481,7 @@
if (!mHasFeature) {
return null;
}
+ enforceManageUsers();
synchronized (getLockObject()) {
List<String> result = null;
// If we have multiple profiles we return the intersection of the
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6f50ee2..5519d22 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -725,7 +725,6 @@
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
- NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
SerialService serial = null;
@@ -1090,12 +1089,7 @@
}
traceBeginAndSlog("StartNetworkScoreService");
- try {
- networkScore = new NetworkScoreService(context);
- ServiceManager.addService(Context.NETWORK_SCORE_SERVICE, networkScore);
- } catch (Throwable e) {
- reportWtf("starting Network Score Service", e);
- }
+ mSystemServiceManager.startService(NetworkScoreService.Lifecycle.class);
traceEnd();
traceBeginAndSlog("StartNetworkStatsService");
@@ -1728,7 +1722,6 @@
final NetworkStatsService networkStatsF = networkStats;
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
final ConnectivityService connectivityF = connectivity;
- final NetworkScoreService networkScoreF = networkScore;
final LocationManagerService locationF = location;
final CountryDetectorService countryDetectorF = countryDetector;
final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
@@ -1789,13 +1782,6 @@
reportWtf("starting System UI", e);
}
traceEnd();
- traceBeginAndSlog("MakeNetworkScoreReady");
- try {
- if (networkScoreF != null) networkScoreF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Network Score Service ready", e);
- }
- traceEnd();
traceBeginAndSlog("MakeNetworkManagementServiceReady");
try {
if (networkManagementF != null) networkManagementF.systemReady();
@@ -1917,13 +1903,6 @@
}
traceEnd();
- traceBeginAndSlog("MakeNetworkScoreServiceReady");
- try {
- if (networkScoreF != null) networkScoreF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying NetworkScoreService running", e);
- }
- traceEnd();
traceBeginAndSlog("IncidentDaemonReady");
try {
// TODO: Switch from checkService to getService once it's always
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index a184b22..87249df 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -40,6 +40,7 @@
import android.net.util.NetdService;
import android.net.util.NetworkConstants;
import android.net.util.SharedLog;
+import android.os.ConditionVariable;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
@@ -150,6 +151,28 @@
public void setNeighborDiscoveryOffload(boolean enable) {}
}
+ public static class WaitForProvisioningCallback extends Callback {
+ private final ConditionVariable mCV = new ConditionVariable();
+ private LinkProperties mCallbackLinkProperties;
+
+ public LinkProperties waitForProvisioning() {
+ mCV.block();
+ return mCallbackLinkProperties;
+ }
+
+ @Override
+ public void onProvisioningSuccess(LinkProperties newLp) {
+ mCallbackLinkProperties = newLp;
+ mCV.open();
+ }
+
+ @Override
+ public void onProvisioningFailure(LinkProperties newLp) {
+ mCallbackLinkProperties = null;
+ mCV.open();
+ }
+ }
+
// Use a wrapper class to log in order to ensure complete and detailed
// logging. This method is lighter weight than annotations/reflection
// and has the following benefits:
@@ -281,6 +304,11 @@
return this;
}
+ public Builder withoutMultinetworkPolicyTracker() {
+ mConfig.mUsingMultinetworkPolicyTracker = false;
+ return this;
+ }
+
public Builder withoutIpReachabilityMonitor() {
mConfig.mUsingIpReachabilityMonitor = false;
return this;
@@ -343,6 +371,7 @@
/* package */ boolean mEnableIPv4 = true;
/* package */ boolean mEnableIPv6 = true;
+ /* package */ boolean mUsingMultinetworkPolicyTracker = true;
/* package */ boolean mUsingIpReachabilityMonitor = true;
/* package */ int mRequestedPreDhcpActionMs;
/* package */ InitialConfiguration mInitialConfig;
@@ -374,6 +403,7 @@
return new StringJoiner(", ", getClass().getSimpleName() + "{", "}")
.add("mEnableIPv4: " + mEnableIPv4)
.add("mEnableIPv6: " + mEnableIPv6)
+ .add("mUsingMultinetworkPolicyTracker: " + mUsingMultinetworkPolicyTracker)
.add("mUsingIpReachabilityMonitor: " + mUsingIpReachabilityMonitor)
.add("mRequestedPreDhcpActionMs: " + mRequestedPreDhcpActionMs)
.add("mInitialConfig: " + mInitialConfig)
@@ -559,7 +589,6 @@
private final NetlinkTracker mNetlinkTracker;
private final WakeupMessage mProvisioningTimeoutAlarm;
private final WakeupMessage mDhcpActionTimeoutAlarm;
- private final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
private final SharedLog mLog;
private final LocalLog mConnectivityPacketLog;
private final MessageHandlingLogger mMsgStateLogger;
@@ -573,6 +602,7 @@
*/
private LinkProperties mLinkProperties;
private ProvisioningConfiguration mConfiguration;
+ private MultinetworkPolicyTracker mMultinetworkPolicyTracker;
private IpReachabilityMonitor mIpReachabilityMonitor;
private DhcpClient mDhcpClient;
private DhcpResults mDhcpResults;
@@ -685,9 +715,6 @@
mLinkProperties = new LinkProperties();
mLinkProperties.setInterfaceName(mInterfaceName);
- mMultinetworkPolicyTracker = new MultinetworkPolicyTracker(mContext, getHandler(),
- () -> { mLog.log("OBSERVED AvoidBadWifi changed"); });
-
mProvisioningTimeoutAlarm = new WakeupMessage(mContext, getHandler(),
mTag + ".EVENT_PROVISIONING_TIMEOUT", EVENT_PROVISIONING_TIMEOUT);
mDhcpActionTimeoutAlarm = new WakeupMessage(mContext, getHandler(),
@@ -719,8 +746,6 @@
} catch (RemoteException e) {
logError("Couldn't register NetlinkTracker: %s", e);
}
-
- mMultinetworkPolicyTracker.start();
}
private void stopStateMachineUpdaters() {
@@ -729,8 +754,6 @@
} catch (RemoteException e) {
logError("Couldn't unregister NetlinkTracker: %s", e);
}
-
- mMultinetworkPolicyTracker.shutdown();
}
@Override
@@ -1028,7 +1051,8 @@
// Note that we can still be disconnected by IpReachabilityMonitor
// if the IPv6 default gateway (but not the IPv6 DNS servers; see
// accompanying code in IpReachabilityMonitor) is unreachable.
- final boolean ignoreIPv6ProvisioningLoss = !mMultinetworkPolicyTracker.getAvoidBadWifi();
+ final boolean ignoreIPv6ProvisioningLoss = (mMultinetworkPolicyTracker != null)
+ && !mMultinetworkPolicyTracker.getAvoidBadWifi();
// Additionally:
//
@@ -1520,6 +1544,13 @@
return;
}
+ if (mConfiguration.mUsingMultinetworkPolicyTracker) {
+ mMultinetworkPolicyTracker = new MultinetworkPolicyTracker(
+ mContext, getHandler(),
+ () -> { mLog.log("OBSERVED AvoidBadWifi changed"); });
+ mMultinetworkPolicyTracker.start();
+ }
+
if (mConfiguration.mUsingIpReachabilityMonitor && !startIpReachabilityMonitor()) {
doImmediateProvisioningFailure(
IpManagerEvent.ERROR_STARTING_IPREACHABILITYMONITOR);
@@ -1537,6 +1568,11 @@
mIpReachabilityMonitor = null;
}
+ if (mMultinetworkPolicyTracker != null) {
+ mMultinetworkPolicyTracker.shutdown();
+ mMultinetworkPolicyTracker = null;
+ }
+
if (mDhcpClient != null) {
mDhcpClient.sendMessage(DhcpClient.CMD_STOP_DHCP);
mDhcpClient.doQuit();
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 508a43d..2eb36a2 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -114,35 +114,6 @@
public static class Callback extends IpClient.Callback {
}
- public static class WaitForProvisioningCallback extends Callback {
- private LinkProperties mCallbackLinkProperties;
-
- public LinkProperties waitForProvisioning() {
- synchronized (this) {
- try {
- wait();
- } catch (InterruptedException e) {}
- return mCallbackLinkProperties;
- }
- }
-
- @Override
- public void onProvisioningSuccess(LinkProperties newLp) {
- synchronized (this) {
- mCallbackLinkProperties = newLp;
- notify();
- }
- }
-
- @Override
- public void onProvisioningFailure(LinkProperties newLp) {
- synchronized (this) {
- mCallbackLinkProperties = null;
- notify();
- }
- }
- }
-
public IpManager(Context context, String ifName, Callback callback) {
super(context, ifName, callback);
}
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index 0ec16b5..8f989df 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -28,5 +28,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.servicestests" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java
index 46b364c..43701e9 100644
--- a/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java
@@ -25,6 +25,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Secure;
+import android.provider.Settings.System;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;
@@ -895,6 +896,52 @@
assertActivated(true /* activated */);
}
+ @Test
+ public void accessibility_colorInversion_transformActivated() {
+ setAccessibilityColorInversion(true);
+ setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+
+ startService();
+ assertAccessibilityTransformActivated(true /* activated */ );
+ assertUserColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+ assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED);
+ }
+
+ @Test
+ public void accessibility_colorCorrection_transformActivated() {
+ setAccessibilityColorCorrection(true);
+ setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+
+ startService();
+ assertAccessibilityTransformActivated(true /* activated */ );
+ assertUserColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+ assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED);
+ }
+
+ @Test
+ public void accessibility_all_transformActivated() {
+ setAccessibilityColorCorrection(true);
+ setAccessibilityColorInversion(true);
+ setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+
+ startService();
+ assertAccessibilityTransformActivated(true /* activated */ );
+ assertUserColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+ assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED);
+ }
+
+ @Test
+ public void accessibility_none_transformActivated() {
+ setAccessibilityColorCorrection(false);
+ setAccessibilityColorInversion(false);
+ setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+
+ startService();
+ assertAccessibilityTransformActivated(false /* activated */ );
+ assertUserColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+ assertActiveColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
+ }
+
/**
* Configures Night display to use a custom schedule.
*
@@ -935,6 +982,35 @@
}
/**
+ * Configures the Accessibility color correction setting state.
+ *
+ * @param state {@code true} if color inversion should be activated
+ */
+ private void setAccessibilityColorCorrection(boolean state) {
+ Secure.putIntForUser(mContext.getContentResolver(),
+ Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, state ? 1 : 0, mUserId);
+ }
+
+ /**
+ * Configures the Accessibility color inversion setting state.
+ *
+ * @param state {@code true} if color inversion should be activated
+ */
+ private void setAccessibilityColorInversion(boolean state) {
+ Secure.putIntForUser(mContext.getContentResolver(),
+ Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, state ? 1 : 0, mUserId);
+ }
+
+ /**
+ * Configures color mode via ColorDisplayController.
+ *
+ * @param mode the color mode to set
+ */
+ private void setColorMode(int mode) {
+ mColorDisplayController.setColorMode(mode);
+ }
+
+ /**
* Convenience method to start {@link #mColorDisplayService}.
*/
private void startService() {
@@ -962,6 +1038,41 @@
}
/**
+ * Convenience method for asserting that Accessibility color transform is detected.
+ *
+ * @param state {@code true} if any Accessibility transform should be activated
+ */
+ private void assertAccessibilityTransformActivated(boolean state) {
+ assertWithMessage("Unexpected Accessibility color transform state")
+ .that(mColorDisplayController.getAccessibilityTransformActivated())
+ .isEqualTo(state);
+ }
+
+ /**
+ * Convenience method for asserting that the active color mode matches expectation.
+ *
+ * @param mode the expected active color mode.
+ */
+ private void assertActiveColorMode(int mode) {
+ assertWithMessage("Unexpected color mode setting")
+ .that(mColorDisplayController.getColorMode())
+ .isEqualTo(mode);
+ }
+
+ /**
+ * Convenience method for asserting that the user chosen color mode matches expectation.
+ *
+ * @param mode the expected color mode setting.
+ */
+ private void assertUserColorMode(int mode) {
+ final int actualMode = System.getIntForUser(mContext.getContentResolver(),
+ System.DISPLAY_COLOR_MODE, -1, mUserId);
+ assertWithMessage("Unexpected color mode setting")
+ .that(actualMode)
+ .isEqualTo(mode);
+ }
+
+ /**
* Convenience for making a {@link LocalTime} instance with an offset relative to now.
*
* @param offsetMinutes the offset relative to now (in minutes)
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index d31d550..cecc94b 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -18,6 +18,7 @@
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
@@ -30,6 +31,7 @@
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
@@ -37,9 +39,13 @@
import static android.telephony.CarrierConfigManager.KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG;
import static android.telephony.CarrierConfigManager.KEY_DATA_WARNING_THRESHOLD_BYTES_LONG;
import static android.telephony.CarrierConfigManager.KEY_MONTHLY_DATA_CYCLE_DAY_INT;
+import static android.telephony.SubscriptionPlan.BYTES_UNLIMITED;
import static android.telephony.SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED;
import static android.text.format.Time.TIMEZONE_UTC;
+import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_JOBS;
+import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
+import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID;
@@ -62,6 +68,7 @@
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -118,7 +125,7 @@
import android.text.format.Time;
import android.util.DataUnit;
import android.util.Log;
-import android.util.Pair;
+import android.util.Range;
import android.util.RecurrenceRule;
import com.android.internal.telephony.PhoneConstants;
@@ -198,7 +205,8 @@
private static final int TEST_SUB_ID = 42;
private static final int TEST_NET_ID = 24;
- private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi(TEST_SSID);
+ private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_SSID);
+ private static NetworkTemplate sTemplateMobileAll = buildTemplateMobileAll(TEST_IMSI);
/**
* Path on assets where files used by {@link NetPolicyXml} are located.
@@ -218,6 +226,7 @@
private @Mock IActivityManager mActivityManager;
private @Mock INetworkManagementService mNetworkManager;
private @Mock IConnectivityManager mConnManager;
+ private @Mock ConnectivityManager mConnectivityManager;
private @Mock NotificationManager mNotifManager;
private @Mock PackageManager mPackageManager;
private @Mock IPackageManager mIpm;
@@ -225,6 +234,9 @@
private @Mock CarrierConfigManager mCarrierConfigManager;
private @Mock TelephonyManager mTelephonyManager;
+ private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
+ ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+
private ActivityManagerInternal mActivityManagerInternal;
private NetworkStatsManagerInternal mStatsService;
@@ -328,6 +340,8 @@
return mTelephonyManager;
case Context.NOTIFICATION_SERVICE:
return mNotifManager;
+ case Context.CONNECTIVITY_SERVICE:
+ return mConnectivityManager;
default:
return super.getSystemService(name);
}
@@ -391,6 +405,8 @@
.thenReturn(buildApplicationInfo(PKG_NAME_C));
when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
when(mNetworkManager.setDataSaverModeEnabled(anyBoolean())).thenReturn(true);
+ doNothing().when(mConnectivityManager)
+ .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture());
// Prepare NPMS.
mService.systemReady(mService.networkScoreAndNetworkManagementServiceReady());
@@ -818,11 +834,11 @@
private static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTime),
ZoneId.systemDefault());
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = policy.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = policy.cycleIterator();
while (it.hasNext()) {
- final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next();
- if (cycle.first.toInstant().toEpochMilli() < currentTime) {
- return cycle.first.toInstant().toEpochMilli();
+ final Range<ZonedDateTime> cycle = it.next();
+ if (cycle.getLower().toInstant().toEpochMilli() < currentTime) {
+ return cycle.getLower().toInstant().toEpochMilli();
}
}
throw new IllegalStateException(
@@ -832,7 +848,7 @@
private static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) {
RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTime),
ZoneId.systemDefault());
- return policy.cycleIterator().next().second.toInstant().toEpochMilli();
+ return policy.cycleIterator().next().getUpper().toInstant().toEpochMilli();
}
@Test
@@ -1012,10 +1028,8 @@
mService.updateNetworks();
// Define simple data plan
- final SubscriptionPlan plan = SubscriptionPlan.Builder
- .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
- .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_DISABLED)
- .build();
+ final SubscriptionPlan plan = buildMonthlyDataPlan(
+ ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), DataUnit.MEGABYTES.toBytes(1800));
mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
mServiceContext.getOpPackageName());
@@ -1119,10 +1133,8 @@
mService.updateNetworks();
// Define simple data plan which gives us effectively 60MB/day
- final SubscriptionPlan plan = SubscriptionPlan.Builder
- .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
- .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_DISABLED)
- .build();
+ final SubscriptionPlan plan = buildMonthlyDataPlan(
+ ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), DataUnit.MEGABYTES.toBytes(1800));
mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
mServiceContext.getOpPackageName());
@@ -1484,6 +1496,145 @@
true);
}
+ @Test
+ public void testOpportunisticQuota() throws Exception {
+ final Network net = new Network(TEST_NET_ID);
+ final NetworkPolicyManagerInternal internal = LocalServices
+ .getService(NetworkPolicyManagerInternal.class);
+
+ // Create a place to store fake usage
+ final NetworkStatsHistory history = new NetworkStatsHistory(TimeUnit.HOURS.toMillis(1));
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
+ when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
+ .thenAnswer(invocation -> {
+ final NetworkStatsHistory.Entry entry = history.getValues(
+ invocation.getArgument(1), invocation.getArgument(2), null);
+ return entry.rxBytes + entry.txBytes;
+ });
+ when(mStatsService.getNetworkUidBytes(any(), anyLong(), anyLong()))
+ .thenReturn(stats);
+
+ // Get active mobile network in place
+ expectMobileDefaults();
+ mService.updateNetworks();
+
+ // We're 20% through the month (6 days)
+ final long start = parseTime("2015-11-01T00:00Z");
+ final long end = parseTime("2015-11-07T00:00Z");
+ setCurrentTimeMillis(end);
+
+ // Get some data usage in place
+ history.clear();
+ history.recordData(start, end,
+ new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(360), 0L, 0L, 0L, 0));
+
+ // No data plan
+ {
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+ expectMobileDefaults();
+
+ mService.updateNetworks();
+
+ // No quotas
+ assertEquals(OPPORTUNISTIC_QUOTA_UNKNOWN,
+ internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
+ assertEquals(OPPORTUNISTIC_QUOTA_UNKNOWN,
+ internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
+ }
+
+ // Limited data plan
+ {
+ final SubscriptionPlan plan = buildMonthlyDataPlan(
+ ZonedDateTime.parse("2015-11-01T00:00:00.00Z"),
+ DataUnit.MEGABYTES.toBytes(1800));
+ mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
+ mServiceContext.getOpPackageName());
+
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+ expectMobileDefaults();
+
+ mService.updateNetworks();
+
+ // We have 1440MB and 24 days left, which is 60MB/day; assuming 10%
+ // for quota split equally between two types gives 3MB.
+ assertEquals(DataUnit.MEGABYTES.toBytes(3),
+ internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
+ assertEquals(DataUnit.MEGABYTES.toBytes(3),
+ internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
+ }
+
+ // Limited data plan, over quota
+ {
+ final SubscriptionPlan plan = buildMonthlyDataPlan(
+ ZonedDateTime.parse("2015-11-01T00:00:00.00Z"),
+ DataUnit.MEGABYTES.toBytes(100));
+ mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
+ mServiceContext.getOpPackageName());
+
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+ expectMobileDefaults();
+
+ mService.updateNetworks();
+
+ assertEquals(0L, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
+ assertEquals(0L, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
+ }
+
+ // Roaming
+ {
+ final SubscriptionPlan plan = buildMonthlyDataPlan(
+ ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), BYTES_UNLIMITED);
+ mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
+ mServiceContext.getOpPackageName());
+
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+ expectMobileDefaults();
+ expectNetworkState(true /* roaming */);
+
+ mService.updateNetworks();
+
+ assertEquals(0L, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
+ assertEquals(0L, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
+ }
+
+ // Unlimited data plan
+ {
+ final SubscriptionPlan plan = buildMonthlyDataPlan(
+ ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), BYTES_UNLIMITED);
+ mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
+ mServiceContext.getOpPackageName());
+
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+ expectMobileDefaults();
+
+ mService.updateNetworks();
+
+ // 20MB/day, split equally between two types gives 10MB.
+ assertEquals(DataUnit.MEBIBYTES.toBytes(10),
+ internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
+ assertEquals(DataUnit.MEBIBYTES.toBytes(10),
+ internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
+
+ // Capabilities change to roaming
+ final ConnectivityManager.NetworkCallback callback = mNetworkCallbackCaptor.getValue();
+ assertNotNull(callback);
+ expectNetworkState(true /* roaming */);
+ callback.onCapabilitiesChanged(
+ new Network(TEST_NET_ID),
+ buildNetworkCapabilities(TEST_SUB_ID, true /* roaming */));
+
+ assertEquals(0, internal.getSubscriptionOpportunisticQuota(
+ new Network(TEST_NET_ID), NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH));
+ }
+ }
+
+ private SubscriptionPlan buildMonthlyDataPlan(ZonedDateTime start, long limitBytes) {
+ return SubscriptionPlan.Builder
+ .createRecurringMonthly(start)
+ .setDataLimit(limitBytes, LIMIT_BEHAVIOR_DISABLED)
+ .build();
+ }
+
private ApplicationInfo buildApplicationInfo(String label) {
final ApplicationInfo ai = new ApplicationInfo();
ai.nonLocalizedLabel = label;
@@ -1503,9 +1654,12 @@
return lp;
}
- private NetworkCapabilities buildNetworkCapabilities(int subId) {
+ private NetworkCapabilities buildNetworkCapabilities(int subId, boolean roaming) {
final NetworkCapabilities nc = new NetworkCapabilities();
nc.addTransportType(TRANSPORT_CELLULAR);
+ if (!roaming) {
+ nc.addCapability(NET_CAPABILITY_NOT_ROAMING);
+ }
nc.setNetworkSpecifier(new StringNetworkSpecifier(String.valueOf(subId)));
return nc;
}
@@ -1559,16 +1713,20 @@
hasIt ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
}
+ private void expectNetworkState(boolean roaming) throws Exception {
+ when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[] {
+ new NetworkState(buildNetworkInfo(),
+ buildLinkProperties(TEST_IFACE),
+ buildNetworkCapabilities(TEST_SUB_ID, roaming),
+ new Network(TEST_NET_ID), TEST_IMSI, null)
+ });
+ }
+
private void expectMobileDefaults() throws Exception {
when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(
new int[] { TEST_SUB_ID });
when(mTelephonyManager.getSubscriberId(TEST_SUB_ID)).thenReturn(TEST_IMSI);
- when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[] {
- new NetworkState(buildNetworkInfo(),
- buildLinkProperties(TEST_IFACE),
- buildNetworkCapabilities(TEST_SUB_ID),
- new Network(TEST_NET_ID), TEST_IMSI, null)
- });
+ expectNetworkState(false /* roaming */);
}
private void verifyAdvisePersistThreshold() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index b9ddf5c..c78fcd3 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -24,8 +24,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
@@ -43,9 +41,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.app.servertransaction.DestroyActivityItem;
import android.content.pm.ActivityInfo;
-import android.os.Debug;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
@@ -67,6 +63,7 @@
public class ActivityStackTests extends ActivityTestsBase {
private ActivityManagerService mService;
private ActivityStackSupervisor mSupervisor;
+ private ActivityDisplay mDefaultDisplay;
private ActivityStack mStack;
private TaskRecord mTask;
@@ -77,8 +74,9 @@
mService = createActivityManagerService();
mSupervisor = mService.mStackSupervisor;
- mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ mDefaultDisplay = mService.mStackSupervisor.getDefaultDisplay();
+ mStack = mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
}
@@ -112,9 +110,8 @@
public void testPrimarySplitScreenToFullscreenWhenMovedToBack() throws Exception {
// Create primary splitscreen stack. This will create secondary stacks and places the
// existing fullscreen stack on the bottom.
- final ActivityStack primarySplitScreen = mService.mStackSupervisor.getDefaultDisplay()
- .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
- true /* onTop */);
+ final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Assert windowing mode.
assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
@@ -124,8 +121,7 @@
null /* task */);
// Assert that stack is at the bottom.
- assertEquals(mService.mStackSupervisor.getDefaultDisplay().getIndexOf(primarySplitScreen),
- 0);
+ assertEquals(mDefaultDisplay.getIndexOf(primarySplitScreen), 0);
// Ensure no longer in splitscreen.
assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_FULLSCREEN);
@@ -165,16 +161,15 @@
@Test
public void testShouldBeVisible_Fullscreen() throws Exception {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(display,
+ final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
assertTrue(homeStack.shouldBeVisible(null /* starting */));
assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
- final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Home stack shouldn't be visible behind an opaque fullscreen stack, but pinned stack
// should be visible since it is always on-top.
@@ -191,14 +186,13 @@
@Test
public void testShouldBeVisible_SplitScreen() throws Exception {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
// Home stack should always be fullscreen for this test.
homeStack.setSupportsSplitScreen(false);
- final TestActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Home stack shouldn't be visible if both halves of split-screen are opaque.
@@ -214,7 +208,7 @@
assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
- final TestActivityStack splitScreenSecondary2 = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack splitScreenSecondary2 = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// First split-screen secondary shouldn't be visible behind another opaque split-split
// secondary.
@@ -228,7 +222,7 @@
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
- final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
// Split-screen stacks shouldn't be visible behind an opaque fullscreen stack.
@@ -258,11 +252,11 @@
@Test
public void testShouldBeVisible_Finishing() throws Exception {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack translucentStack = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final TestActivityStack translucentStack = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
translucentStack.setIsTranslucent(true);
assertTrue(homeStack.shouldBeVisible(null /* starting */));
@@ -286,76 +280,74 @@
@Test
public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindFullscreen() {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- display.removeChild(mStack);
+ mDefaultDisplay.removeChild(mStack);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
homeStack.setIsTranslucent(false);
fullscreenStack.setIsTranslucent(false);
// Ensure that we don't move the home stack if it is already behind the top fullscreen stack
- int homeStackIndex = display.getIndexOf(homeStack);
- assertTrue(display.getStackAboveHome() == fullscreenStack);
- display.moveHomeStackBehindBottomMostVisibleStack();
- assertTrue(display.getIndexOf(homeStack) == homeStackIndex);
+ int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack);
+ mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ assertTrue(mDefaultDisplay.getIndexOf(homeStack) == homeStackIndex);
}
@Test
public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindTranslucent() {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- display.removeChild(mStack);
+ mDefaultDisplay.removeChild(mStack);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
homeStack.setIsTranslucent(false);
fullscreenStack.setIsTranslucent(true);
// Ensure that we don't move the home stack if it is already behind the top fullscreen stack
- int homeStackIndex = display.getIndexOf(homeStack);
- assertTrue(display.getStackAboveHome() == fullscreenStack);
- display.moveHomeStackBehindBottomMostVisibleStack();
- assertTrue(display.getIndexOf(homeStack) == homeStackIndex);
+ int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack);
+ mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ assertTrue(mDefaultDisplay.getIndexOf(homeStack) == homeStackIndex);
}
@Test
public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeOnTop() {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- display.removeChild(mStack);
+ mDefaultDisplay.removeChild(mStack);
- final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
homeStack.setIsTranslucent(false);
fullscreenStack.setIsTranslucent(false);
// Ensure we don't move the home stack if it is already on top
- int homeStackIndex = display.getIndexOf(homeStack);
- assertTrue(display.getStackAboveHome() == null);
- display.moveHomeStackBehindBottomMostVisibleStack();
- assertTrue(display.getIndexOf(homeStack) == homeStackIndex);
+ int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == null);
+ mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ assertTrue(mDefaultDisplay.getIndexOf(homeStack) == homeStackIndex);
}
@Test
public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreen() {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- display.removeChild(mStack);
+ mDefaultDisplay.removeChild(mStack);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack pinnedStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
homeStack.setIsTranslucent(false);
@@ -364,22 +356,23 @@
// Ensure that we move the home stack behind the bottom most fullscreen stack, ignoring the
// pinned stack
- assertTrue(display.getStackAboveHome() == fullscreenStack1);
- display.moveHomeStackBehindBottomMostVisibleStack();
- assertTrue(display.getStackAboveHome() == fullscreenStack2);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack1);
+ mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack2);
}
@Test
public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreenAndTranslucent() {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- display.removeChild(mStack);
+ mDefaultDisplay.removeChild(mStack);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
homeStack.setIsTranslucent(false);
fullscreenStack1.setIsTranslucent(false);
@@ -387,21 +380,22 @@
// Ensure that we move the home stack behind the bottom most non-translucent fullscreen
// stack
- assertTrue(display.getStackAboveHome() == fullscreenStack1);
- display.moveHomeStackBehindBottomMostVisibleStack();
- assertTrue(display.getStackAboveHome() == fullscreenStack1);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack1);
+ mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack1);
}
@Test
public void testMoveHomeStackBehindStack_BehindHomeStack() {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- display.removeChild(mStack);
+ mDefaultDisplay.removeChild(mStack);
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
homeStack.setIsTranslucent(false);
@@ -409,45 +403,49 @@
fullscreenStack2.setIsTranslucent(false);
// Ensure we don't move the home stack behind itself
- int homeStackIndex = display.getIndexOf(homeStack);
- display.moveHomeStackBehindStack(homeStack);
- assertTrue(display.getIndexOf(homeStack) == homeStackIndex);
+ int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
+ mDefaultDisplay.moveStackBehindStack(homeStack, homeStack);
+ assertTrue(mDefaultDisplay.getIndexOf(homeStack) == homeStackIndex);
}
@Test
public void testMoveHomeStackBehindStack() {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- display.removeChild(mStack);
+ mDefaultDisplay.removeChild(mStack);
- final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack homeStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- display.moveHomeStackBehindStack(fullscreenStack1);
- assertTrue(display.getStackAboveHome() == fullscreenStack1);
- display.moveHomeStackBehindStack(fullscreenStack2);
- assertTrue(display.getStackAboveHome() == fullscreenStack2);
- display.moveHomeStackBehindStack(fullscreenStack4);
- assertTrue(display.getStackAboveHome() == fullscreenStack4);
- display.moveHomeStackBehindStack(fullscreenStack2);
- assertTrue(display.getStackAboveHome() == fullscreenStack2);
+ mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack1);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack1);
+ mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack2);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack2);
+ mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack4);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack4);
+ mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack2);
+ assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack2);
}
@Test
public void testSplitScreenMoveToFront() throws Exception {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
- final TestActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(display,
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(display,
+ final TestActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(
+ mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
splitScreenPrimary.setIsTranslucent(false);
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index edc6509..592f7b1 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -39,6 +39,7 @@
import static java.lang.Integer.MAX_VALUE;
+import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManager.RunningTaskInfo;
@@ -327,6 +328,33 @@
}
@Test
+ public void testAddTaskCompatibleActivityTypeDifferentUser_expectNoRemove() throws Exception {
+ Configuration config1 = new Configuration();
+ config1.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
+ TaskRecord task1 = createTaskBuilder(".Task1")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK)
+ .setStack(mStack)
+ .setUserId(TEST_USER_0_ID)
+ .build();
+ task1.onConfigurationChanged(config1);
+ assertTrue(task1.getActivityType() == ACTIVITY_TYPE_UNDEFINED);
+ mRecentTasks.add(task1);
+ mCallbacksRecorder.clear();
+
+ TaskRecord task2 = createTaskBuilder(".Task1")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK)
+ .setStack(mStack)
+ .setUserId(TEST_USER_1_ID)
+ .build();
+ assertTrue(task2.getActivityType() == ACTIVITY_TYPE_STANDARD);
+ mRecentTasks.add(task2);
+ assertTrue(mCallbacksRecorder.added.size() == 1);
+ assertTrue(mCallbacksRecorder.added.contains(task2));
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.isEmpty());
+ }
+
+ @Test
public void testUsersTasks() throws Exception {
mRecentTasks.setOnlyTestVisibleRange();
@@ -567,6 +595,23 @@
}
@Test
+ public void testRemovePackageByName() throws Exception {
+ // Add a number of tasks with the same package name
+ mRecentTasks.add(createTaskBuilder("com.android.pkg1", ".Task1").build());
+ mRecentTasks.add(createTaskBuilder("com.android.pkg2", ".Task2").build());
+ mRecentTasks.add(createTaskBuilder("com.android.pkg3", ".Task3").build());
+ mRecentTasks.add(createTaskBuilder("com.android.pkg1", ".Task4").build());
+ mRecentTasks.removeTasksByPackageName("com.android.pkg1", TEST_USER_0_ID);
+
+ final ArrayList<TaskRecord> tasks = mRecentTasks.getRawTasks();
+ for (int i = 0; i < tasks.size(); i++) {
+ if (tasks.get(i).intent.getComponent().getPackageName().equals("com.android.pkg1")) {
+ fail("Expected com.android.pkg1 tasks to be removed");
+ }
+ }
+ }
+
+ @Test
public void testNotRecentsComponent_denyApiAccess() throws Exception {
doReturn(PackageManager.PERMISSION_DENIED).when(mService).checkPermission(anyString(),
anyInt(), anyInt());
@@ -667,8 +712,12 @@
}
private TaskBuilder createTaskBuilder(String className) {
+ return createTaskBuilder(mContext.getPackageName(), className);
+ }
+
+ private TaskBuilder createTaskBuilder(String packageName, String className) {
return new TaskBuilder(mService.mStackSupervisor)
- .setComponent(new ComponentName(mContext.getPackageName(), className))
+ .setComponent(new ComponentName(packageName, className))
.setStack(mStack)
.setTaskId(LAST_TASK_ID++)
.setUserId(TEST_USER_0_ID);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
index f740654..e4e9701 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
@@ -24,7 +24,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.app.admin.FreezeInterval;
+import android.app.admin.FreezePeriod;
import android.app.admin.SystemUpdatePolicy;
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
@@ -42,15 +42,15 @@
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
-import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
-import java.time.LocalTime;
+import java.time.MonthDay;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
+
/**
* Unit tests for {@link android.app.admin.SystemUpdatePolicy}.
* Throughout this test, we use "MM-DD" format to denote dates without year.
@@ -224,36 +224,36 @@
@Test
public void testDistanceWithoutLeapYear() {
- assertEquals(364, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(364, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2016, 12, 31), LocalDate.of(2016, 1, 1)));
- assertEquals(365, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(365, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2017, 1, 1), LocalDate.of(2016, 1, 1)));
- assertEquals(365, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(365, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2017, 2, 28), LocalDate.of(2016, 2, 29)));
- assertEquals(-365, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(-365, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2016, 1, 1), LocalDate.of(2017, 1, 1)));
- assertEquals(1, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(1, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 29)));
- assertEquals(1, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(1, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 28)));
- assertEquals(0, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(0, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2016, 2, 29), LocalDate.of(2016, 2, 28)));
- assertEquals(0, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(0, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2016, 2, 28), LocalDate.of(2016, 2, 28)));
- assertEquals(59, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(59, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2016, 3, 1), LocalDate.of(2016, 1, 1)));
- assertEquals(59, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(59, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2017, 3, 1), LocalDate.of(2017, 1, 1)));
- assertEquals(365 * 40, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(365 * 40, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2040, 1, 1), LocalDate.of(2000, 1, 1)));
- assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2019, 3, 1), LocalDate.of(2017, 3, 1)));
- assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2018, 3, 1), LocalDate.of(2016, 3, 1)));
- assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
+ assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
LocalDate.of(2017, 3, 1), LocalDate.of(2015, 3, 1)));
}
@@ -386,10 +386,10 @@
// Two freeze periods
p = SystemUpdatePolicy.createAutomaticInstallPolicy();
- setFreezePeriods(p, "05-01", "06-01", "11-01", "01-29");
- // automatic policy for July, August, September and October
+ setFreezePeriods(p, "05-01", "06-01", "10-15", "01-10");
+ // automatic policy for July, August, September and October until 15th
assertInstallationOption(
- SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(92),
+ SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(31 + 30 + 14),
millis_2018_08_01, p);
}
@@ -435,18 +435,18 @@
String... dates) throws Exception {
SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy();
setFreezePeriods(p, dates);
- p.validateAgainstPreviousFreezePeriod(parseDate(prevStart), parseDate(prevEnd),
- parseDate(now));
+ p.validateAgainstPreviousFreezePeriod(parseLocalDate(prevStart),
+ parseLocalDate(prevEnd), parseLocalDate(now));
}
// "MM-DD" format for date
private void setFreezePeriods(SystemUpdatePolicy policy, String... dates) throws Exception {
- List<Pair<Integer, Integer>> periods = new ArrayList<>();
- LocalDate lastDate = null;
+ List<FreezePeriod> periods = new ArrayList<>();
+ MonthDay lastDate = null;
for (String date : dates) {
- LocalDate currentDate = parseDate(date);
+ MonthDay currentDate = parseMonthDay(date);
if (lastDate != null) {
- periods.add(new Pair<>(lastDate.getDayOfYear(), currentDate.getDayOfYear()));
+ periods.add(new FreezePeriod(lastDate, currentDate));
lastDate = null;
} else {
lastDate = currentDate;
@@ -457,7 +457,7 @@
}
private void testSerialization(SystemUpdatePolicy policy,
- List<Pair<Integer, Integer>> expectedPeriods) throws Exception {
+ List<FreezePeriod> expectedPeriods) throws Exception {
// Test parcel / unparcel
Parcel parcel = Parcel.obtain();
policy.writeToParcel(parcel, 0);
@@ -485,36 +485,27 @@
}
private void checkFreezePeriods(SystemUpdatePolicy policy,
- List<Pair<Integer, Integer>> expectedPeriods) {
+ List<FreezePeriod> expectedPeriods) {
int i = 0;
- for (Pair<Integer, Integer> period : policy.getFreezePeriods()) {
- assertEquals(expectedPeriods.get(i).first, period.first);
- assertEquals(expectedPeriods.get(i).second, period.second);
+ for (FreezePeriod period : policy.getFreezePeriods()) {
+ assertEquals(expectedPeriods.get(i).getStart(), period.getStart());
+ assertEquals(expectedPeriods.get(i).getEnd(), period.getEnd());
i++;
}
}
- private LocalDate parseDate(String date) {
- // Use leap year when parsing date string to handle "02-29", but force round down
- // to Feb 28th by overriding the year to non-leap year.
- final int year;
- boolean monthDateOnly = false;
- if (date.length() == 5) {
- year = 2000;
- monthDateOnly = true;
- } else {
- year = Integer.parseInt(date.substring(0, 4));
- date = date.substring(5);
- }
- LocalDate result = LocalDate.of(year, Integer.parseInt(date.substring(0, 2)),
+ // MonthDay is of format MM-dd
+ private MonthDay parseMonthDay(String date) {
+ return MonthDay.of(Integer.parseInt(date.substring(0, 2)),
Integer.parseInt(date.substring(3, 5)));
- if (monthDateOnly) {
- return result.withYear(2001);
- } else {
- return result;
- }
}
+ // LocalDat is of format YYYY-MM-dd
+ private LocalDate parseLocalDate(String date) {
+ return parseMonthDay(date.substring(5)).atYear(Integer.parseInt(date.substring(0, 4)));
+ }
+
+
private long toMillis(int year, int month, int day) {
return LocalDateTime.of(year, month, day, 0, 0, 0).atZone(ZoneId.systemDefault())
.toInstant().toEpochMilli();
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 2f2afd7..ceee60c 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -17,12 +17,15 @@
package com.android.server.display;
import android.content.Context;
+import android.hardware.display.BrightnessConfiguration;
+import android.hardware.display.Curve;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayViewport;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.input.InputManagerInternal;
import android.os.Handler;
import android.os.IBinder;
+import android.os.UserHandle;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.SurfaceControl;
@@ -226,6 +229,62 @@
+ " virtual display adapter");
}
+ /**
+ * Tests that an exception is raised for too dark a brightness configuration.
+ */
+ public void testTooDarkBrightnessConfigurationThrowException() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ Curve minimumBrightnessCurve = displayManager.getMinimumBrightnessCurveInternal();
+ float[] lux = minimumBrightnessCurve.getX();
+ float[] minimumNits = minimumBrightnessCurve.getY();
+ float[] nits = new float[minimumNits.length];
+ // For every control point, assert that making it slightly lower than the minimum throws an
+ // exception.
+ for (int i = 0; i < nits.length; i++) {
+ for (int j = 0; j < nits.length; j++) {
+ nits[j] = minimumNits[j];
+ if (j == i) {
+ nits[j] -= 0.1f;
+ }
+ if (nits[j] < 0) {
+ nits[j] = 0;
+ }
+ }
+ BrightnessConfiguration config =
+ new BrightnessConfiguration.Builder(lux, nits).build();
+ Exception thrown = null;
+ try {
+ displayManager.validateBrightnessConfiguration(config);
+ } catch (IllegalArgumentException e) {
+ thrown = e;
+ }
+ assertNotNull("Building too dark a brightness configuration must throw an exception");
+ }
+ }
+
+ /**
+ * Tests that no exception is raised for not too dark a brightness configuration.
+ */
+ public void testBrightEnoughBrightnessConfigurationDoesNotThrowException() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ Curve minimumBrightnessCurve = displayManager.getMinimumBrightnessCurveInternal();
+ float[] lux = minimumBrightnessCurve.getX();
+ float[] nits = minimumBrightnessCurve.getY();
+ BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits).build();
+ displayManager.validateBrightnessConfiguration(config);
+ }
+
+ /**
+ * Tests that null brightness configurations are alright.
+ */
+ public void testNullBrightnessConfiguration() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ displayManager.validateBrightnessConfiguration(null);
+ }
+
private void registerDefaultDisplays(DisplayManagerService displayManager) {
Handler handler = displayManager.getDisplayHandler();
// Would prefer to call displayManager.onStart() directly here but it performs binderService
diff --git a/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 8874894..5b59e60 100644
--- a/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -23,19 +23,28 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import android.app.job.JobInfo;
import android.content.ComponentName;
+import android.content.Context;
import android.content.pm.PackageManagerInternal;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkPolicyManager;
import android.os.Build;
-import android.os.Handler;
import android.os.SystemClock;
-import android.support.test.runner.AndroidJUnit4;
import android.util.DataUnit;
import com.android.server.LocalServices;
@@ -45,14 +54,26 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
import java.time.Clock;
import java.time.ZoneOffset;
-@RunWith(AndroidJUnit4.class)
+@RunWith(MockitoJUnitRunner.class)
public class ConnectivityControllerTest {
+
+ @Mock private Context mContext;
+ @Mock private ConnectivityManager mConnManager;
+ @Mock private NetworkPolicyManager mNetPolicyManager;
+ @Mock private JobSchedulerService mService;
+
private Constants mConstants;
+ private static final int UID_RED = 10001;
+ private static final int UID_BLUE = 10002;
+
@Before
public void setUp() throws Exception {
// Assume all packages are current SDK
@@ -72,6 +93,19 @@
// Assume default constants for now
mConstants = new Constants();
+
+ // Get our mocks ready
+ when(mContext.getSystemServiceName(ConnectivityManager.class))
+ .thenReturn(Context.CONNECTIVITY_SERVICE);
+ when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+ .thenReturn(mConnManager);
+ when(mContext.getSystemServiceName(NetworkPolicyManager.class))
+ .thenReturn(Context.NETWORK_POLICY_SERVICE);
+ when(mContext.getSystemService(Context.NETWORK_POLICY_SERVICE))
+ .thenReturn(mNetPolicyManager);
+ when(mService.getTestableContext()).thenReturn(mContext);
+ when(mService.getLock()).thenReturn(mService);
+ when(mService.getConstants()).thenReturn(mConstants);
}
@Test
@@ -155,6 +189,99 @@
}
}
+ @Test
+ public void testUpdates() throws Exception {
+ final ArgumentCaptor<NetworkCallback> callback = ArgumentCaptor
+ .forClass(NetworkCallback.class);
+ doNothing().when(mConnManager).registerNetworkCallback(any(), callback.capture());
+
+ final ConnectivityController controller = new ConnectivityController(mService);
+
+ final Network meteredNet = new Network(101);
+ final NetworkCapabilities meteredCaps = createCapabilities();
+ final Network unmeteredNet = new Network(202);
+ final NetworkCapabilities unmeteredCaps = createCapabilities()
+ .addCapability(NET_CAPABILITY_NOT_METERED);
+
+ final JobStatus red = createJobStatus(createJob()
+ .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED), UID_RED);
+ final JobStatus blue = createJobStatus(createJob()
+ .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY), UID_BLUE);
+
+ // Pretend we're offline when job is added
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, null, null);
+ answerNetwork(UID_BLUE, null, null);
+
+ controller.maybeStartTrackingJobLocked(red, null);
+ controller.maybeStartTrackingJobLocked(blue, null);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
+ // Metered network
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, meteredNet, meteredCaps);
+ answerNetwork(UID_BLUE, meteredNet, meteredCaps);
+
+ callback.getValue().onCapabilitiesChanged(meteredNet, meteredCaps);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
+ // Unmetered network background
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, meteredNet, meteredCaps);
+ answerNetwork(UID_BLUE, meteredNet, meteredCaps);
+
+ callback.getValue().onCapabilitiesChanged(unmeteredNet, unmeteredCaps);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
+ // Lost metered network
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, unmeteredNet, unmeteredCaps);
+ answerNetwork(UID_BLUE, unmeteredNet, unmeteredCaps);
+
+ callback.getValue().onLost(meteredNet);
+
+ assertTrue(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
+ // Specific UID was blocked
+ {
+ reset(mConnManager);
+ answerNetwork(UID_RED, null, null);
+ answerNetwork(UID_BLUE, unmeteredNet, unmeteredCaps);
+
+ callback.getValue().onCapabilitiesChanged(unmeteredNet, unmeteredCaps);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+ }
+
+ private void answerNetwork(int uid, Network net, NetworkCapabilities caps) {
+ when(mConnManager.getActiveNetworkForUid(eq(uid))).thenReturn(net);
+ when(mConnManager.getNetworkCapabilities(eq(net))).thenReturn(caps);
+ if (net != null) {
+ final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, null, null);
+ ni.setDetailedState(DetailedState.CONNECTED, null, null);
+ when(mConnManager.getNetworkInfoForUid(eq(net), eq(uid), anyBoolean())).thenReturn(ni);
+ }
+ }
+
private static NetworkCapabilities createCapabilities() {
return new NetworkCapabilities().addCapability(NET_CAPABILITY_INTERNET)
.addCapability(NET_CAPABILITY_VALIDATED);
@@ -165,12 +292,22 @@
}
private static JobStatus createJobStatus(JobInfo.Builder job) {
- return createJobStatus(job, 0, Long.MAX_VALUE);
+ return createJobStatus(job, android.os.Process.NOBODY_UID, 0, Long.MAX_VALUE);
}
- private static JobStatus createJobStatus(JobInfo.Builder job, long earliestRunTimeElapsedMillis,
- long latestRunTimeElapsedMillis) {
- return new JobStatus(job.build(), 0, null, -1, 0, 0, null, earliestRunTimeElapsedMillis,
- latestRunTimeElapsedMillis, 0, 0, null, 0);
+ private static JobStatus createJobStatus(JobInfo.Builder job, int uid) {
+ return createJobStatus(job, uid, 0, Long.MAX_VALUE);
+ }
+
+ private static JobStatus createJobStatus(JobInfo.Builder job,
+ long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
+ return createJobStatus(job, android.os.Process.NOBODY_UID,
+ earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
+ }
+
+ private static JobStatus createJobStatus(JobInfo.Builder job, int uid,
+ long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
+ return new JobStatus(job.build(), uid, null, -1, 0, 0, null,
+ earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, 0, 0, null, 0);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
index b6be3a4..97a716f 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
@@ -22,6 +22,7 @@
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -29,6 +30,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
@@ -260,6 +262,23 @@
}
@Test
+ public void layoutWindowLw_withDisplayCutout_floatingInScreen() {
+ addDisplayCutout();
+
+ mAppWindow.attrs.flags = FLAG_LAYOUT_IN_SCREEN;
+ mAppWindow.attrs.type = TYPE_APPLICATION_OVERLAY;
+ mAppWindow.attrs.width = DISPLAY_WIDTH;
+ mAppWindow.attrs.height = DISPLAY_HEIGHT;
+ mPolicy.addWindow(mAppWindow);
+
+ mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
+
+ assertInsetByTopBottom(mAppWindow.parentFrame, 0, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mAppWindow.displayFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ }
+
+ @Test
public void layoutWindowLw_withDisplayCutout_fullscreenInCutout_landscape() {
addDisplayCutout();
setRotation(ROTATION_90);
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
index 195dd39..2c47a94 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
@@ -229,7 +229,8 @@
void addWindow(WindowState state) {
if (state instanceof FakeWindowState) {
((FakeWindowState) state).surfaceLayer =
- getWindowLayerFromTypeLw(state.getAttrs().type);
+ getWindowLayerFromTypeLw(state.getAttrs().type,
+ true /* canAddInternalSystemWindow */);
}
adjustWindowParamsLw(state, state.getAttrs(), true /* hasStatusBarPermission */);
assertEquals(WindowManagerGlobal.ADD_OKAY, prepareAddWindowLw(state, state.getAttrs()));
diff --git a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java b/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
index 8b78f10..164c80b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
@@ -88,4 +88,25 @@
verify(mMockEndDeferFinishCallback1).run();
verifyZeroInteractions(mMockEndDeferFinishCallback2);
}
+
+ @Test
+ public void testContainerRemoved() throws Exception {
+ final AppWindowToken window1 = createAppWindowToken(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final AppWindowToken window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
+ "window2").mAppToken;
+ final AnimatingAppWindowTokenRegistry registry =
+ window1.getStack().getAnimatingAppWindowTokenRegistry();
+
+ window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
+ window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
+ assertTrue(window1.isSelfAnimating());
+ assertTrue(window2.isSelfAnimating());
+
+ // Make sure that first animation finish is deferred, and removing the second window stops
+ // finishes all pending deferred finishings.
+ registry.notifyAboutToFinish(window1, mMockEndDeferFinishCallback1);
+ window2.setParent(null);
+ verify(mMockEndDeferFinishCallback1).run();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 7f1bcac..845095a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -46,6 +46,7 @@
import android.graphics.Rect;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.DisplayMetrics;
@@ -56,7 +57,9 @@
import com.android.server.wm.utils.WmDisplayCutout;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -72,6 +75,7 @@
public class DisplayContentTests extends WindowTestsBase {
@Test
+ @FlakyTest(bugId = 77772044)
public void testForAllWindows() throws Exception {
final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
mDisplayContent, "exiting app");
@@ -495,24 +499,24 @@
assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
}
- private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
- final LinkedList<WindowState> actualWindows = new LinkedList();
+ private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
+ final LinkedList<WindowState> actualWindows = new LinkedList<>();
// Test forward traversal.
mDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
- assertEquals(expectedWindows.size(), actualWindows.size());
- for (WindowState w : expectedWindows) {
- assertEquals(w, actualWindows.pollFirst());
- }
- assertTrue(actualWindows.isEmpty());
+ assertThat("bottomToTop", actualWindows, is(expectedWindowsBottomToTop));
+
+ actualWindows.clear();
// Test backward traversal.
mDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
- assertEquals(expectedWindows.size(), actualWindows.size());
- for (WindowState w : expectedWindows) {
- assertEquals(w, actualWindows.pollLast());
- }
- assertTrue(actualWindows.isEmpty());
+ assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
+ }
+
+ private static List<WindowState> reverseList(List<WindowState> list) {
+ final ArrayList<WindowState> result = new ArrayList<>(list);
+ Collections.reverse(result);
+ return result;
}
private MotionEvent createTapEvent(float x, float y, boolean isDownEvent) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
new file mode 100644
index 0000000..fbf6691
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.wm;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.os.Binder;
+import android.os.IInterface;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.IRecentsAnimationRunner;
+import android.view.SurfaceControl;
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * atest FrameworksServicesTests:com.android.server.wm.RecentsAnimationControllerTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class RecentsAnimationControllerTest extends WindowTestsBase {
+
+ @Mock SurfaceControl mMockLeash;
+ @Mock SurfaceControl.Transaction mMockTransaction;
+ @Mock OnAnimationFinishedCallback mFinishedCallback;
+ @Mock IRecentsAnimationRunner mMockRunner;
+ @Mock RecentsAnimationController.RecentsAnimationCallbacks mAnimationCallbacks;
+ private RecentsAnimationController mController;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ when(mMockRunner.asBinder()).thenReturn(new Binder());
+ mController = new RecentsAnimationController(sWm, mMockRunner, mAnimationCallbacks,
+ DEFAULT_DISPLAY);
+ }
+
+ @Test
+ public void testRemovedBeforeStarted_expectCanceled() throws Exception {
+ final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ AnimationAdapter adapter = mController.addAnimation(appWindow.getTask(),
+ false /* isRecentTaskInvisible */);
+ adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
+
+ // Remove the app window so that the animation target can not be created
+ appWindow.removeImmediately();
+ mController.startAnimation();
+
+ // Verify that the finish callback to reparent the leash is called
+ verify(mFinishedCallback).onAnimationFinished(eq(adapter));
+ // Verify the animation canceled callback to the app was made
+ verify(mMockRunner).onAnimationCanceled();
+ verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
+ }
+
+ private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
+ verify(binder, atLeast(0)).asBinder();
+ verifyNoMoreInteractions(binder);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
index 794d033..ca520ed 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -56,7 +56,8 @@
Rect windowCrop = new Rect(0, 0, 20, 20);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(windowCrop)));
@@ -65,7 +66,8 @@
@Test
public void testApply_clipAfter() {
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
@@ -77,7 +79,8 @@
// Stack bounds is (0, 0, 10, 10) position is (20, 40)
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation,
new Point(20, 40), mStackBounds, false /* canSkipFirstFrame */,
- STACK_CLIP_AFTER_ANIM);
+ STACK_CLIP_AFTER_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
@@ -89,7 +92,8 @@
public void testApply_clipBeforeNoAnimationBounds() {
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 0, 0)
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(mStackBounds)));
@@ -102,7 +106,8 @@
Animation a = createClipRectAnimation(windowCrop, windowCrop);
a.initialize(0, 0, 0, 0);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
}
@@ -113,7 +118,8 @@
Rect windowCrop = new Rect(0, 0, 5, 5);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(windowCrop)));
@@ -125,7 +131,8 @@
Rect windowCrop = new Rect(0, 0, 20, 20);
Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
- mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
+ mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM,
+ true /* isAppAnimation */);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(mStackBounds)));
diff --git a/services/tests/uiservicestests/AndroidTest.xml b/services/tests/uiservicestests/AndroidTest.xml
index d3b9d4a..11e8f09 100644
--- a/services/tests/uiservicestests/AndroidTest.xml
+++ b/services/tests/uiservicestests/AndroidTest.xml
@@ -24,5 +24,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.tests.uiservices" />
<option name="runner" value="android.testing.TestableInstrumentation" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
index 0f2e56b..9f7205b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
@@ -28,7 +28,7 @@
import android.app.ActivityManager;
import android.app.Notification;
-import android.app.Notification.Person;
+import android.app.Person;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
@@ -193,13 +193,13 @@
Notification.Builder nM1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
- "a", 100, mock(Notification.Person.class))));
+ "a", 100, mock(Person.class))));
Notification.Builder nM2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
- "a", 100, mock(Notification.Person.class)))
+ "a", 100, mock(Person.class)))
.addMessage(new Notification.MessagingStyle.Message(
- "b", 100, mock(Notification.Person.class)))
+ "b", 100, mock(Person.class)))
);
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2));
@@ -257,11 +257,11 @@
Notification.Builder nM1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
- "a", 100, mock(Notification.Person.class))));
+ "a", 100, mock(Person.class))));
Notification.Builder nM2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
- "a", 1000, mock(Notification.Person.class)))
+ "a", 1000, mock(Person.class)))
);
assertFalse(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
index a60d715..025b11a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
import android.app.Notification;
+import android.app.Person;
import android.os.Bundle;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
@@ -158,10 +159,10 @@
public void testPeopleArrayList() throws Exception {
Bundle bundle = new Bundle();
String[] expected = { "name:test" , "tel:1234" };
- final ArrayList<Notification.Person> arrayList =
+ final ArrayList<Person> arrayList =
new ArrayList<>(expected.length);
- arrayList.add(new Notification.Person().setName("test"));
- arrayList.add(new Notification.Person().setUri(expected[1]));
+ arrayList.add(new Person.Builder().setName("test").build());
+ arrayList.add(new Person.Builder().setUri(expected[1]).build());
bundle.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, arrayList);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testPeopleArrayList", expected, result);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 3acc277..d02a983 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -201,12 +201,12 @@
AudioAttributes.USAGE_MEDIA);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_GAME);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_UNKNOWN);
// Alarms only will silence system noises (but not vibrations)
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
- AudioAttributes.USAGE_UNKNOWN);
}
@Test
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 95eb14a..b3a3bf2 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -129,6 +129,9 @@
* <p>
* By default, Self-Managed {@link PhoneAccount}s do not log their calls to the call log.
* Setting this extra to {@code true} provides a means for them to log their calls.
+ * <p>
+ * Note: Only calls where the {@link Call.Details#getHandle()} {@link Uri#getScheme()} is
+ * {@link #SCHEME_SIP} or {@link #SCHEME_TEL} will be logged at the current time.
*/
public static final String EXTRA_LOG_SELF_MANAGED_CALLS =
"android.telecom.extra.LOG_SELF_MANAGED_CALLS";
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 288411a..aa76eab 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2187,7 +2187,7 @@
sDefaults.putStringArray(KEY_FILTERED_CNAP_NAMES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
- sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, false);
+ sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, true);
sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1);
sDefaults.putInt(KEY_EMERGENCY_NOTIFICATION_DELAY_INT, -1);
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index 35682a7..f7e6840 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -206,8 +206,10 @@
}
}
- /** @hide */
- protected NetworkService() {
+ /**
+ * Default constructor.
+ */
+ public NetworkService() {
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index e971d08..fa7988d 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -977,11 +977,13 @@
}
/** @hide */
+ @TestApi
public void setCellBandwidths(int[] bandwidths) {
mCellBandwidths = bandwidths;
}
/** @hide */
+ @TestApi
public void setChannelNumber(int channelNumber) {
mChannelNumber = channelNumber;
}
@@ -1172,6 +1174,7 @@
}
/** @hide */
+ @TestApi
public void setRilVoiceRadioTechnology(int rt) {
if (rt == RIL_RADIO_TECHNOLOGY_LTE_CA) {
rt = RIL_RADIO_TECHNOLOGY_LTE;
@@ -1181,6 +1184,7 @@
}
/** @hide */
+ @TestApi
public void setRilDataRadioTechnology(int rt) {
if (rt == RIL_RADIO_TECHNOLOGY_LTE_CA) {
rt = RIL_RADIO_TECHNOLOGY_LTE;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 754fe68..a9389be 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -477,6 +477,9 @@
* <p>
* Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
* the user is interested in.
+ * <p>
+ * Receivers should protect themselves by checking that the sender holds the
+ * {@code android.permission.MANAGE_SUBSCRIPTION_PLANS} permission.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@SystemApi
@@ -1719,6 +1722,8 @@
* </ul>
*
* @param subId the subscriber this relationship applies to
+ * @throws SecurityException if the caller doesn't meet the requirements
+ * outlined above.
*/
@SystemApi
public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) {
@@ -1744,10 +1749,13 @@
* {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
* </ul>
*
- * @param subId the subscriber this relationship applies to
+ * @param subId the subscriber this relationship applies to. An empty list
+ * may be sent to clear any existing plans.
* @param plans the list of plans. The first plan is always the primary and
* most important plan. Any additional plans are secondary and
* may not be displayed or used by decision making logic.
+ * @throws SecurityException if the caller doesn't meet the requirements
+ * outlined above.
*/
@SystemApi
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
@@ -1788,6 +1796,8 @@
* be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
+ * @throws SecurityException if the caller doesn't meet the requirements
+ * outlined above.
*/
@SystemApi
public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
@@ -1822,6 +1832,8 @@
* be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
+ * @throws SecurityException if the caller doesn't meet the requirements
+ * outlined above.
*/
@SystemApi
public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index 4ffb70b..ef2a364 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -24,7 +24,7 @@
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Pair;
+import android.util.Range;
import android.util.RecurrenceRule;
import com.android.internal.util.Preconditions;
@@ -209,7 +209,7 @@
* any recurrence rules. The iterator starts from the currently active cycle
* and walks backwards through time.
*/
- public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() {
+ public Iterator<Range<ZonedDateTime>> cycleIterator() {
return cycleRule.cycleIterator();
}
@@ -227,6 +227,9 @@
/**
* Start defining a {@link SubscriptionPlan} that covers a very specific
* window of time, and never automatically recurs.
+ *
+ * @param start The exact time at which the plan starts.
+ * @param end The exact time at which the plan ends.
*/
public static Builder createNonrecurring(ZonedDateTime start, ZonedDateTime end) {
if (!end.isAfter(start)) {
@@ -237,28 +240,40 @@
}
/**
- * Start defining a {@link SubscriptionPlan} that will recur
- * automatically every month. It will always recur on the same day of a
- * particular month. When a particular month ends before the defined
- * recurrence day, the plan will recur on the last instant of that
- * month.
+ * Start defining a {@link SubscriptionPlan} that starts at a specific
+ * time, and automatically recurs after each specific period of time,
+ * repeating indefinitely.
+ * <p>
+ * When the given period is set to exactly one month, the plan will
+ * always recur on the day of the month defined by
+ * {@link ZonedDateTime#getDayOfMonth()}. When a particular month ends
+ * before this day, the plan will recur on the last possible instant of
+ * that month.
+ *
+ * @param start The exact time at which the plan starts.
+ * @param period The period after which the plan automatically recurs.
*/
+ public static Builder createRecurring(ZonedDateTime start, Period period) {
+ return new Builder(start, null, period);
+ }
+
+ /** {@hide} */
+ @SystemApi
+ @Deprecated
public static Builder createRecurringMonthly(ZonedDateTime start) {
return new Builder(start, null, Period.ofMonths(1));
}
- /**
- * Start defining a {@link SubscriptionPlan} that will recur
- * automatically every week.
- */
+ /** {@hide} */
+ @SystemApi
+ @Deprecated
public static Builder createRecurringWeekly(ZonedDateTime start) {
return new Builder(start, null, Period.ofDays(7));
}
- /**
- * Start defining a {@link SubscriptionPlan} that will recur
- * automatically every day.
- */
+ /** {@hide} */
+ @SystemApi
+ @Deprecated
public static Builder createRecurringDaily(ZonedDateTime start) {
return new Builder(start, null, Period.ofDays(1));
}
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index e8c1cb1..4ca5ce3 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -429,8 +429,10 @@
}
}
- /** @hide */
- protected DataService() {
+ /**
+ * Default constructor.
+ */
+ public DataService() {
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 2f52c0a..dfb6e2c 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -77,6 +77,11 @@
result = 31 * result + featureType;
return result;
}
+
+ @Override
+ public String toString() {
+ return "{s=" + slotId + ", f=" + featureType + "}";
+ }
}
/**
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 03fc84d..7e8b2de 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -829,6 +829,16 @@
boolean isResolvingImsBinding();
/**
+ * @return true if the ImsService to bind to for the slot id specified was set, false otherwise.
+ */
+ boolean setImsService(int slotId, boolean isCarrierImsService, String packageName);
+
+ /**
+ * @return the package name of the carrier/device ImsService associated with this slot.
+ */
+ String getImsService(int slotId, boolean isCarrierImsService);
+
+ /**
* Set the network selection mode to automatic.
*
* @param subId the id of the subscription to update.
diff --git a/tests/DexLoggerIntegrationTests/AndroidTest.xml b/tests/DexLoggerIntegrationTests/AndroidTest.xml
index 8ed19f8..fb1bef6 100644
--- a/tests/DexLoggerIntegrationTests/AndroidTest.xml
+++ b/tests/DexLoggerIntegrationTests/AndroidTest.xml
@@ -25,5 +25,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.frameworks.dexloggertest"/>
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/tests/UsbTests/AndroidTest.xml b/tests/UsbTests/AndroidTest.xml
index 0b623fb..4affad3 100644
--- a/tests/UsbTests/AndroidTest.xml
+++ b/tests/UsbTests/AndroidTest.xml
@@ -25,5 +25,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.server.usb"/>
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+ <option name="hidden-api-checks" value="false"/>
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/net/AndroidTest.xml b/tests/net/AndroidTest.xml
index f8ecc6b..6e020a3 100644
--- a/tests/net/AndroidTest.xml
+++ b/tests/net/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.tests.net" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
index 13210e8..8160924 100644
--- a/tests/net/java/android/net/IpSecManagerTest.java
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -38,6 +38,7 @@
import com.android.server.IpSecService;
import java.net.InetAddress;
+import java.net.Socket;
import java.net.UnknownHostException;
import org.junit.Before;
@@ -195,6 +196,33 @@
}
@Test
+ public void testApplyTransportModeTransformEnsuresSocketCreation() throws Exception {
+ Socket socket = new Socket();
+ IpSecConfig dummyConfig = new IpSecConfig();
+ IpSecTransform dummyTransform = new IpSecTransform(null, dummyConfig);
+
+ // Even if underlying SocketImpl is not initalized, this should force the init, and
+ // thereby succeed.
+ mIpSecManager.applyTransportModeTransform(
+ socket, IpSecManager.DIRECTION_IN, dummyTransform);
+
+ // Check to make sure the FileDescriptor is non-null
+ assertNotNull(socket.getFileDescriptor$());
+ }
+
+ @Test
+ public void testRemoveTransportModeTransformsForcesSocketCreation() throws Exception {
+ Socket socket = new Socket();
+
+ // Even if underlying SocketImpl is not initalized, this should force the init, and
+ // thereby succeed.
+ mIpSecManager.removeTransportModeTransforms(socket);
+
+ // Check to make sure the FileDescriptor is non-null
+ assertNotNull(socket.getFileDescriptor$());
+ }
+
+ @Test
public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
IpSecUdpEncapResponse udpEncapResp =
new IpSecUdpEncapResponse(
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index fef702e..9364ec8 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -34,7 +34,7 @@
import android.net.apf.ApfFilter.ApfConfiguration;
import android.net.apf.ApfGenerator.IllegalInstructionException;
import android.net.apf.ApfGenerator.Register;
-import android.net.ip.IpManager;
+import android.net.ip.IpClient;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
import android.net.util.InterfaceParams;
@@ -606,7 +606,7 @@
}
}
- private class MockIpManagerCallback extends IpManager.Callback {
+ private class MockIpClientCallback extends IpClient.Callback {
private final ConditionVariable mGotApfProgram = new ConditionVariable();
private byte[] mLastApfProgram;
@@ -637,8 +637,8 @@
private final long mFixedTimeMs = SystemClock.elapsedRealtime();
public TestApfFilter(Context context, ApfConfiguration config,
- IpManager.Callback ipManagerCallback, IpConnectivityLog log) throws Exception {
- super(context, config, InterfaceParams.getByName("lo"), ipManagerCallback, log);
+ IpClient.Callback ipClientCallback, IpConnectivityLog log) throws Exception {
+ super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, log);
}
// Pretend an RA packet has been received and show it to ApfFilter.
@@ -761,29 +761,29 @@
private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0};
// Helper to initialize a default apfFilter.
- private ApfFilter setupApfFilter(IpManager.Callback ipManagerCallback, ApfConfiguration config)
+ private ApfFilter setupApfFilter(IpClient.Callback ipClientCallback, ApfConfiguration config)
throws Exception {
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(link);
- TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog);
+ TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
apfFilter.setLinkProperties(lp);
return apfFilter;
}
@Test
public void testApfFilterIPv4() throws Exception {
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ MockIpClientCallback ipClientCallback = new MockIpClientCallback();
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(link);
ApfConfiguration config = getDefaultConfig();
config.multicastFilter = DROP_MULTICAST;
- TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog);
+ TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
apfFilter.setLinkProperties(lp);
- byte[] program = ipManagerCallback.getApfProgram();
+ byte[] program = ipClientCallback.getApfProgram();
// Verify empty packet of 100 zero bytes is passed
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
@@ -830,10 +830,10 @@
@Test
public void testApfFilterIPv6() throws Exception {
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ MockIpClientCallback ipClientCallback = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
- TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog);
- byte[] program = ipManagerCallback.getApfProgram();
+ TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
+ byte[] program = ipClientCallback.getApfProgram();
// Verify empty IPv6 packet is passed
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
@@ -868,17 +868,17 @@
final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ MockIpClientCallback ipClientCallback = new MockIpClientCallback();
LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(link);
ApfConfiguration config = getDefaultConfig();
config.ieee802_3Filter = DROP_802_3_FRAMES;
- TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog);
+ TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
apfFilter.setLinkProperties(lp);
- byte[] program = ipManagerCallback.getApfProgram();
+ byte[] program = ipClientCallback.getApfProgram();
// Construct IPv4 and IPv6 multicast packets.
ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
@@ -915,9 +915,9 @@
assertPass(program, bcastv4unicastl2packet.array());
// Turn on multicast filter and verify it works
- ipManagerCallback.resetApfProgramWait();
+ ipClientCallback.resetApfProgramWait();
apfFilter.setMulticastFilter(true);
- program = ipManagerCallback.getApfProgram();
+ program = ipClientCallback.getApfProgram();
assertDrop(program, mcastv4packet.array());
assertDrop(program, mcastv6packet.array());
assertDrop(program, bcastv4packet1.array());
@@ -925,9 +925,9 @@
assertDrop(program, bcastv4unicastl2packet.array());
// Turn off multicast filter and verify it's off
- ipManagerCallback.resetApfProgramWait();
+ ipClientCallback.resetApfProgramWait();
apfFilter.setMulticastFilter(false);
- program = ipManagerCallback.getApfProgram();
+ program = ipClientCallback.getApfProgram();
assertPass(program, mcastv4packet.array());
assertPass(program, mcastv6packet.array());
assertPass(program, bcastv4packet1.array());
@@ -935,13 +935,13 @@
assertPass(program, bcastv4unicastl2packet.array());
// Verify it can be initialized to on
- ipManagerCallback.resetApfProgramWait();
+ ipClientCallback.resetApfProgramWait();
apfFilter.shutdown();
config.multicastFilter = DROP_MULTICAST;
config.ieee802_3Filter = DROP_802_3_FRAMES;
- apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog);
+ apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
apfFilter.setLinkProperties(lp);
- program = ipManagerCallback.getApfProgram();
+ program = ipClientCallback.getApfProgram();
assertDrop(program, mcastv4packet.array());
assertDrop(program, mcastv6packet.array());
assertDrop(program, bcastv4packet1.array());
@@ -956,8 +956,8 @@
@Test
public void testApfFilterMulticastPingWhileDozing() throws Exception {
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
- ApfFilter apfFilter = setupApfFilter(ipManagerCallback, getDefaultConfig());
+ MockIpClientCallback ipClientCallback = new MockIpClientCallback();
+ ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig());
// Construct a multicast ICMPv6 ECHO request.
final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
@@ -968,35 +968,35 @@
put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
// Normally, we let multicast pings alone...
- assertPass(ipManagerCallback.getApfProgram(), packet.array());
+ assertPass(ipClientCallback.getApfProgram(), packet.array());
// ...and even while dozing...
apfFilter.setDozeMode(true);
- assertPass(ipManagerCallback.getApfProgram(), packet.array());
+ assertPass(ipClientCallback.getApfProgram(), packet.array());
// ...but when the multicast filter is also enabled, drop the multicast pings to save power.
apfFilter.setMulticastFilter(true);
- assertDrop(ipManagerCallback.getApfProgram(), packet.array());
+ assertDrop(ipClientCallback.getApfProgram(), packet.array());
// However, we should still let through all other ICMPv6 types.
ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone());
raPacket.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ROUTER_ADVERTISEMENT);
- assertPass(ipManagerCallback.getApfProgram(), raPacket.array());
+ assertPass(ipClientCallback.getApfProgram(), raPacket.array());
// Now wake up from doze mode to ensure that we no longer drop the packets.
// (The multicast filter is still enabled at this point).
apfFilter.setDozeMode(false);
- assertPass(ipManagerCallback.getApfProgram(), packet.array());
+ assertPass(ipClientCallback.getApfProgram(), packet.array());
apfFilter.shutdown();
}
@Test
public void testApfFilter802_3() throws Exception {
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ MockIpClientCallback ipClientCallback = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
- ApfFilter apfFilter = setupApfFilter(ipManagerCallback, config);
- byte[] program = ipManagerCallback.getApfProgram();
+ ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
+ byte[] program = ipClientCallback.getApfProgram();
// Verify empty packet of 100 zero bytes is passed
// Note that eth-type = 0 makes it an IEEE802.3 frame
@@ -1012,11 +1012,11 @@
assertPass(program, packet.array());
// Now turn on the filter
- ipManagerCallback.resetApfProgramWait();
+ ipClientCallback.resetApfProgramWait();
apfFilter.shutdown();
config.ieee802_3Filter = DROP_802_3_FRAMES;
- apfFilter = setupApfFilter(ipManagerCallback, config);
- program = ipManagerCallback.getApfProgram();
+ apfFilter = setupApfFilter(ipClientCallback, config);
+ program = ipClientCallback.getApfProgram();
// Verify that IEEE802.3 frame is dropped
// In this case ethtype is used for payload length
@@ -1040,10 +1040,10 @@
final int[] ipv4BlackList = {ETH_P_IP};
final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ MockIpClientCallback ipClientCallback = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
- ApfFilter apfFilter = setupApfFilter(ipManagerCallback, config);
- byte[] program = ipManagerCallback.getApfProgram();
+ ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
+ byte[] program = ipClientCallback.getApfProgram();
// Verify empty packet of 100 zero bytes is passed
// Note that eth-type = 0 makes it an IEEE802.3 frame
@@ -1059,11 +1059,11 @@
assertPass(program, packet.array());
// Now add IPv4 to the black list
- ipManagerCallback.resetApfProgramWait();
+ ipClientCallback.resetApfProgramWait();
apfFilter.shutdown();
config.ethTypeBlackList = ipv4BlackList;
- apfFilter = setupApfFilter(ipManagerCallback, config);
- program = ipManagerCallback.getApfProgram();
+ apfFilter = setupApfFilter(ipClientCallback, config);
+ program = ipClientCallback.getApfProgram();
// Verify that IPv4 frame will be dropped
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
@@ -1074,11 +1074,11 @@
assertPass(program, packet.array());
// Now let us have both IPv4 and IPv6 in the black list
- ipManagerCallback.resetApfProgramWait();
+ ipClientCallback.resetApfProgramWait();
apfFilter.shutdown();
config.ethTypeBlackList = ipv4Ipv6BlackList;
- apfFilter = setupApfFilter(ipManagerCallback, config);
- program = ipManagerCallback.getApfProgram();
+ apfFilter = setupApfFilter(ipClientCallback, config);
+ program = ipClientCallback.getApfProgram();
// Verify that IPv4 frame will be dropped
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
@@ -1091,7 +1091,7 @@
apfFilter.shutdown();
}
- private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
+ private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) {
cb.resetApfProgramWait();
filter.setLinkProperties(lp);
return cb.getApfProgram();
@@ -1114,23 +1114,23 @@
@Test
public void testApfFilterArp() throws Exception {
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ MockIpClientCallback ipClientCallback = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
config.multicastFilter = DROP_MULTICAST;
config.ieee802_3Filter = DROP_802_3_FRAMES;
- TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog);
+ TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
// Verify initially ARP request filter is off, and GARP filter is on.
- verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
+ verifyArpFilter(ipClientCallback.getApfProgram(), PASS);
// Inform ApfFilter of our address and verify ARP filtering is on
LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
LinkProperties lp = new LinkProperties();
assertTrue(lp.addLinkAddress(linkAddress));
- verifyArpFilter(getProgram(ipManagerCallback, apfFilter, lp), DROP);
+ verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP);
// Inform ApfFilter of loss of IP and verify ARP filtering is off
- verifyArpFilter(getProgram(ipManagerCallback, apfFilter, new LinkProperties()), PASS);
+ verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS);
apfFilter.shutdown();
}
@@ -1161,7 +1161,7 @@
return packet.array();
}
- // Verify that the last program pushed to the IpManager.Callback properly filters the
+ // Verify that the last program pushed to the IpClient.Callback properly filters the
// given packet for the given lifetime.
private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
final int FRACTION_OF_LIFETIME = 6;
@@ -1191,12 +1191,12 @@
// Test that when ApfFilter is shown the given packet, it generates a program to filter it
// for the given lifetime.
- private void verifyRaLifetime(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
+ private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
// Verify new program generated if ApfFilter witnesses RA
- ipManagerCallback.resetApfProgramWait();
+ ipClientCallback.resetApfProgramWait();
apfFilter.pretendPacketReceived(packet.array());
- byte[] program = ipManagerCallback.getApfProgram();
+ byte[] program = ipClientCallback.getApfProgram();
verifyRaLifetime(program, packet, lifetime);
}
@@ -1229,21 +1229,21 @@
&& (ev1.dnsslLifetime == ev2.dnsslLifetime);
}
- private void assertInvalidRa(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
+ private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
ByteBuffer packet) throws IOException, ErrnoException {
- ipManagerCallback.resetApfProgramWait();
+ ipClientCallback.resetApfProgramWait();
apfFilter.pretendPacketReceived(packet.array());
- ipManagerCallback.assertNoProgramUpdate();
+ ipClientCallback.assertNoProgramUpdate();
}
@Test
public void testApfFilterRa() throws Exception {
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ MockIpClientCallback ipClientCallback = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
config.multicastFilter = DROP_MULTICAST;
config.ieee802_3Filter = DROP_802_3_FRAMES;
- TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipManagerCallback, mLog);
- byte[] program = ipManagerCallback.getApfProgram();
+ TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
+ byte[] program = ipClientCallback.getApfProgram();
final int ROUTER_LIFETIME = 1000;
final int PREFIX_VALID_LIFETIME = 200;
@@ -1268,7 +1268,7 @@
basePacket.put(IPV6_ALL_NODES_ADDRESS);
assertPass(program, basePacket.array());
- verifyRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME);
+ verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
@@ -1286,7 +1286,7 @@
zeroLengthOptionPacket.put(basePacket);
zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
zeroLengthOptionPacket.put((byte)0);
- assertInvalidRa(apfFilter, ipManagerCallback, zeroLengthOptionPacket);
+ assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket);
// Generate several RAs with different options and lifetimes, and verify when
// ApfFilter is shown these packets, it generates programs to filter them for the
@@ -1304,7 +1304,7 @@
ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
PREFIX_VALID_LIFETIME);
verifyRaLifetime(
- apfFilter, ipManagerCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
+ apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
verifyRaEvent(new RaEvent(
ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
@@ -1316,7 +1316,7 @@
rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
rdnssOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
- verifyRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, RDNSS_LIFETIME);
+ verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
@@ -1327,7 +1327,7 @@
routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
routeInfoOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
- verifyRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
+ verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
@@ -1338,11 +1338,11 @@
dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
dnsslOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
- verifyRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, ROUTER_LIFETIME);
+ verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
// Verify that current program filters all five RAs:
- program = ipManagerCallback.getApfProgram();
+ program = ipClientCallback.getApfProgram();
verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
@@ -1384,7 +1384,7 @@
public void testRaParsing() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
- MockIpManagerCallback cb = new MockIpManagerCallback();
+ MockIpClientCallback cb = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
config.multicastFilter = DROP_MULTICAST;
config.ieee802_3Filter = DROP_802_3_FRAMES;
@@ -1405,7 +1405,7 @@
public void testRaProcessing() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
- MockIpManagerCallback cb = new MockIpManagerCallback();
+ MockIpClientCallback cb = new MockIpClientCallback();
ApfConfiguration config = getDefaultConfig();
config.multicastFilter = DROP_MULTICAST;
config.ieee802_3Filter = DROP_802_3_FRAMES;
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 163dd2a..482d6e1 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -17,6 +17,9 @@
package com.android.server;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
@@ -70,6 +73,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -157,6 +161,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -181,6 +186,9 @@
private static final int TIMEOUT_MS = 500;
private static final int TEST_LINGER_DELAY_MS = 120;
+ private static final String MOBILE_IFNAME = "test_rmnet_data0";
+ private static final String WIFI_IFNAME = "test_wlan0";
+
private MockContext mServiceContext;
private WrappedConnectivityService mService;
private WrappedConnectivityManager mCm;
@@ -751,7 +759,7 @@
// NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
private class WrappedNetworkMonitor extends NetworkMonitor {
- public Handler connectivityHandler;
+ public final Handler connectivityHandler;
// HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
public int gen204ProbeResult = 500;
public String gen204ProbeRedirectUrl = null;
@@ -872,6 +880,10 @@
return mMetricsService;
}
+ @Override
+ protected void registerNetdEventCallback() {
+ }
+
public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
return mLastCreatedNetworkMonitor;
}
@@ -928,6 +940,7 @@
// Ensure that the default setting for Captive Portals is used for most tests
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
setMobileDataAlwaysOn(false);
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
}
@After
@@ -2582,6 +2595,14 @@
waitForIdle();
}
+ private void setPrivateDnsSettings(String mode, String specifier) {
+ final ContentResolver cr = mServiceContext.getContentResolver();
+ Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
+ Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
+ mService.updatePrivateDnsSettings();
+ waitForIdle();
+ }
+
private boolean isForegroundNetwork(MockNetworkAgent network) {
NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
assertNotNull(nc);
@@ -3583,7 +3604,7 @@
mCm.registerNetworkCallback(networkRequest, networkCallback);
LinkProperties lp = new LinkProperties();
- lp.setInterfaceName("wlan0");
+ lp.setInterfaceName(WIFI_IFNAME);
LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
@@ -3672,52 +3693,63 @@
@Test
public void testBasicDnsConfigurationPushed() throws Exception {
- final String IFNAME = "test_rmnet_data0";
- final String[] EMPTY_TLS_SERVERS = new String[0];
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
+ ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
+
+ // Clear any interactions that occur as a result of CS starting up.
+ reset(mNetworkManagementService);
+
+ final String[] EMPTY_STRING_ARRAY = new String[0];
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
waitForIdle();
verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
- anyInt(), any(), any(), any(), anyString(), eq(EMPTY_TLS_SERVERS));
+ anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
+ verifyNoMoreInteractions(mNetworkManagementService);
final LinkProperties cellLp = new LinkProperties();
- cellLp.setInterfaceName(IFNAME);
+ cellLp.setInterfaceName(MOBILE_IFNAME);
// Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
// "is-reachable" testing in order to not program netd with unreachable
// nameservers that it might try repeated to validate.
cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
- cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), IFNAME));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
+ MOBILE_IFNAME));
cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
- cellLp.addRoute(
- new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), IFNAME));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
+ MOBILE_IFNAME));
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(false);
waitForIdle();
- verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
- anyInt(), mStringArrayCaptor.capture(), any(), any(),
- anyString(), eq(EMPTY_TLS_SERVERS));
// CS tells netd about the empty DNS config for this network.
- assertEmpty(mStringArrayCaptor.getValue());
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
+ anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
reset(mNetworkManagementService);
cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
- verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
- anyString(), eq(EMPTY_TLS_SERVERS));
+ eq(""), tlsServers.capture());
assertEquals(1, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
+ // Opportunistic mode.
+ assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
reset(mNetworkManagementService);
cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
- verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
- anyString(), eq(EMPTY_TLS_SERVERS));
+ eq(""), tlsServers.capture());
assertEquals(2, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
+ // Opportunistic mode.
+ assertEquals(2, tlsServers.getValue().length);
+ assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
reset(mNetworkManagementService);
final String TLS_SPECIFIER = "tls.example.com";
@@ -3730,7 +3762,7 @@
mCellNetworkAgent.getNetwork().netId,
new DnsManager.PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS)));
waitForIdle();
- verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
eq(TLS_SPECIFIER), eq(TLS_SERVERS));
assertEquals(2, mStringArrayCaptor.getValue().length);
@@ -3739,6 +3771,195 @@
reset(mNetworkManagementService);
}
+ @Test
+ public void testPrivateDnsSettingsChange() throws Exception {
+ final String[] EMPTY_STRING_ARRAY = new String[0];
+ ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
+
+ // Clear any interactions that occur as a result of CS starting up.
+ reset(mNetworkManagementService);
+
+ // The default on Android is opportunistic mode ("Automatic").
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
+
+ final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ mCm.requestNetwork(cellRequest, cellNetworkCallback);
+
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ waitForIdle();
+ // CS tells netd about the empty DNS config for this network.
+ verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
+ anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
+ verifyNoMoreInteractions(mNetworkManagementService);
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName(MOBILE_IFNAME);
+ // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
+ // "is-reachable" testing in order to not program netd with unreachable
+ // nameservers that it might try repeated to validate.
+ cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
+ MOBILE_IFNAME));
+ cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
+ MOBILE_IFNAME));
+ cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
+ cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
+
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ mCellNetworkAgent.connect(false);
+ waitForIdle();
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ eq(""), tlsServers.capture());
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ // Opportunistic mode.
+ assertEquals(2, tlsServers.getValue().length);
+ assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+ cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
+ mCellNetworkAgent);
+ CallbackInfo cbi = cellNetworkCallback.expectCallback(
+ CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
+ assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ eq(""), eq(EMPTY_STRING_ARRAY));
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+ cellNetworkCallback.assertNoCallback();
+
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ eq(""), tlsServers.capture());
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ assertEquals(2, tlsServers.getValue().length);
+ assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+ cellNetworkCallback.assertNoCallback();
+
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
+ // Can't test dns configuration for strict mode without properly mocking
+ // out the DNS lookups, but can test that LinkProperties is updated.
+ cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
+ assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ }
+
+ @Test
+ public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
+ // The default on Android is opportunistic mode ("Automatic").
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
+
+ final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ mCm.requestNetwork(cellRequest, cellNetworkCallback);
+
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ waitForIdle();
+ LinkProperties lp = new LinkProperties();
+ mCellNetworkAgent.sendLinkProperties(lp);
+ mCellNetworkAgent.connect(false);
+ waitForIdle();
+ cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
+ mCellNetworkAgent);
+ CallbackInfo cbi = cellNetworkCallback.expectCallback(
+ CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
+ assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ Set<InetAddress> dnsServers = new HashSet<>();
+ checkDnsServers(cbi.arg, dnsServers);
+
+ // Send a validation event for a server that is not part of the current
+ // resolver config. The validation event should be ignored.
+ mService.mNetdEventCallback.onPrivateDnsValidationEvent(
+ mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
+ cellNetworkCallback.assertNoCallback();
+
+ // Add a dns server to the LinkProperties.
+ LinkProperties lp2 = new LinkProperties(lp);
+ lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
+ mCellNetworkAgent.sendLinkProperties(lp2);
+ cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
+ assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ dnsServers.add(InetAddress.getByName("145.100.185.16"));
+ checkDnsServers(cbi.arg, dnsServers);
+
+ // Send a validation event containing a hostname that is not part of
+ // the current resolver config. The validation event should be ignored.
+ mService.mNetdEventCallback.onPrivateDnsValidationEvent(
+ mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
+ cellNetworkCallback.assertNoCallback();
+
+ // Send a validation event where validation failed.
+ mService.mNetdEventCallback.onPrivateDnsValidationEvent(
+ mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
+ cellNetworkCallback.assertNoCallback();
+
+ // Send a validation event where validation succeeded for a server in
+ // the current resolver config. A LinkProperties callback with updated
+ // private dns fields should be sent.
+ mService.mNetdEventCallback.onPrivateDnsValidationEvent(
+ mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
+ cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
+ assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ checkDnsServers(cbi.arg, dnsServers);
+
+ // The private dns fields in LinkProperties should be preserved when
+ // the network agent sends unrelated changes.
+ LinkProperties lp3 = new LinkProperties(lp2);
+ lp3.setMtu(1300);
+ mCellNetworkAgent.sendLinkProperties(lp3);
+ cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
+ assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ checkDnsServers(cbi.arg, dnsServers);
+ assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
+
+ // Removing the only validated server should affect the private dns
+ // fields in LinkProperties.
+ LinkProperties lp4 = new LinkProperties(lp3);
+ lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
+ mCellNetworkAgent.sendLinkProperties(lp4);
+ cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
+ assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ dnsServers.remove(InetAddress.getByName("145.100.185.16"));
+ checkDnsServers(cbi.arg, dnsServers);
+ assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
+ }
+
private void checkDirectlyConnectedRoutes(Object callbackObj,
Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
assertTrue(callbackObj instanceof LinkProperties);
@@ -3756,6 +3977,13 @@
assertTrue(observedRoutes.containsAll(expectedRoutes));
}
+ private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
+ assertTrue(callbackObj instanceof LinkProperties);
+ LinkProperties lp = (LinkProperties) callbackObj;
+ assertEquals(dnsServers.size(), lp.getDnsServers().size());
+ assertTrue(lp.getDnsServers().containsAll(dnsServers));
+ }
+
private static <T> void assertEmpty(T[] ts) {
int length = ts.length;
assertEquals("expected empty array, but length was " + length, 0, length);
diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
new file mode 100644
index 0000000..bcd8bf3
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
@@ -0,0 +1,201 @@
+/*
+ * 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.connectivity;
+
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.os.INetworkManagementService;
+import android.provider.Settings;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.connectivity.MockableSystemProperties;
+
+import java.net.InetAddress;
+
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link DnsManager}.
+ *
+ * Build, install and run with:
+ * runtest frameworks-net -c com.android.server.connectivity.DnsManagerTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DnsManagerTest {
+ static final int TEST_NETID = 100;
+ static final int TEST_NETID_ALTERNATE = 101;
+ static final int TEST_NETID_UNTRACKED = 102;
+ final boolean IS_DEFAULT = true;
+ final boolean NOT_DEFAULT = false;
+
+ DnsManager mDnsManager;
+ MockContentResolver mContentResolver;
+
+ @Mock Context mCtx;
+ @Mock INetworkManagementService mNMService;
+ @Mock MockableSystemProperties mSystemProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContentResolver = new MockContentResolver();
+ mContentResolver.addProvider(Settings.AUTHORITY,
+ new FakeSettingsProvider());
+ when(mCtx.getContentResolver()).thenReturn(mContentResolver);
+ mDnsManager = new DnsManager(mCtx, mNMService, mSystemProperties);
+
+ // Clear the private DNS settings
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.PRIVATE_DNS_MODE, "");
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.PRIVATE_DNS_SPECIFIER, "");
+ }
+
+ @Test
+ public void testTrackedValidationUpdates() throws Exception {
+ mDnsManager.updatePrivateDns(new Network(TEST_NETID),
+ mDnsManager.getPrivateDnsConfig());
+ mDnsManager.updatePrivateDns(new Network(TEST_NETID_ALTERNATE),
+ mDnsManager.getPrivateDnsConfig());
+ LinkProperties lp = new LinkProperties();
+ lp.addDnsServer(InetAddress.getByName("3.3.3.3"));
+ lp.addDnsServer(InetAddress.getByName("4.4.4.4"));
+
+ // Send a validation event that is tracked on the alternate netId
+ mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
+ mDnsManager.setDnsConfigurationForNetwork(TEST_NETID_ALTERNATE, lp, NOT_DEFAULT);
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_ALTERNATE,
+ InetAddress.parseNumericAddress("4.4.4.4"), "", true));
+ LinkProperties fixedLp = new LinkProperties(lp);
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
+ assertFalse(fixedLp.isPrivateDnsActive());
+ assertNull(fixedLp.getPrivateDnsServerName());
+ fixedLp = new LinkProperties(lp);
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID_ALTERNATE, fixedLp);
+ assertTrue(fixedLp.isPrivateDnsActive());
+ assertNull(fixedLp.getPrivateDnsServerName());
+
+ // Switch to strict mode
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.PRIVATE_DNS_MODE,
+ PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.PRIVATE_DNS_SPECIFIER, "strictmode.com");
+ mDnsManager.updatePrivateDns(new Network(TEST_NETID),
+ mDnsManager.getPrivateDnsConfig());
+ mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
+ fixedLp = new LinkProperties(lp);
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
+ assertTrue(fixedLp.isPrivateDnsActive());
+ assertEquals("strictmode.com", fixedLp.getPrivateDnsServerName());
+ fixedLp = new LinkProperties(lp);
+ }
+
+ @Test
+ public void testIgnoreUntrackedValidationUpdates() throws Exception {
+ // The PrivateDnsConfig map is empty, so no validation events will
+ // be tracked.
+ LinkProperties lp = new LinkProperties();
+ lp.addDnsServer(InetAddress.getByName("3.3.3.3"));
+ mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
+ InetAddress.parseNumericAddress("3.3.3.3"), "", true));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ assertFalse(lp.isPrivateDnsActive());
+ assertNull(lp.getPrivateDnsServerName());
+
+ // Validation event has untracked netId
+ mDnsManager.updatePrivateDns(new Network(TEST_NETID),
+ mDnsManager.getPrivateDnsConfig());
+ mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_UNTRACKED,
+ InetAddress.parseNumericAddress("3.3.3.3"), "", true));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ assertFalse(lp.isPrivateDnsActive());
+ assertNull(lp.getPrivateDnsServerName());
+
+ // Validation event has untracked ipAddress
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
+ InetAddress.parseNumericAddress("4.4.4.4"), "", true));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ assertFalse(lp.isPrivateDnsActive());
+ assertNull(lp.getPrivateDnsServerName());
+
+ // Validation event has untracked hostname
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
+ InetAddress.parseNumericAddress("3.3.3.3"), "hostname",
+ true));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ assertFalse(lp.isPrivateDnsActive());
+ assertNull(lp.getPrivateDnsServerName());
+
+ // Validation event failed
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
+ InetAddress.parseNumericAddress("3.3.3.3"), "", false));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ assertFalse(lp.isPrivateDnsActive());
+ assertNull(lp.getPrivateDnsServerName());
+
+ // Network removed
+ mDnsManager.removeNetwork(new Network(TEST_NETID));
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
+ InetAddress.parseNumericAddress("3.3.3.3"), "", true));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ assertFalse(lp.isPrivateDnsActive());
+ assertNull(lp.getPrivateDnsServerName());
+
+ // Turn private DNS mode off
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OFF);
+ mDnsManager.updatePrivateDns(new Network(TEST_NETID),
+ mDnsManager.getPrivateDnsConfig());
+ mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
+ InetAddress.parseNumericAddress("3.3.3.3"), "", true));
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
+ assertFalse(lp.isPrivateDnsActive());
+ assertNull(lp.getPrivateDnsServerName());
+ }
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 2f7b50d..b333126 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -143,7 +143,7 @@
WifiConfiguration getWifiApConfiguration();
- void setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
+ boolean setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
Messenger getWifiServiceMessenger(String packageName);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index b77b1ad..f6c67c9 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -28,10 +28,12 @@
import android.net.wifi.WifiInfo;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.BackupUtils;
import android.util.Log;
+import android.util.TimeUtils;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -611,37 +613,6 @@
/**
* @hide
- * Last time the system tried to connect and failed.
- */
- public long lastConnectionFailure;
-
- /**
- * @hide
- * Last time the system tried to roam and failed because of authentication failure or DHCP
- * RENEW failure.
- */
- public long lastRoamingFailure;
-
- /** @hide */
- public static int ROAMING_FAILURE_IP_CONFIG = 1;
- /** @hide */
- public static int ROAMING_FAILURE_AUTH_FAILURE = 2;
-
- /**
- * @hide
- * Initial amount of time this Wifi configuration gets blacklisted for network switching
- * because of roaming failure
- */
- public long roamingFailureBlackListTimeMilli = 1000;
-
- /**
- * @hide
- * Last roaming failure reason code
- */
- public int lastRoamingFailureReason;
-
- /**
- * @hide
* Last time the system was disconnected to this configuration.
*/
public long lastDisconnected;
@@ -1620,8 +1591,9 @@
}
if (mNetworkSelectionStatus.getConnectChoice() != null) {
sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice());
- sbuf.append(" connect choice set time: ").append(mNetworkSelectionStatus
- .getConnectChoiceTimestamp());
+ sbuf.append(" connect choice set time: ")
+ .append(TimeUtils.logTimeOfDay(
+ mNetworkSelectionStatus.getConnectChoiceTimestamp()));
}
sbuf.append(" hasEverConnected: ")
.append(mNetworkSelectionStatus.getHasEverConnected()).append("\n");
@@ -1724,7 +1696,7 @@
sbuf.append(" networkSelectionBSSID="
+ mNetworkSelectionStatus.getNetworkSelectionBSSID());
}
- long now_ms = System.currentTimeMillis();
+ long now_ms = SystemClock.elapsedRealtime();
if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus
.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) {
sbuf.append('\n');
@@ -1746,35 +1718,9 @@
if (this.lastConnected != 0) {
sbuf.append('\n');
- long diff = now_ms - this.lastConnected;
- if (diff <= 0) {
- sbuf.append("lastConnected since <incorrect>");
- } else {
- sbuf.append("lastConnected: ").append(Long.toString(diff / 1000)).append("sec ");
- }
+ sbuf.append("lastConnected: ").append(TimeUtils.logTimeOfDay(this.lastConnected));
+ sbuf.append(" ");
}
- if (this.lastConnectionFailure != 0) {
- sbuf.append('\n');
- long diff = now_ms - this.lastConnectionFailure;
- if (diff <= 0) {
- sbuf.append("lastConnectionFailure since <incorrect> ");
- } else {
- sbuf.append("lastConnectionFailure: ").append(Long.toString(diff / 1000));
- sbuf.append("sec ");
- }
- }
- if (this.lastRoamingFailure != 0) {
- sbuf.append('\n');
- long diff = now_ms - this.lastRoamingFailure;
- if (diff <= 0) {
- sbuf.append("lastRoamingFailure since <incorrect> ");
- } else {
- sbuf.append("lastRoamingFailure: ").append(Long.toString(diff / 1000));
- sbuf.append("sec ");
- }
- }
- sbuf.append("roamingFailureBlackListTimeMilli: ").
- append(Long.toString(this.roamingFailureBlackListTimeMilli));
sbuf.append('\n');
if (this.linkedConfigurations != null) {
for (String key : this.linkedConfigurations.keySet()) {
@@ -2119,10 +2065,6 @@
lastConnected = source.lastConnected;
lastDisconnected = source.lastDisconnected;
- lastConnectionFailure = source.lastConnectionFailure;
- lastRoamingFailure = source.lastRoamingFailure;
- lastRoamingFailureReason = source.lastRoamingFailureReason;
- roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli;
numScorerOverride = source.numScorerOverride;
numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
numAssociation = source.numAssociation;
@@ -2188,10 +2130,6 @@
dest.writeInt(lastUpdateUid);
dest.writeString(creatorName);
dest.writeString(lastUpdateName);
- dest.writeLong(lastConnectionFailure);
- dest.writeLong(lastRoamingFailure);
- dest.writeInt(lastRoamingFailureReason);
- dest.writeLong(roamingFailureBlackListTimeMilli);
dest.writeInt(numScorerOverride);
dest.writeInt(numScorerOverrideAndSwitchedNetwork);
dest.writeInt(numAssociation);
@@ -2257,10 +2195,6 @@
config.lastUpdateUid = in.readInt();
config.creatorName = in.readString();
config.lastUpdateName = in.readString();
- config.lastConnectionFailure = in.readLong();
- config.lastRoamingFailure = in.readLong();
- config.lastRoamingFailureReason = in.readInt();
- config.roamingFailureBlackListTimeMilli = in.readLong();
config.numScorerOverride = in.readInt();
config.numScorerOverrideAndSwitchedNetwork = in.readInt();
config.numAssociation = in.readInt();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 433285b..9c6c8a9 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2141,7 +2141,8 @@
}
/**
- * Sets the Wi-Fi AP Configuration.
+ * Sets the Wi-Fi AP Configuration. The AP configuration must either be open or
+ * WPA2 PSK networks.
* @return {@code true} if the operation succeeded, {@code false} otherwise
*
* @hide
@@ -2150,8 +2151,7 @@
@RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
try {
- mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
- return true;
+ return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/wifi/tests/AndroidTest.xml b/wifi/tests/AndroidTest.xml
index 764eb2b..45c7a17 100644
--- a/wifi/tests/AndroidTest.xml
+++ b/wifi/tests/AndroidTest.xml
@@ -23,5 +23,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.net.wifi.test" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index f3a78bd..f3ffcad 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -1034,4 +1034,40 @@
verifyNoMoreInteractions(mWifiService);
}
+ /**
+ * Verify that a successful call properly returns true.
+ */
+ @Test
+ public void testSetWifiApConfigurationSuccessReturnsTrue() throws Exception {
+ WifiConfiguration apConfig = new WifiConfiguration();
+
+ when(mWifiService.setWifiApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
+ .thenReturn(true);
+ assertTrue(mWifiManager.setWifiApConfiguration(apConfig));
+ }
+
+ /**
+ * Verify that a failed call properly returns false.
+ */
+ @Test
+ public void testSetWifiApConfigurationFailureReturnsFalse() throws Exception {
+ WifiConfiguration apConfig = new WifiConfiguration();
+
+ when(mWifiService.setWifiApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
+ .thenReturn(false);
+ assertFalse(mWifiManager.setWifiApConfiguration(apConfig));
+ }
+
+ /**
+ * Verify Exceptions are rethrown when underlying calls to WifiService throw exceptions.
+ */
+ @Test
+ public void testSetWifiApConfigurationRethrowsException() throws Exception {
+ doThrow(new SecurityException()).when(mWifiService).setWifiApConfiguration(any(), any());
+
+ try {
+ mWifiManager.setWifiApConfiguration(new WifiConfiguration());
+ fail("setWifiApConfiguration should rethrow Exceptions from WifiService");
+ } catch (SecurityException e) { }
+ }
}