Merge "Add metric for anomaly detection"
diff --git a/Android.bp b/Android.bp
index 81d6dab..4f2e6d0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,6 +12,44 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// ==== c++ proto device library ==============================
+cc_library {
+ name: "libplatformprotos",
+ host_supported: true,
+ // b/34740546, work around clang-tidy segmentation fault.
+ tidy_checks: ["-modernize*"],
+ proto: {
+ export_proto_headers: true,
+ include_dirs: ["external/protobuf/src"],
+ },
+
+ target: {
+ host: {
+ proto: {
+ type: "full",
+ },
+ },
+ android: {
+ proto: {
+ type: "lite",
+ },
+ shared: {
+ // The proto files generate full protos, but we only use
+ // them as lite on device. This works fine for a static
+ // library, where the unused full symbols are stripped,
+ // but fails if it is linked as a standalone shared
+ // library because it is missing the full runtime.
+ enabled: false,
+ },
+ },
+ },
+
+ srcs: [
+ "core/proto/**/*.proto",
+ "libs/incident/**/*.proto",
+ ],
+}
+
subdirs = [
"libs/*",
"tools/*",
diff --git a/Android.mk b/Android.mk
index 6e75bea..c10a0cc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -114,6 +114,8 @@
core/java/android/app/backup/IRestoreObserver.aidl \
core/java/android/app/backup/IRestoreSession.aidl \
core/java/android/app/backup/ISelectBackupTransportCallback.aidl \
+ core/java/android/app/timezone/ICallback.aidl \
+ core/java/android/app/timezone/IRulesManager.aidl \
core/java/android/app/usage/ICacheQuotaService.aidl \
core/java/android/app/usage/IStorageStatsManager.aidl \
core/java/android/app/usage/IUsageStatsManager.aidl \
@@ -157,6 +159,7 @@
core/java/android/content/ISyncServiceAdapter.aidl \
core/java/android/content/ISyncStatusObserver.aidl \
core/java/android/content/om/IOverlayManager.aidl \
+ core/java/android/content/pm/IDexModuleRegisterCallback.aidl \
core/java/android/content/pm/ILauncherApps.aidl \
core/java/android/content/pm/IOnAppsChangedListener.aidl \
core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
@@ -1477,35 +1480,6 @@
include $(BUILD_JAVA_LIBRARY)
-# ==== c++ proto device library ==============================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libplatformprotos
-# b/34740546, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -modernize*
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-LOCAL_PROTOC_FLAGS := \
- --include_source_info \
- -Iexternal/protobuf/src
-LOCAL_SRC_FILES := \
- $(call all-proto-files-under, core/proto) \
- $(call all-proto-files-under, libs/incident/proto)
-include $(BUILD_STATIC_LIBRARY)
-
-# ==== c++ proto host library ==============================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libplatformprotos
-# b/34740546, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -modernize*
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-LOCAL_PROTOC_FLAGS := \
- --include_source_info \
- -Iexternal/protobuf/src
-LOCAL_SRC_FILES := \
- $(call all-proto-files-under, core/proto) \
- $(call all-proto-files-under, libs/incident/proto)
-include $(BUILD_HOST_SHARED_LIBRARY)
-
-
# ==== java proto host library ==============================
include $(CLEAR_VARS)
LOCAL_MODULE := platformprotos
diff --git a/api/current.txt b/api/current.txt
index 6b88cfc..0cb71a0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1061,6 +1061,7 @@
field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
field public static final int readPermission = 16842759; // 0x1010007
field public static final int recognitionService = 16843932; // 0x101049c
+ field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
field public static final int recycleEnabled = 16844124; // 0x101055c
field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
field public static final int reparent = 16843964; // 0x10104bc
@@ -1085,7 +1086,6 @@
field public static final int resizeable = 16843405; // 0x101028d
field public static final int resizeableActivity = 16844022; // 0x10104f6
field public static final int resource = 16842789; // 0x1010025
- field public static final int restartOnConfigChanges = 16844105; // 0x1010549
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int restrictedAccountType = 16843733; // 0x10103d5
@@ -3579,7 +3579,6 @@
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public deprecated void enterPictureInPictureMode();
- method public deprecated boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
method public boolean enterPictureInPictureMode(android.app.PictureInPictureParams);
method public <T extends android.view.View> T findViewById(int);
method public void finish();
@@ -3754,7 +3753,6 @@
method public void setImmersive(boolean);
method public void setIntent(android.content.Intent);
method public final void setMediaController(android.media.session.MediaController);
- method public void setPictureInPictureArgs(android.app.PictureInPictureArgs);
method public void setPictureInPictureParams(android.app.PictureInPictureParams);
method public final deprecated void setProgress(int);
method public final deprecated void setProgressBarIndeterminate(boolean);
@@ -3834,7 +3832,6 @@
method public int getLauncherLargeIconDensity();
method public int getLauncherLargeIconSize();
method public int getLockTaskModeState();
- method public static deprecated int getMaxNumPictureInPictureActions();
method public int getMemoryClass();
method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
@@ -4698,7 +4695,6 @@
public abstract class FragmentContainer {
ctor public FragmentContainer();
- method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
method public abstract <T extends android.view.View> T onFindViewById(int);
method public abstract boolean onHasView();
}
@@ -4971,7 +4967,6 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
- method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -5120,7 +5115,6 @@
method public android.app.Notification clone();
method public int describeContents();
method public int getBadgeIconType();
- method public java.lang.String getChannel();
method public java.lang.String getChannelId();
method public java.lang.String getGroup();
method public int getGroupAlertBehavior();
@@ -5129,7 +5123,6 @@
method public java.lang.String getShortcutId();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
- method public long getTimeout();
method public long getTimeoutAfter();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
@@ -5332,7 +5325,6 @@
method public android.app.Notification.Builder setAutoCancel(boolean);
method public android.app.Notification.Builder setBadgeIconType(int);
method public android.app.Notification.Builder setCategory(java.lang.String);
- method public android.app.Notification.Builder setChannel(java.lang.String);
method public android.app.Notification.Builder setChannelId(java.lang.String);
method public android.app.Notification.Builder setChronometerCountDown(boolean);
method public android.app.Notification.Builder setColor(int);
@@ -5377,7 +5369,6 @@
method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
- method public android.app.Notification.Builder setTimeout(long);
method public android.app.Notification.Builder setTimeoutAfter(long);
method public android.app.Notification.Builder setUsesChronometer(boolean);
method public deprecated android.app.Notification.Builder setVibrate(long[]);
@@ -5696,21 +5687,10 @@
method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle);
}
- public final deprecated class PictureInPictureArgs extends android.app.PictureInPictureParams {
- ctor public deprecated PictureInPictureArgs();
- ctor public deprecated PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>);
- method public deprecated void setActions(java.util.List<android.app.RemoteAction>);
- method public deprecated void setAspectRatio(float);
- method public deprecated void setSourceRectHint(android.graphics.Rect);
- }
-
- public class PictureInPictureParams implements android.os.Parcelable {
+ public final class PictureInPictureParams implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.PictureInPictureParams> CREATOR;
- field protected android.util.Rational mAspectRatio;
- field protected android.graphics.Rect mSourceRectHint;
- field protected java.util.List<android.app.RemoteAction> mUserActions;
}
public static class PictureInPictureParams.Builder {
@@ -10928,8 +10908,8 @@
field public android.content.pm.ActivityInfo activityInfo;
field public android.content.IntentFilter filter;
field public int icon;
- field public boolean instantAppAvailable;
field public boolean isDefault;
+ field public boolean isInstantAppAvailable;
field public int labelRes;
field public int match;
field public java.lang.CharSequence nonLocalizedLabel;
@@ -10966,7 +10946,7 @@
method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
method public java.lang.String getName();
method public int getType();
- method public long getVersion();
+ method public int getVersion();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
field public static final int TYPE_BUILTIN = 0; // 0x0
@@ -13853,6 +13833,7 @@
package android.graphics.drawable {
public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ ctor public AdaptiveIconDrawable(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
method public void draw(android.graphics.Canvas);
method public android.graphics.drawable.Drawable getBackground();
method public static float getExtraInsetFraction();
@@ -26564,6 +26545,7 @@
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
+ method public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, android.os.Handler);
method public boolean startScan();
method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
method public int updateNetwork(android.net.wifi.WifiConfiguration);
@@ -26614,6 +26596,22 @@
field public static final int WPS_WEP_PROHIBITED = 4; // 0x4
}
+ public static class WifiManager.LocalOnlyHotspotCallback {
+ ctor public WifiManager.LocalOnlyHotspotCallback();
+ method public void onFailed(int);
+ method public void onStarted(android.net.wifi.WifiManager.LocalOnlyHotspotReservation);
+ method public void onStopped();
+ field public static final int ERROR_GENERIC = 2; // 0x2
+ field public static final int ERROR_INCOMPATIBLE_MODE = 3; // 0x3
+ field public static final int ERROR_NO_CHANNEL = 1; // 0x1
+ field public static final int ERROR_TETHERING_DISALLOWED = 4; // 0x4
+ }
+
+ public class WifiManager.LocalOnlyHotspotReservation implements java.lang.AutoCloseable {
+ method public void close();
+ method public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ }
+
public class WifiManager.MulticastLock {
method public void acquire();
method public boolean isHeld();
@@ -26776,33 +26774,9 @@
ctor public PasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public int describeContents();
method public android.net.wifi.hotspot2.pps.Credential getCredential();
- method public int getCredentialPriority();
method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
- method public android.net.wifi.hotspot2.pps.Policy getPolicy();
- method public long getSubscriptionCreationTimeInMs();
- method public long getSubscriptionExpirationTimeInMs();
- method public java.lang.String getSubscriptionType();
- method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
- method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentifier();
- method public long getUsageLimitDataLimit();
- method public long getUsageLimitStartTimeInMs();
- method public long getUsageLimitTimeLimitInMinutes();
- method public long getUsageLimitUsageTimePeriodInMinutes();
method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
- method public void setCredentialPriority(int);
method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
- method public void setPolicy(android.net.wifi.hotspot2.pps.Policy);
- method public void setSubscriptionCreationTimeInMs(long);
- method public void setSubscriptionExpirationTimeInMs(long);
- method public void setSubscriptionType(java.lang.String);
- method public void setSubscriptionUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public void setTrustRootCertList(java.util.Map<java.lang.String, byte[]>);
- method public void setUpdateIdentifier(int);
- method public void setUsageLimitDataLimit(long);
- method public void setUsageLimitStartTimeInMs(long);
- method public void setUsageLimitTimeLimitInMinutes(long);
- method public void setUsageLimitUsageTimePeriodInMinutes(long);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
}
@@ -26825,21 +26799,15 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
- method public long getCreationTimeInMs();
- method public long getExpirationTimeInMs();
method public java.lang.String getRealm();
method public android.net.wifi.hotspot2.pps.Credential.SimCredential getSimCredential();
method public android.net.wifi.hotspot2.pps.Credential.UserCredential getUserCredential();
method public void setCaCertificate(java.security.cert.X509Certificate);
method public void setCertCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
- method public void setCheckAaaServerCertStatus(boolean);
method public void setClientCertificateChain(java.security.cert.X509Certificate[]);
method public void setClientPrivateKey(java.security.PrivateKey);
- method public void setCreationTimeInMs(long);
- method public void setExpirationTimeInMs(long);
method public void setRealm(java.lang.String);
method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
@@ -26875,19 +26843,13 @@
ctor public Credential.UserCredential();
ctor public Credential.UserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
method public int describeContents();
- method public boolean getAbleToShare();
method public int getEapType();
- method public boolean getMachineManaged();
method public java.lang.String getNonEapInnerMethod();
method public java.lang.String getPassword();
- method public java.lang.String getSoftTokenApp();
method public java.lang.String getUsername();
- method public void setAbleToShare(boolean);
method public void setEapType(int);
- method public void setMachineManaged(boolean);
method public void setNonEapInnerMethod(java.lang.String);
method public void setPassword(java.lang.String);
- method public void setSoftTokenApp(java.lang.String);
method public void setUsername(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
@@ -26899,96 +26861,14 @@
method public int describeContents();
method public java.lang.String getFqdn();
method public java.lang.String getFriendlyName();
- method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
- method public java.lang.String getIconUrl();
- method public long[] getMatchAllOis();
- method public long[] getMatchAnyOis();
- method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
method public void setFriendlyName(java.lang.String);
- method public void setHomeNetworkIds(java.util.Map<java.lang.String, java.lang.Long>);
- method public void setIconUrl(java.lang.String);
- method public void setMatchAllOis(long[]);
- method public void setMatchAnyOis(long[]);
- method public void setOtherHomePartners(java.lang.String[]);
method public void setRoamingConsortiumOis(long[]);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
}
- public final class Policy implements android.os.Parcelable {
- ctor public Policy();
- ctor public Policy(android.net.wifi.hotspot2.pps.Policy);
- method public int describeContents();
- method public java.lang.String[] getExcludedSsidList();
- method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandwidth();
- method public long getMinHomeUplinkBandwidth();
- method public long getMinRoamingDownlinkBandwidth();
- method public long getMinRoamingUplinkBandwidth();
- method public android.net.wifi.hotspot2.pps.UpdateParameter getPolicyUpdate();
- method public java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> getPreferredRoamingPartnerList();
- method public java.util.Map<java.lang.Integer, java.lang.String> getRequiredProtoPortMap();
- method public void setExcludedSsidList(java.lang.String[]);
- method public void setMaximumBssLoadValue(int);
- method public void setMinHomeDownlinkBandwidth(long);
- method public void setMinHomeUplinkBandwidth(long);
- method public void setMinRoamingDownlinkBandwidth(long);
- method public void setMinRoamingUplinkBandwidth(long);
- method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
- method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
- }
-
- public static final class Policy.RoamingPartner implements android.os.Parcelable {
- ctor public Policy.RoamingPartner();
- ctor public Policy.RoamingPartner(android.net.wifi.hotspot2.pps.Policy.RoamingPartner);
- method public int describeContents();
- method public java.lang.String getCountries();
- method public java.lang.String getFqdn();
- method public boolean getFqdnExactMatch();
- method public int getPriority();
- method public void setCountries(java.lang.String);
- method public void setFqdn(java.lang.String);
- method public void setFqdnExactMatch(boolean);
- method public void setPriority(int);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
- }
-
- public final class UpdateParameter implements android.os.Parcelable {
- ctor public UpdateParameter();
- ctor public UpdateParameter(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public int describeContents();
- method public java.lang.String getBase64EncodedPassword();
- method public java.lang.String getRestriction();
- method public java.lang.String getServerUri();
- method public byte[] getTrustRootCertSha256Fingerprint();
- method public java.lang.String getTrustRootCertUrl();
- method public long getUpdateIntervalInMinutes();
- method public java.lang.String getUpdateMethod();
- method public java.lang.String getUsername();
- method public void setBase64EncodedPassword(java.lang.String);
- method public void setRestriction(java.lang.String);
- method public void setServerUri(java.lang.String);
- method public void setTrustRootCertSha256Fingerprint(byte[]);
- method public void setTrustRootCertUrl(java.lang.String);
- method public void setUpdateIntervalInMinutes(long);
- method public void setUpdateMethod(java.lang.String);
- method public void setUsername(java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
- field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
- field public static final java.lang.String UPDATE_METHOD_OMADM = "OMA-DM-ClientInitiated";
- field public static final java.lang.String UPDATE_METHOD_SSP = "SSP-ClientInitiated";
- field public static final java.lang.String UPDATE_RESTRICTION_HOMESP = "HomeSP";
- field public static final java.lang.String UPDATE_RESTRICTION_ROAMING_PARTNER = "RoamingPartner";
- field public static final java.lang.String UPDATE_RESTRICTION_UNRESTRICTED = "Unrestricted";
- }
-
}
package android.net.wifi.p2p {
@@ -31616,7 +31496,7 @@
public class TestLooperManager {
method public void execute(android.os.Message);
- method public android.os.MessageQueue getQueue();
+ method public android.os.MessageQueue getMessageQueue();
method public boolean hasMessages(android.os.Handler, java.lang.Object, int);
method public boolean hasMessages(android.os.Handler, java.lang.Object, java.lang.Runnable);
method public android.os.Message next();
@@ -37026,7 +36906,7 @@
public final class FillRequest implements android.os.Parcelable {
method public int describeContents();
method public android.os.Bundle getClientState();
- method public java.util.ArrayList<android.service.autofill.FillContext> getFillContexts();
+ method public java.util.List<android.service.autofill.FillContext> getFillContexts();
method public int getFlags();
method public int getId();
method public void writeToParcel(android.os.Parcel, int);
@@ -38010,7 +37890,6 @@
method public void onRangeStart(java.lang.String, int, int, int);
method public abstract void onStart(java.lang.String);
method public void onStop(java.lang.String, boolean);
- method public deprecated void onUtteranceRangeStart(java.lang.String, int, int);
}
public class Voice implements android.os.Parcelable {
@@ -44100,6 +43979,7 @@
method public android.os.Vibrator getVibrator();
method public boolean[] hasKeys(int...);
method public boolean hasMicrophone();
+ method public boolean isEnabled();
method public boolean isVirtual();
method public boolean supportsSource(int);
method public void writeToParcel(android.os.Parcel, int);
@@ -47797,7 +47677,7 @@
method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
- field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.EXTRA_CLIENT_STATE";
+ field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.CLIENT_STATE";
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/removed.txt b/api/removed.txt
index 779ff7c..e7b573b 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -1,9 +1,64 @@
package android.app {
+ public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+ method public deprecated boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
+ method public deprecated void setPictureInPictureArgs(android.app.PictureInPictureArgs);
+ }
+
+ public class ActivityManager {
+ method public static deprecated int getMaxNumPictureInPictureActions();
+ }
+
+ public class KeyguardManager {
+ method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
+ }
+
public class Notification implements android.os.Parcelable {
+ method public deprecated java.lang.String getChannel();
+ method public deprecated long getTimeout();
method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
}
+ public static class Notification.Builder {
+ method public deprecated android.app.Notification.Builder setChannel(java.lang.String);
+ method public deprecated android.app.Notification.Builder setTimeout(long);
+ }
+
+ public static final class Notification.TvExtender implements android.app.Notification.Extender {
+ method public deprecated java.lang.String getChannel();
+ }
+
+ public final deprecated class PictureInPictureArgs implements android.os.Parcelable {
+ ctor public deprecated PictureInPictureArgs();
+ ctor public deprecated PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>);
+ method public static android.app.PictureInPictureArgs convert(android.app.PictureInPictureParams);
+ method public static android.app.PictureInPictureParams convert(android.app.PictureInPictureArgs);
+ method public void copyOnlySet(android.app.PictureInPictureArgs);
+ method public java.util.List<android.app.RemoteAction> getActions();
+ method public float getAspectRatio();
+ method public android.util.Rational getAspectRatioRational();
+ method public android.graphics.Rect getSourceRectHint();
+ method public android.graphics.Rect getSourceRectHintInsets();
+ method public boolean hasSetActions();
+ method public boolean hasSetAspectRatio();
+ method public boolean hasSourceBoundsHint();
+ method public boolean hasSourceBoundsHintInsets();
+ method public deprecated void setActions(java.util.List<android.app.RemoteAction>);
+ method public deprecated void setAspectRatio(float);
+ method public deprecated void setSourceRectHint(android.graphics.Rect);
+ method public deprecated void setSourceRectHintInsets(android.graphics.Rect);
+ method public void truncateActions(int);
+ field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR;
+ }
+
+ public static class PictureInPictureArgs.Builder {
+ ctor public PictureInPictureArgs.Builder();
+ method public android.app.PictureInPictureArgs build();
+ method public android.app.PictureInPictureArgs.Builder setActions(java.util.List<android.app.RemoteAction>);
+ method public android.app.PictureInPictureArgs.Builder setAspectRatio(android.util.Rational);
+ method public android.app.PictureInPictureArgs.Builder setSourceRectHint(android.graphics.Rect);
+ }
+
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
method public deprecated void showAsNotification(android.content.Context);
}
@@ -76,6 +131,10 @@
method public abstract boolean setInstantAppCookie(byte[]);
}
+ public class ResolveInfo implements android.os.Parcelable {
+ field public deprecated boolean instantAppAvailable;
+ }
+
public final class SharedLibraryInfo implements android.os.Parcelable {
method public boolean isBuiltin();
method public boolean isDynamic();
@@ -188,6 +247,26 @@
method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
}
+ public deprecated class NetworkBadging {
+ method public static android.graphics.drawable.Drawable getWifiIcon(int, int, android.content.res.Resources.Theme);
+ field public static final int BADGING_4K = 30; // 0x1e
+ field public static final int BADGING_HD = 20; // 0x14
+ field public static final int BADGING_NONE = 0; // 0x0
+ field public static final int BADGING_SD = 10; // 0xa
+ }
+
+ public abstract class NetworkRecommendationProvider {
+ ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
+ method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
+ field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
+ field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
+ }
+
+ public static deprecated class NetworkRecommendationProvider.ResultCallback {
+ ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
+ method public void onResult(android.net.RecommendationResult);
+ }
+
public abstract class PskKeyManager {
ctor public PskKeyManager();
field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -195,6 +274,37 @@
field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
}
+ public final deprecated class RecommendationRequest implements android.os.Parcelable {
+ ctor protected RecommendationRequest(android.os.Parcel);
+ method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
+ method public android.net.wifi.WifiConfiguration getConnectedConfig();
+ method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
+ method public int getLastSelectedNetworkId();
+ method public long getLastSelectedNetworkTimestamp();
+ method public android.net.wifi.ScanResult[] getScanResults();
+ method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
+ method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
+ }
+
+ public static final deprecated class RecommendationRequest.Builder {
+ ctor public RecommendationRequest.Builder();
+ method public android.net.RecommendationRequest build();
+ method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
+ method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
+ method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
+ method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
+ method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
+ }
+
+ public final deprecated class RecommendationResult implements android.os.Parcelable {
+ method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
+ method public static android.net.RecommendationResult createDoNotConnectRecommendation();
+ method public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ method public boolean hasRecommendation();
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
+ }
+
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
@@ -221,6 +331,10 @@
ctor public RecoverySystem();
}
+ public class TestLooperManager {
+ method public deprecated android.os.MessageQueue getQueue();
+ }
+
public class UserManager {
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
@@ -382,6 +496,14 @@
}
+package android.speech.tts {
+
+ public abstract class UtteranceProgressListener {
+ method public deprecated void onUtteranceRangeStart(java.lang.String, int, int);
+ }
+
+}
+
package android.test.mock {
public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/api/system-current.txt b/api/system-current.txt
index 92d76f7..738ea33 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1182,6 +1182,7 @@
field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
field public static final int readPermission = 16842759; // 0x1010007
field public static final int recognitionService = 16843932; // 0x101049c
+ field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
field public static final int recycleEnabled = 16844124; // 0x101055c
field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
field public static final int reparent = 16843964; // 0x10104bc
@@ -1208,7 +1209,6 @@
field public static final int resizeable = 16843405; // 0x101028d
field public static final int resizeableActivity = 16844022; // 0x10104f6
field public static final int resource = 16842789; // 0x1010025
- field public static final int restartOnConfigChanges = 16844105; // 0x1010549
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int restrictedAccountType = 16843733; // 0x10103d5
@@ -3712,7 +3712,6 @@
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public deprecated void enterPictureInPictureMode();
- method public deprecated boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
method public boolean enterPictureInPictureMode(android.app.PictureInPictureParams);
method public <T extends android.view.View> T findViewById(int);
method public void finish();
@@ -3890,7 +3889,6 @@
method public void setImmersive(boolean);
method public void setIntent(android.content.Intent);
method public final void setMediaController(android.media.session.MediaController);
- method public void setPictureInPictureArgs(android.app.PictureInPictureArgs);
method public void setPictureInPictureParams(android.app.PictureInPictureParams);
method public final deprecated void setProgress(int);
method public final deprecated void setProgressBarIndeterminate(boolean);
@@ -3977,7 +3975,6 @@
method public int getLauncherLargeIconDensity();
method public int getLauncherLargeIconSize();
method public int getLockTaskModeState();
- method public static deprecated int getMaxNumPictureInPictureActions();
method public int getMemoryClass();
method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
@@ -4868,7 +4865,6 @@
public abstract class FragmentContainer {
ctor public FragmentContainer();
- method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
method public abstract <T extends android.view.View> T onFindViewById(int);
method public abstract boolean onHasView();
}
@@ -5153,7 +5149,6 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
- method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -5302,7 +5297,6 @@
method public android.app.Notification clone();
method public int describeContents();
method public int getBadgeIconType();
- method public java.lang.String getChannel();
method public java.lang.String getChannelId();
method public java.lang.String getGroup();
method public int getGroupAlertBehavior();
@@ -5312,7 +5306,6 @@
method public java.lang.String getShortcutId();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
- method public long getTimeout();
method public long getTimeoutAfter();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
@@ -5518,7 +5511,6 @@
method public android.app.Notification.Builder setAutoCancel(boolean);
method public android.app.Notification.Builder setBadgeIconType(int);
method public android.app.Notification.Builder setCategory(java.lang.String);
- method public android.app.Notification.Builder setChannel(java.lang.String);
method public android.app.Notification.Builder setChannelId(java.lang.String);
method public android.app.Notification.Builder setChronometerCountDown(boolean);
method public android.app.Notification.Builder setColor(int);
@@ -5563,7 +5555,6 @@
method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
- method public android.app.Notification.Builder setTimeout(long);
method public android.app.Notification.Builder setTimeoutAfter(long);
method public android.app.Notification.Builder setUsesChronometer(boolean);
method public deprecated android.app.Notification.Builder setVibrate(long[]);
@@ -5668,7 +5659,6 @@
ctor public Notification.TvExtender();
ctor public Notification.TvExtender(android.app.Notification);
method public android.app.Notification.Builder extend(android.app.Notification.Builder);
- method public java.lang.String getChannel();
method public java.lang.String getChannelId();
method public android.app.PendingIntent getContentIntent();
method public android.app.PendingIntent getDeleteIntent();
@@ -5903,21 +5893,10 @@
method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle);
}
- public final deprecated class PictureInPictureArgs extends android.app.PictureInPictureParams {
- ctor public deprecated PictureInPictureArgs();
- ctor public deprecated PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>);
- method public deprecated void setActions(java.util.List<android.app.RemoteAction>);
- method public deprecated void setAspectRatio(float);
- method public deprecated void setSourceRectHint(android.graphics.Rect);
- }
-
- public class PictureInPictureParams implements android.os.Parcelable {
+ public final class PictureInPictureParams implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.PictureInPictureParams> CREATOR;
- field protected android.util.Rational mAspectRatio;
- field protected android.graphics.Rect mSourceRectHint;
- field protected java.util.List<android.app.RemoteAction> mUserActions;
}
public static class PictureInPictureParams.Builder {
@@ -11360,6 +11339,7 @@
method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int);
method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
method public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract void registerDexModule(java.lang.String, android.content.pm.PackageManager.DexModuleRegisterCallback);
method public abstract void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract deprecated void removePackageFromPreferred(java.lang.String);
method public abstract void removePermission(java.lang.String);
@@ -11580,6 +11560,11 @@
field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
}
+ public static abstract class PackageManager.DexModuleRegisterCallback {
+ ctor public PackageManager.DexModuleRegisterCallback();
+ method public abstract void onDexModuleRegistered(java.lang.String, boolean, java.lang.String);
+ }
+
public static class PackageManager.NameNotFoundException extends android.util.AndroidException {
ctor public PackageManager.NameNotFoundException();
ctor public PackageManager.NameNotFoundException(java.lang.String);
@@ -11696,8 +11681,8 @@
field public android.content.pm.ActivityInfo activityInfo;
field public android.content.IntentFilter filter;
field public int icon;
- field public boolean instantAppAvailable;
field public boolean isDefault;
+ field public boolean isInstantAppAvailable;
field public int labelRes;
field public int match;
field public java.lang.CharSequence nonLocalizedLabel;
@@ -11734,7 +11719,7 @@
method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
method public java.lang.String getName();
method public int getType();
- method public long getVersion();
+ method public int getVersion();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
field public static final int TYPE_BUILTIN = 0; // 0x0
@@ -14635,6 +14620,7 @@
package android.graphics.drawable {
public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ ctor public AdaptiveIconDrawable(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
method public void draw(android.graphics.Canvas);
method public android.graphics.drawable.Drawable getBackground();
method public static float getExtraInsetFraction();
@@ -27797,17 +27783,6 @@
field public static final android.os.Parcelable.Creator<android.net.Network> CREATOR;
}
- public class NetworkBadging {
- method public static android.graphics.drawable.Drawable getWifiIcon(int, int, android.content.res.Resources.Theme);
- field public static final int BADGING_4K = 30; // 0x1e
- field public static final int BADGING_HD = 20; // 0x14
- field public static final int BADGING_NONE = 0; // 0x0
- field public static final int BADGING_SD = 10; // 0xa
- }
-
- public static abstract class NetworkBadging.Badging implements java.lang.annotation.Annotation {
- }
-
public final class NetworkCapabilities implements android.os.Parcelable {
ctor public NetworkCapabilities(android.net.NetworkCapabilities);
method public int describeContents();
@@ -27902,17 +27877,9 @@
}
public abstract class NetworkRecommendationProvider {
- ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor);
method public final android.os.IBinder getBinder();
- method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
method public abstract void onRequestScores(android.net.NetworkKey[]);
- field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
- field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
- }
-
- public static deprecated class NetworkRecommendationProvider.ResultCallback {
- method public void onResult(android.net.RecommendationResult);
}
public class NetworkRequest implements android.os.Parcelable {
@@ -27978,41 +27945,6 @@
field public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
}
- public final deprecated class RecommendationRequest implements android.os.Parcelable {
- ctor protected RecommendationRequest(android.os.Parcel);
- method public int describeContents();
- method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
- method public android.net.wifi.WifiConfiguration getConnectedConfig();
- method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
- method public int getLastSelectedNetworkId();
- method public long getLastSelectedNetworkTimestamp();
- method public android.net.wifi.ScanResult[] getScanResults();
- method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
- method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
- }
-
- public static final deprecated class RecommendationRequest.Builder {
- ctor public RecommendationRequest.Builder();
- method public android.net.RecommendationRequest build();
- method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
- method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
- method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
- method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
- method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
- }
-
- public final deprecated class RecommendationResult implements android.os.Parcelable {
- method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
- method public static android.net.RecommendationResult createDoNotConnectRecommendation();
- method public int describeContents();
- method public android.net.wifi.WifiConfiguration getWifiConfiguration();
- method public boolean hasRecommendation();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
- }
-
public final class RouteInfo implements android.os.Parcelable {
method public int describeContents();
method public android.net.IpPrefix getDestination();
@@ -29147,6 +29079,7 @@
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method public boolean setWifiApEnabled(android.net.wifi.WifiConfiguration, boolean);
method public boolean setWifiEnabled(boolean);
+ method public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, android.os.Handler);
method public deprecated boolean startLocationRestrictedScan(android.os.WorkSource);
method public boolean startScan();
method public boolean startScan(android.os.WorkSource);
@@ -29224,6 +29157,22 @@
method public abstract void onSuccess();
}
+ public static class WifiManager.LocalOnlyHotspotCallback {
+ ctor public WifiManager.LocalOnlyHotspotCallback();
+ method public void onFailed(int);
+ method public void onStarted(android.net.wifi.WifiManager.LocalOnlyHotspotReservation);
+ method public void onStopped();
+ field public static final int ERROR_GENERIC = 2; // 0x2
+ field public static final int ERROR_INCOMPATIBLE_MODE = 3; // 0x3
+ field public static final int ERROR_NO_CHANNEL = 1; // 0x1
+ field public static final int ERROR_TETHERING_DISALLOWED = 4; // 0x4
+ }
+
+ public class WifiManager.LocalOnlyHotspotReservation implements java.lang.AutoCloseable {
+ method public void close();
+ method public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ }
+
public class WifiManager.MulticastLock {
method public void acquire();
method public boolean isHeld();
@@ -29528,33 +29477,9 @@
ctor public PasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public int describeContents();
method public android.net.wifi.hotspot2.pps.Credential getCredential();
- method public int getCredentialPriority();
method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
- method public android.net.wifi.hotspot2.pps.Policy getPolicy();
- method public long getSubscriptionCreationTimeInMs();
- method public long getSubscriptionExpirationTimeInMs();
- method public java.lang.String getSubscriptionType();
- method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
- method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentifier();
- method public long getUsageLimitDataLimit();
- method public long getUsageLimitStartTimeInMs();
- method public long getUsageLimitTimeLimitInMinutes();
- method public long getUsageLimitUsageTimePeriodInMinutes();
method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
- method public void setCredentialPriority(int);
method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
- method public void setPolicy(android.net.wifi.hotspot2.pps.Policy);
- method public void setSubscriptionCreationTimeInMs(long);
- method public void setSubscriptionExpirationTimeInMs(long);
- method public void setSubscriptionType(java.lang.String);
- method public void setSubscriptionUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public void setTrustRootCertList(java.util.Map<java.lang.String, byte[]>);
- method public void setUpdateIdentifier(int);
- method public void setUsageLimitDataLimit(long);
- method public void setUsageLimitStartTimeInMs(long);
- method public void setUsageLimitTimeLimitInMinutes(long);
- method public void setUsageLimitUsageTimePeriodInMinutes(long);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
}
@@ -29577,21 +29502,15 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
- method public long getCreationTimeInMs();
- method public long getExpirationTimeInMs();
method public java.lang.String getRealm();
method public android.net.wifi.hotspot2.pps.Credential.SimCredential getSimCredential();
method public android.net.wifi.hotspot2.pps.Credential.UserCredential getUserCredential();
method public void setCaCertificate(java.security.cert.X509Certificate);
method public void setCertCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
- method public void setCheckAaaServerCertStatus(boolean);
method public void setClientCertificateChain(java.security.cert.X509Certificate[]);
method public void setClientPrivateKey(java.security.PrivateKey);
- method public void setCreationTimeInMs(long);
- method public void setExpirationTimeInMs(long);
method public void setRealm(java.lang.String);
method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
@@ -29627,19 +29546,13 @@
ctor public Credential.UserCredential();
ctor public Credential.UserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
method public int describeContents();
- method public boolean getAbleToShare();
method public int getEapType();
- method public boolean getMachineManaged();
method public java.lang.String getNonEapInnerMethod();
method public java.lang.String getPassword();
- method public java.lang.String getSoftTokenApp();
method public java.lang.String getUsername();
- method public void setAbleToShare(boolean);
method public void setEapType(int);
- method public void setMachineManaged(boolean);
method public void setNonEapInnerMethod(java.lang.String);
method public void setPassword(java.lang.String);
- method public void setSoftTokenApp(java.lang.String);
method public void setUsername(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
@@ -29651,96 +29564,14 @@
method public int describeContents();
method public java.lang.String getFqdn();
method public java.lang.String getFriendlyName();
- method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
- method public java.lang.String getIconUrl();
- method public long[] getMatchAllOis();
- method public long[] getMatchAnyOis();
- method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
method public void setFriendlyName(java.lang.String);
- method public void setHomeNetworkIds(java.util.Map<java.lang.String, java.lang.Long>);
- method public void setIconUrl(java.lang.String);
- method public void setMatchAllOis(long[]);
- method public void setMatchAnyOis(long[]);
- method public void setOtherHomePartners(java.lang.String[]);
method public void setRoamingConsortiumOis(long[]);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
}
- public final class Policy implements android.os.Parcelable {
- ctor public Policy();
- ctor public Policy(android.net.wifi.hotspot2.pps.Policy);
- method public int describeContents();
- method public java.lang.String[] getExcludedSsidList();
- method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandwidth();
- method public long getMinHomeUplinkBandwidth();
- method public long getMinRoamingDownlinkBandwidth();
- method public long getMinRoamingUplinkBandwidth();
- method public android.net.wifi.hotspot2.pps.UpdateParameter getPolicyUpdate();
- method public java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> getPreferredRoamingPartnerList();
- method public java.util.Map<java.lang.Integer, java.lang.String> getRequiredProtoPortMap();
- method public void setExcludedSsidList(java.lang.String[]);
- method public void setMaximumBssLoadValue(int);
- method public void setMinHomeDownlinkBandwidth(long);
- method public void setMinHomeUplinkBandwidth(long);
- method public void setMinRoamingDownlinkBandwidth(long);
- method public void setMinRoamingUplinkBandwidth(long);
- method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
- method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
- }
-
- public static final class Policy.RoamingPartner implements android.os.Parcelable {
- ctor public Policy.RoamingPartner();
- ctor public Policy.RoamingPartner(android.net.wifi.hotspot2.pps.Policy.RoamingPartner);
- method public int describeContents();
- method public java.lang.String getCountries();
- method public java.lang.String getFqdn();
- method public boolean getFqdnExactMatch();
- method public int getPriority();
- method public void setCountries(java.lang.String);
- method public void setFqdn(java.lang.String);
- method public void setFqdnExactMatch(boolean);
- method public void setPriority(int);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
- }
-
- public final class UpdateParameter implements android.os.Parcelable {
- ctor public UpdateParameter();
- ctor public UpdateParameter(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public int describeContents();
- method public java.lang.String getBase64EncodedPassword();
- method public java.lang.String getRestriction();
- method public java.lang.String getServerUri();
- method public byte[] getTrustRootCertSha256Fingerprint();
- method public java.lang.String getTrustRootCertUrl();
- method public long getUpdateIntervalInMinutes();
- method public java.lang.String getUpdateMethod();
- method public java.lang.String getUsername();
- method public void setBase64EncodedPassword(java.lang.String);
- method public void setRestriction(java.lang.String);
- method public void setServerUri(java.lang.String);
- method public void setTrustRootCertSha256Fingerprint(byte[]);
- method public void setTrustRootCertUrl(java.lang.String);
- method public void setUpdateIntervalInMinutes(long);
- method public void setUpdateMethod(java.lang.String);
- method public void setUsername(java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
- field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
- field public static final java.lang.String UPDATE_METHOD_OMADM = "OMA-DM-ClientInitiated";
- field public static final java.lang.String UPDATE_METHOD_SSP = "SSP-ClientInitiated";
- field public static final java.lang.String UPDATE_RESTRICTION_HOMESP = "HomeSP";
- field public static final java.lang.String UPDATE_RESTRICTION_ROAMING_PARTNER = "RoamingPartner";
- field public static final java.lang.String UPDATE_RESTRICTION_UNRESTRICTED = "Unrestricted";
- }
-
}
package android.net.wifi.p2p {
@@ -34443,7 +34274,7 @@
public class TestLooperManager {
method public void execute(android.os.Message);
- method public android.os.MessageQueue getQueue();
+ method public android.os.MessageQueue getMessageQueue();
method public boolean hasMessages(android.os.Handler, java.lang.Object, int);
method public boolean hasMessages(android.os.Handler, java.lang.Object, java.lang.Runnable);
method public android.os.Message next();
@@ -40151,7 +39982,7 @@
public final class FillRequest implements android.os.Parcelable {
method public int describeContents();
method public android.os.Bundle getClientState();
- method public java.util.ArrayList<android.service.autofill.FillContext> getFillContexts();
+ method public java.util.List<android.service.autofill.FillContext> getFillContexts();
method public int getFlags();
method public int getId();
method public void writeToParcel(android.os.Parcel, int);
@@ -41278,7 +41109,6 @@
method public void onRangeStart(java.lang.String, int, int, int);
method public abstract void onStart(java.lang.String);
method public void onStop(java.lang.String, boolean);
- method public deprecated void onUtteranceRangeStart(java.lang.String, int, int);
}
public class Voice implements android.os.Parcelable {
@@ -44574,6 +44404,7 @@
method public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int);
method public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
method public java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public void registerDexModule(java.lang.String, android.content.pm.PackageManager.DexModuleRegisterCallback);
method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public void removePackageFromPreferred(java.lang.String);
method public void removePermission(java.lang.String);
@@ -47695,6 +47526,7 @@
method public android.os.Vibrator getVibrator();
method public boolean[] hasKeys(int...);
method public boolean hasMicrophone();
+ method public boolean isEnabled();
method public boolean isVirtual();
method public boolean supportsSource(int);
method public void writeToParcel(android.os.Parcel, int);
@@ -50696,6 +50528,7 @@
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
method public void interrupt();
+ method public static boolean isAccessibilityButtonSupported();
method public boolean isEnabled();
method public boolean isTouchExplorationEnabled();
method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
@@ -51395,7 +51228,7 @@
method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
- field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.EXTRA_CLIENT_STATE";
+ field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.CLIENT_STATE";
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index fe51248..15de5c4 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -1,9 +1,64 @@
package android.app {
+ public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+ method public deprecated boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
+ method public deprecated void setPictureInPictureArgs(android.app.PictureInPictureArgs);
+ }
+
+ public class ActivityManager {
+ method public static deprecated int getMaxNumPictureInPictureActions();
+ }
+
+ public class KeyguardManager {
+ method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
+ }
+
public class Notification implements android.os.Parcelable {
+ method public deprecated java.lang.String getChannel();
+ method public deprecated long getTimeout();
method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
}
+ public static class Notification.Builder {
+ method public deprecated android.app.Notification.Builder setChannel(java.lang.String);
+ method public deprecated android.app.Notification.Builder setTimeout(long);
+ }
+
+ public static final class Notification.TvExtender implements android.app.Notification.Extender {
+ method public deprecated java.lang.String getChannel();
+ }
+
+ public final deprecated class PictureInPictureArgs implements android.os.Parcelable {
+ ctor public deprecated PictureInPictureArgs();
+ ctor public deprecated PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>);
+ method public static android.app.PictureInPictureArgs convert(android.app.PictureInPictureParams);
+ method public static android.app.PictureInPictureParams convert(android.app.PictureInPictureArgs);
+ method public void copyOnlySet(android.app.PictureInPictureArgs);
+ method public java.util.List<android.app.RemoteAction> getActions();
+ method public float getAspectRatio();
+ method public android.util.Rational getAspectRatioRational();
+ method public android.graphics.Rect getSourceRectHint();
+ method public android.graphics.Rect getSourceRectHintInsets();
+ method public boolean hasSetActions();
+ method public boolean hasSetAspectRatio();
+ method public boolean hasSourceBoundsHint();
+ method public boolean hasSourceBoundsHintInsets();
+ method public deprecated void setActions(java.util.List<android.app.RemoteAction>);
+ method public deprecated void setAspectRatio(float);
+ method public deprecated void setSourceRectHint(android.graphics.Rect);
+ method public deprecated void setSourceRectHintInsets(android.graphics.Rect);
+ method public void truncateActions(int);
+ field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR;
+ }
+
+ public static class PictureInPictureArgs.Builder {
+ ctor public PictureInPictureArgs.Builder();
+ method public android.app.PictureInPictureArgs build();
+ method public android.app.PictureInPictureArgs.Builder setActions(java.util.List<android.app.RemoteAction>);
+ method public android.app.PictureInPictureArgs.Builder setAspectRatio(android.util.Rational);
+ method public android.app.PictureInPictureArgs.Builder setSourceRectHint(android.graphics.Rect);
+ }
+
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
method public deprecated void showAsNotification(android.content.Context);
}
@@ -74,6 +129,10 @@
method public abstract boolean setInstantAppCookie(byte[]);
}
+ public class ResolveInfo implements android.os.Parcelable {
+ field public deprecated boolean instantAppAvailable;
+ }
+
public final class SharedLibraryInfo implements android.os.Parcelable {
method public boolean isBuiltin();
method public boolean isDynamic();
@@ -186,6 +245,26 @@
method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
}
+ public deprecated class NetworkBadging {
+ method public static android.graphics.drawable.Drawable getWifiIcon(int, int, android.content.res.Resources.Theme);
+ field public static final int BADGING_4K = 30; // 0x1e
+ field public static final int BADGING_HD = 20; // 0x14
+ field public static final int BADGING_NONE = 0; // 0x0
+ field public static final int BADGING_SD = 10; // 0xa
+ }
+
+ public abstract class NetworkRecommendationProvider {
+ ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
+ method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
+ field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
+ field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
+ }
+
+ public static deprecated class NetworkRecommendationProvider.ResultCallback {
+ ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
+ method public void onResult(android.net.RecommendationResult);
+ }
+
public abstract class PskKeyManager {
ctor public PskKeyManager();
field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -193,6 +272,37 @@
field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
}
+ public final deprecated class RecommendationRequest implements android.os.Parcelable {
+ ctor protected RecommendationRequest(android.os.Parcel);
+ method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
+ method public android.net.wifi.WifiConfiguration getConnectedConfig();
+ method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
+ method public int getLastSelectedNetworkId();
+ method public long getLastSelectedNetworkTimestamp();
+ method public android.net.wifi.ScanResult[] getScanResults();
+ method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
+ method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
+ }
+
+ public static final deprecated class RecommendationRequest.Builder {
+ ctor public RecommendationRequest.Builder();
+ method public android.net.RecommendationRequest build();
+ method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
+ method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
+ method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
+ method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
+ method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
+ }
+
+ public final deprecated class RecommendationResult implements android.os.Parcelable {
+ method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
+ method public static android.net.RecommendationResult createDoNotConnectRecommendation();
+ method public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ method public boolean hasRecommendation();
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
+ }
+
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
@@ -215,6 +325,10 @@
ctor public RecoverySystem();
}
+ public class TestLooperManager {
+ method public deprecated android.os.MessageQueue getQueue();
+ }
+
public class UserManager {
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
@@ -376,6 +490,14 @@
}
+package android.speech.tts {
+
+ public abstract class UtteranceProgressListener {
+ method public deprecated void onUtteranceRangeStart(java.lang.String, int, int);
+ }
+
+}
+
package android.test.mock {
public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/api/test-current.txt b/api/test-current.txt
index 1a446ca..a1850f5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1061,6 +1061,7 @@
field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
field public static final int readPermission = 16842759; // 0x1010007
field public static final int recognitionService = 16843932; // 0x101049c
+ field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
field public static final int recycleEnabled = 16844124; // 0x101055c
field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
field public static final int reparent = 16843964; // 0x10104bc
@@ -1085,7 +1086,6 @@
field public static final int resizeable = 16843405; // 0x101028d
field public static final int resizeableActivity = 16844022; // 0x10104f6
field public static final int resource = 16842789; // 0x1010025
- field public static final int restartOnConfigChanges = 16844105; // 0x1010549
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int restrictedAccountType = 16843733; // 0x10103d5
@@ -3581,7 +3581,6 @@
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public deprecated void enterPictureInPictureMode();
- method public deprecated boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
method public boolean enterPictureInPictureMode(android.app.PictureInPictureParams);
method public <T extends android.view.View> T findViewById(int);
method public void finish();
@@ -3756,7 +3755,6 @@
method public void setImmersive(boolean);
method public void setIntent(android.content.Intent);
method public final void setMediaController(android.media.session.MediaController);
- method public void setPictureInPictureArgs(android.app.PictureInPictureArgs);
method public void setPictureInPictureParams(android.app.PictureInPictureParams);
method public final deprecated void setProgress(int);
method public final deprecated void setProgressBarIndeterminate(boolean);
@@ -3837,7 +3835,6 @@
method public int getLauncherLargeIconDensity();
method public int getLauncherLargeIconSize();
method public int getLockTaskModeState();
- method public static deprecated int getMaxNumPictureInPictureActions();
method public int getMemoryClass();
method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
@@ -4711,7 +4708,6 @@
public abstract class FragmentContainer {
ctor public FragmentContainer();
- method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
method public abstract <T extends android.view.View> T onFindViewById(int);
method public abstract boolean onHasView();
}
@@ -4984,7 +4980,6 @@
public class KeyguardManager {
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
- method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
method public boolean isDeviceLocked();
@@ -5133,7 +5128,6 @@
method public android.app.Notification clone();
method public int describeContents();
method public int getBadgeIconType();
- method public java.lang.String getChannel();
method public java.lang.String getChannelId();
method public java.lang.String getGroup();
method public int getGroupAlertBehavior();
@@ -5142,7 +5136,6 @@
method public java.lang.String getShortcutId();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
- method public long getTimeout();
method public long getTimeoutAfter();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
@@ -5345,7 +5338,6 @@
method public android.app.Notification.Builder setAutoCancel(boolean);
method public android.app.Notification.Builder setBadgeIconType(int);
method public android.app.Notification.Builder setCategory(java.lang.String);
- method public android.app.Notification.Builder setChannel(java.lang.String);
method public android.app.Notification.Builder setChannelId(java.lang.String);
method public android.app.Notification.Builder setChronometerCountDown(boolean);
method public android.app.Notification.Builder setColor(int);
@@ -5390,7 +5382,6 @@
method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
- method public android.app.Notification.Builder setTimeout(long);
method public android.app.Notification.Builder setTimeoutAfter(long);
method public android.app.Notification.Builder setUsesChronometer(boolean);
method public deprecated android.app.Notification.Builder setVibrate(long[]);
@@ -5710,21 +5701,10 @@
method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle);
}
- public final deprecated class PictureInPictureArgs extends android.app.PictureInPictureParams {
- ctor public deprecated PictureInPictureArgs();
- ctor public deprecated PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>);
- method public deprecated void setActions(java.util.List<android.app.RemoteAction>);
- method public deprecated void setAspectRatio(float);
- method public deprecated void setSourceRectHint(android.graphics.Rect);
- }
-
- public class PictureInPictureParams implements android.os.Parcelable {
+ public final class PictureInPictureParams implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.PictureInPictureParams> CREATOR;
- field protected android.util.Rational mAspectRatio;
- field protected android.graphics.Rect mSourceRectHint;
- field protected java.util.List<android.app.RemoteAction> mUserActions;
}
public static class PictureInPictureParams.Builder {
@@ -10969,8 +10949,8 @@
field public android.content.pm.ActivityInfo activityInfo;
field public android.content.IntentFilter filter;
field public int icon;
- field public boolean instantAppAvailable;
field public boolean isDefault;
+ field public boolean isInstantAppAvailable;
field public int labelRes;
field public int match;
field public java.lang.CharSequence nonLocalizedLabel;
@@ -11007,7 +10987,7 @@
method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
method public java.lang.String getName();
method public int getType();
- method public long getVersion();
+ method public int getVersion();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
field public static final int TYPE_BUILTIN = 0; // 0x0
@@ -13895,6 +13875,7 @@
package android.graphics.drawable {
public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ ctor public AdaptiveIconDrawable(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
method public void draw(android.graphics.Canvas);
method public android.graphics.drawable.Drawable getBackground();
method public static float getExtraInsetFraction();
@@ -13908,6 +13889,7 @@
method public void setColorFilter(android.graphics.ColorFilter);
method public void setOpacity(int);
method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+ field public static final float MASK_SIZE = 100.0f;
}
public abstract interface Animatable {
@@ -26672,6 +26654,7 @@
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
+ method public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, android.os.Handler);
method public boolean startScan();
method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
method public int updateNetwork(android.net.wifi.WifiConfiguration);
@@ -26722,6 +26705,22 @@
field public static final int WPS_WEP_PROHIBITED = 4; // 0x4
}
+ public static class WifiManager.LocalOnlyHotspotCallback {
+ ctor public WifiManager.LocalOnlyHotspotCallback();
+ method public void onFailed(int);
+ method public void onStarted(android.net.wifi.WifiManager.LocalOnlyHotspotReservation);
+ method public void onStopped();
+ field public static final int ERROR_GENERIC = 2; // 0x2
+ field public static final int ERROR_INCOMPATIBLE_MODE = 3; // 0x3
+ field public static final int ERROR_NO_CHANNEL = 1; // 0x1
+ field public static final int ERROR_TETHERING_DISALLOWED = 4; // 0x4
+ }
+
+ public class WifiManager.LocalOnlyHotspotReservation implements java.lang.AutoCloseable {
+ method public void close();
+ method public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ }
+
public class WifiManager.MulticastLock {
method public void acquire();
method public boolean isHeld();
@@ -26884,33 +26883,9 @@
ctor public PasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public int describeContents();
method public android.net.wifi.hotspot2.pps.Credential getCredential();
- method public int getCredentialPriority();
method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
- method public android.net.wifi.hotspot2.pps.Policy getPolicy();
- method public long getSubscriptionCreationTimeInMs();
- method public long getSubscriptionExpirationTimeInMs();
- method public java.lang.String getSubscriptionType();
- method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
- method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentifier();
- method public long getUsageLimitDataLimit();
- method public long getUsageLimitStartTimeInMs();
- method public long getUsageLimitTimeLimitInMinutes();
- method public long getUsageLimitUsageTimePeriodInMinutes();
method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
- method public void setCredentialPriority(int);
method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
- method public void setPolicy(android.net.wifi.hotspot2.pps.Policy);
- method public void setSubscriptionCreationTimeInMs(long);
- method public void setSubscriptionExpirationTimeInMs(long);
- method public void setSubscriptionType(java.lang.String);
- method public void setSubscriptionUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public void setTrustRootCertList(java.util.Map<java.lang.String, byte[]>);
- method public void setUpdateIdentifier(int);
- method public void setUsageLimitDataLimit(long);
- method public void setUsageLimitStartTimeInMs(long);
- method public void setUsageLimitTimeLimitInMinutes(long);
- method public void setUsageLimitUsageTimePeriodInMinutes(long);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
}
@@ -26933,21 +26908,15 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
- method public long getCreationTimeInMs();
- method public long getExpirationTimeInMs();
method public java.lang.String getRealm();
method public android.net.wifi.hotspot2.pps.Credential.SimCredential getSimCredential();
method public android.net.wifi.hotspot2.pps.Credential.UserCredential getUserCredential();
method public void setCaCertificate(java.security.cert.X509Certificate);
method public void setCertCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
- method public void setCheckAaaServerCertStatus(boolean);
method public void setClientCertificateChain(java.security.cert.X509Certificate[]);
method public void setClientPrivateKey(java.security.PrivateKey);
- method public void setCreationTimeInMs(long);
- method public void setExpirationTimeInMs(long);
method public void setRealm(java.lang.String);
method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
@@ -26983,19 +26952,13 @@
ctor public Credential.UserCredential();
ctor public Credential.UserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
method public int describeContents();
- method public boolean getAbleToShare();
method public int getEapType();
- method public boolean getMachineManaged();
method public java.lang.String getNonEapInnerMethod();
method public java.lang.String getPassword();
- method public java.lang.String getSoftTokenApp();
method public java.lang.String getUsername();
- method public void setAbleToShare(boolean);
method public void setEapType(int);
- method public void setMachineManaged(boolean);
method public void setNonEapInnerMethod(java.lang.String);
method public void setPassword(java.lang.String);
- method public void setSoftTokenApp(java.lang.String);
method public void setUsername(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
@@ -27007,96 +26970,14 @@
method public int describeContents();
method public java.lang.String getFqdn();
method public java.lang.String getFriendlyName();
- method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
- method public java.lang.String getIconUrl();
- method public long[] getMatchAllOis();
- method public long[] getMatchAnyOis();
- method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
method public void setFriendlyName(java.lang.String);
- method public void setHomeNetworkIds(java.util.Map<java.lang.String, java.lang.Long>);
- method public void setIconUrl(java.lang.String);
- method public void setMatchAllOis(long[]);
- method public void setMatchAnyOis(long[]);
- method public void setOtherHomePartners(java.lang.String[]);
method public void setRoamingConsortiumOis(long[]);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
}
- public final class Policy implements android.os.Parcelable {
- ctor public Policy();
- ctor public Policy(android.net.wifi.hotspot2.pps.Policy);
- method public int describeContents();
- method public java.lang.String[] getExcludedSsidList();
- method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandwidth();
- method public long getMinHomeUplinkBandwidth();
- method public long getMinRoamingDownlinkBandwidth();
- method public long getMinRoamingUplinkBandwidth();
- method public android.net.wifi.hotspot2.pps.UpdateParameter getPolicyUpdate();
- method public java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> getPreferredRoamingPartnerList();
- method public java.util.Map<java.lang.Integer, java.lang.String> getRequiredProtoPortMap();
- method public void setExcludedSsidList(java.lang.String[]);
- method public void setMaximumBssLoadValue(int);
- method public void setMinHomeDownlinkBandwidth(long);
- method public void setMinHomeUplinkBandwidth(long);
- method public void setMinRoamingDownlinkBandwidth(long);
- method public void setMinRoamingUplinkBandwidth(long);
- method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
- method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
- }
-
- public static final class Policy.RoamingPartner implements android.os.Parcelable {
- ctor public Policy.RoamingPartner();
- ctor public Policy.RoamingPartner(android.net.wifi.hotspot2.pps.Policy.RoamingPartner);
- method public int describeContents();
- method public java.lang.String getCountries();
- method public java.lang.String getFqdn();
- method public boolean getFqdnExactMatch();
- method public int getPriority();
- method public void setCountries(java.lang.String);
- method public void setFqdn(java.lang.String);
- method public void setFqdnExactMatch(boolean);
- method public void setPriority(int);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
- }
-
- public final class UpdateParameter implements android.os.Parcelable {
- ctor public UpdateParameter();
- ctor public UpdateParameter(android.net.wifi.hotspot2.pps.UpdateParameter);
- method public int describeContents();
- method public java.lang.String getBase64EncodedPassword();
- method public java.lang.String getRestriction();
- method public java.lang.String getServerUri();
- method public byte[] getTrustRootCertSha256Fingerprint();
- method public java.lang.String getTrustRootCertUrl();
- method public long getUpdateIntervalInMinutes();
- method public java.lang.String getUpdateMethod();
- method public java.lang.String getUsername();
- method public void setBase64EncodedPassword(java.lang.String);
- method public void setRestriction(java.lang.String);
- method public void setServerUri(java.lang.String);
- method public void setTrustRootCertSha256Fingerprint(byte[]);
- method public void setTrustRootCertUrl(java.lang.String);
- method public void setUpdateIntervalInMinutes(long);
- method public void setUpdateMethod(java.lang.String);
- method public void setUsername(java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
- field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
- field public static final java.lang.String UPDATE_METHOD_OMADM = "OMA-DM-ClientInitiated";
- field public static final java.lang.String UPDATE_METHOD_SSP = "SSP-ClientInitiated";
- field public static final java.lang.String UPDATE_RESTRICTION_HOMESP = "HomeSP";
- field public static final java.lang.String UPDATE_RESTRICTION_ROAMING_PARTNER = "RoamingPartner";
- field public static final java.lang.String UPDATE_RESTRICTION_UNRESTRICTED = "Unrestricted";
- }
-
}
package android.net.wifi.p2p {
@@ -31746,7 +31627,7 @@
public class TestLooperManager {
method public void execute(android.os.Message);
- method public android.os.MessageQueue getQueue();
+ method public android.os.MessageQueue getMessageQueue();
method public boolean hasMessages(android.os.Handler, java.lang.Object, int);
method public boolean hasMessages(android.os.Handler, java.lang.Object, java.lang.Runnable);
method public android.os.Message next();
@@ -37180,7 +37061,7 @@
public final class FillRequest implements android.os.Parcelable {
method public int describeContents();
method public android.os.Bundle getClientState();
- method public java.util.ArrayList<android.service.autofill.FillContext> getFillContexts();
+ method public java.util.List<android.service.autofill.FillContext> getFillContexts();
method public int getFlags();
method public int getId();
method public void writeToParcel(android.os.Parcel, int);
@@ -38205,7 +38086,6 @@
method public void onRangeStart(java.lang.String, int, int, int);
method public abstract void onStart(java.lang.String);
method public void onStop(java.lang.String, boolean);
- method public deprecated void onUtteranceRangeStart(java.lang.String, int, int);
}
public class Voice implements android.os.Parcelable {
@@ -44464,6 +44344,8 @@
public final class InputDevice implements android.os.Parcelable {
method public int describeContents();
+ method public void disable();
+ method public void enable();
method public int getControllerNumber();
method public java.lang.String getDescriptor();
method public static android.view.InputDevice getDevice(int);
@@ -44481,6 +44363,7 @@
method public android.os.Vibrator getVibrator();
method public boolean[] hasKeys(int...);
method public boolean hasMicrophone();
+ method public boolean isEnabled();
method public boolean isVirtual();
method public boolean supportsSource(int);
method public void writeToParcel(android.os.Parcel, int);
@@ -48192,7 +48075,7 @@
method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
- field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.EXTRA_CLIENT_STATE";
+ field public static final java.lang.String EXTRA_CLIENT_STATE = "android.view.autofill.extra.CLIENT_STATE";
}
public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 779ff7c..e7b573b 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -1,9 +1,64 @@
package android.app {
+ public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+ method public deprecated boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
+ method public deprecated void setPictureInPictureArgs(android.app.PictureInPictureArgs);
+ }
+
+ public class ActivityManager {
+ method public static deprecated int getMaxNumPictureInPictureActions();
+ }
+
+ public class KeyguardManager {
+ method public deprecated void dismissKeyguard(android.app.Activity, android.app.KeyguardManager.KeyguardDismissCallback, android.os.Handler);
+ }
+
public class Notification implements android.os.Parcelable {
+ method public deprecated java.lang.String getChannel();
+ method public deprecated long getTimeout();
method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
}
+ public static class Notification.Builder {
+ method public deprecated android.app.Notification.Builder setChannel(java.lang.String);
+ method public deprecated android.app.Notification.Builder setTimeout(long);
+ }
+
+ public static final class Notification.TvExtender implements android.app.Notification.Extender {
+ method public deprecated java.lang.String getChannel();
+ }
+
+ public final deprecated class PictureInPictureArgs implements android.os.Parcelable {
+ ctor public deprecated PictureInPictureArgs();
+ ctor public deprecated PictureInPictureArgs(float, java.util.List<android.app.RemoteAction>);
+ method public static android.app.PictureInPictureArgs convert(android.app.PictureInPictureParams);
+ method public static android.app.PictureInPictureParams convert(android.app.PictureInPictureArgs);
+ method public void copyOnlySet(android.app.PictureInPictureArgs);
+ method public java.util.List<android.app.RemoteAction> getActions();
+ method public float getAspectRatio();
+ method public android.util.Rational getAspectRatioRational();
+ method public android.graphics.Rect getSourceRectHint();
+ method public android.graphics.Rect getSourceRectHintInsets();
+ method public boolean hasSetActions();
+ method public boolean hasSetAspectRatio();
+ method public boolean hasSourceBoundsHint();
+ method public boolean hasSourceBoundsHintInsets();
+ method public deprecated void setActions(java.util.List<android.app.RemoteAction>);
+ method public deprecated void setAspectRatio(float);
+ method public deprecated void setSourceRectHint(android.graphics.Rect);
+ method public deprecated void setSourceRectHintInsets(android.graphics.Rect);
+ method public void truncateActions(int);
+ field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR;
+ }
+
+ public static class PictureInPictureArgs.Builder {
+ ctor public PictureInPictureArgs.Builder();
+ method public android.app.PictureInPictureArgs build();
+ method public android.app.PictureInPictureArgs.Builder setActions(java.util.List<android.app.RemoteAction>);
+ method public android.app.PictureInPictureArgs.Builder setAspectRatio(android.util.Rational);
+ method public android.app.PictureInPictureArgs.Builder setSourceRectHint(android.graphics.Rect);
+ }
+
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
method public deprecated void showAsNotification(android.content.Context);
}
@@ -76,6 +131,10 @@
method public abstract boolean setInstantAppCookie(byte[]);
}
+ public class ResolveInfo implements android.os.Parcelable {
+ field public deprecated boolean instantAppAvailable;
+ }
+
public final class SharedLibraryInfo implements android.os.Parcelable {
method public boolean isBuiltin();
method public boolean isDynamic();
@@ -188,6 +247,26 @@
method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
}
+ public deprecated class NetworkBadging {
+ method public static android.graphics.drawable.Drawable getWifiIcon(int, int, android.content.res.Resources.Theme);
+ field public static final int BADGING_4K = 30; // 0x1e
+ field public static final int BADGING_HD = 20; // 0x14
+ field public static final int BADGING_NONE = 0; // 0x0
+ field public static final int BADGING_SD = 10; // 0xa
+ }
+
+ public abstract class NetworkRecommendationProvider {
+ ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
+ method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
+ field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
+ field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
+ }
+
+ public static deprecated class NetworkRecommendationProvider.ResultCallback {
+ ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
+ method public void onResult(android.net.RecommendationResult);
+ }
+
public abstract class PskKeyManager {
ctor public PskKeyManager();
field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -195,6 +274,37 @@
field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
}
+ public final deprecated class RecommendationRequest implements android.os.Parcelable {
+ ctor protected RecommendationRequest(android.os.Parcel);
+ method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
+ method public android.net.wifi.WifiConfiguration getConnectedConfig();
+ method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
+ method public int getLastSelectedNetworkId();
+ method public long getLastSelectedNetworkTimestamp();
+ method public android.net.wifi.ScanResult[] getScanResults();
+ method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
+ method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
+ }
+
+ public static final deprecated class RecommendationRequest.Builder {
+ ctor public RecommendationRequest.Builder();
+ method public android.net.RecommendationRequest build();
+ method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
+ method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
+ method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
+ method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
+ method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
+ }
+
+ public final deprecated class RecommendationResult implements android.os.Parcelable {
+ method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
+ method public static android.net.RecommendationResult createDoNotConnectRecommendation();
+ method public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ method public boolean hasRecommendation();
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
+ }
+
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
@@ -221,6 +331,10 @@
ctor public RecoverySystem();
}
+ public class TestLooperManager {
+ method public deprecated android.os.MessageQueue getQueue();
+ }
+
public class UserManager {
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
@@ -382,6 +496,14 @@
}
+package android.speech.tts {
+
+ public abstract class UtteranceProgressListener {
+ method public deprecated void onUtteranceRangeStart(java.lang.String, int, int);
+ }
+
+}
+
package android.test.mock {
public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/cmds/vr/src/com/android/commands/vr/Vr.java b/cmds/vr/src/com/android/commands/vr/Vr.java
index bf97bba..b765866 100644
--- a/cmds/vr/src/com/android/commands/vr/Vr.java
+++ b/cmds/vr/src/com/android/commands/vr/Vr.java
@@ -16,7 +16,7 @@
package com.android.commands.vr;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -39,7 +39,7 @@
private static final String COMMAND_SET_PERSISTENT_VR_MODE_ENABLED =
"set-persistent-vr-mode-enabled";
- private static final String COMMAND_SET_COMPATIBILITY_DISPLAY_PROPERTIES =
+ private static final String COMMAND_SET_VR2D_DISPLAY_PROPERTIES =
"set-display-props";
private IVrManager mVrService;
@@ -63,8 +63,8 @@
String command = nextArgRequired();
switch (command) {
- case COMMAND_SET_COMPATIBILITY_DISPLAY_PROPERTIES:
- runSetCompatibilityDisplayProperties();
+ case COMMAND_SET_VR2D_DISPLAY_PROPERTIES:
+ runSetVr2dDisplayProperties();
break;
case COMMAND_SET_PERSISTENT_VR_MODE_ENABLED:
runSetPersistentVrModeEnabled();
@@ -74,7 +74,7 @@
}
}
- private void runSetCompatibilityDisplayProperties() throws RemoteException {
+ private void runSetVr2dDisplayProperties() throws RemoteException {
String widthStr = nextArgRequired();
int width = Integer.parseInt(widthStr);
@@ -84,11 +84,11 @@
String dpiStr = nextArgRequired();
int dpi = Integer.parseInt(dpiStr);
- CompatibilityDisplayProperties compatDisplayProperties =
- new CompatibilityDisplayProperties(width, height, dpi);
+ Vr2dDisplayProperties vr2dDisplayProperties =
+ new Vr2dDisplayProperties(width, height, dpi);
try {
- mVrService.setCompatibilityDisplayProperties(compatDisplayProperties);
+ mVrService.setVr2dDisplayProperties(vr2dDisplayProperties);
} catch (RemoteException re) {
System.err.println("Error: Can't set persistent mode " + re);
}
diff --git a/core/java/android/accessibilityservice/AccessibilityButtonController.java b/core/java/android/accessibilityservice/AccessibilityButtonController.java
index ee19768..a70085c 100644
--- a/core/java/android/accessibilityservice/AccessibilityButtonController.java
+++ b/core/java/android/accessibilityservice/AccessibilityButtonController.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Handler;
+import android.os.Looper;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Slog;
@@ -91,7 +92,7 @@
* @param callback the callback to add, must be non-null
*/
public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback) {
- registerAccessibilityButtonCallback(callback, new Handler());
+ registerAccessibilityButtonCallback(callback, new Handler(Looper.getMainLooper()));
}
/**
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ab4f33d..4f6c0c9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2050,20 +2050,10 @@
enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
}
- /**
- * TO BE REMOVED
- */
+ /** @removed */
@Deprecated
public boolean enterPictureInPictureMode(@NonNull PictureInPictureArgs args) {
- try {
- if (args == null) {
- throw new IllegalArgumentException("Expected non-null picture-in-picture args");
- }
- updatePictureInPictureParamsForContentInsets(args);
- return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, args);
- } catch (RemoteException e) {
- return false;
- }
+ return enterPictureInPictureMode(PictureInPictureArgs.convert(args));
}
/**
@@ -2095,11 +2085,10 @@
}
}
- /**
- * TO BE REMOVED
- */
+ /** @removed */
+ @Deprecated
public void setPictureInPictureArgs(@NonNull PictureInPictureArgs args) {
- setPictureInPictureParams(args);
+ setPictureInPictureParams(PictureInPictureArgs.convert(args));
}
/**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 66d221a..4c3e1b0 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1143,13 +1143,7 @@
com.android.internal.R.bool.config_supportsSplitScreenMultiWindow);
}
- /**
- * Return the number of actions that will be displayed in the picture-in-picture UI when the
- * user interacts with the activity currently in picture-in-picture mode. This number may change
- * if the global configuration changes (ie. if the device is plugged into an external display).
- *
- * TO BE REMOVED
- */
+ /** @removed */
@Deprecated
public static int getMaxNumPictureInPictureActions() {
return 3;
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 65cb5f4..0dfaf6a 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -244,8 +244,8 @@
/**
* Called after virtual display Id is updated by
- * {@link com.android.server.vr.CompatibilityDisplay} with a specific
- * {@param compatibilityDisplayId}.
+ * {@link com.android.server.vr.Vr2dDisplay} with a specific
+ * {@param vr2dDisplayId}.
*/
- public abstract void setVrCompatibilityDisplayId(int vrCompatibilityDisplayId);
+ public abstract void setVr2dDisplayId(int vr2dDisplayId);
}
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 3221c5d..620e5cf 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -226,11 +226,7 @@
@Override
public void doAlarm(IAlarmCompleteListener alarmManager) {
mCompletion = alarmManager;
- mHandler.post(this);
- }
- @Override
- public void run() {
// Remove this listener from the wrapper cache first; the server side
// already considers it gone
synchronized (AlarmManager.class) {
@@ -239,6 +235,11 @@
}
}
+ mHandler.post(this);
+ }
+
+ @Override
+ public void run() {
// Now deliver it to the app
try {
mListener.onAlarm();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index e50c307..f6aea96 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -78,6 +78,10 @@
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructStat;
import android.util.ArrayMap;
import android.util.IconDrawableFactory;
import android.util.LauncherIcons;
@@ -2662,4 +2666,78 @@
throw e.rethrowAsRuntimeException();
}
}
+
+ private static class DexModuleRegisterResult {
+ final String dexModulePath;
+ final boolean success;
+ final String message;
+
+ private DexModuleRegisterResult(String dexModulePath, boolean success, String message) {
+ this.dexModulePath = dexModulePath;
+ this.success = success;
+ this.message = message;
+ }
+ }
+
+ private static class DexModuleRegisterCallbackDelegate
+ extends android.content.pm.IDexModuleRegisterCallback.Stub
+ implements Handler.Callback {
+ private static final int MSG_DEX_MODULE_REGISTERED = 1;
+ private final DexModuleRegisterCallback callback;
+ private final Handler mHandler;
+
+ DexModuleRegisterCallbackDelegate(@NonNull DexModuleRegisterCallback callback) {
+ this.callback = callback;
+ mHandler = new Handler(Looper.getMainLooper(), this);
+ }
+
+ @Override
+ public void onDexModuleRegistered(@NonNull String dexModulePath, boolean success,
+ @Nullable String message)throws RemoteException {
+ mHandler.obtainMessage(MSG_DEX_MODULE_REGISTERED,
+ new DexModuleRegisterResult(dexModulePath, success, message)).sendToTarget();
+ }
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ if (msg.what != MSG_DEX_MODULE_REGISTERED) {
+ return false;
+ }
+ DexModuleRegisterResult result = (DexModuleRegisterResult)msg.obj;
+ callback.onDexModuleRegistered(result.dexModulePath, result.success, result.message);
+ return true;
+ }
+ }
+
+ @Override
+ public void registerDexModule(@NonNull String dexModule,
+ @Nullable DexModuleRegisterCallback callback) {
+ // Check if this is a shared module by looking if the others can read it.
+ boolean isSharedModule = false;
+ try {
+ StructStat stat = Os.stat(dexModule);
+ if ((OsConstants.S_IROTH & stat.st_mode) != 0) {
+ isSharedModule = true;
+ }
+ } catch (ErrnoException e) {
+ callback.onDexModuleRegistered(dexModule, false,
+ "Could not get stat the module file: " + e.getMessage());
+ return;
+ }
+
+ // Module path is ok.
+ // Create the callback delegate to be passed to package manager service.
+ DexModuleRegisterCallbackDelegate callbackDelegate = null;
+ if (callback != null) {
+ callbackDelegate = new DexModuleRegisterCallbackDelegate(callback);
+ }
+
+ // Invoke the package manager service.
+ try {
+ mPM.registerDexModule(mContext.getPackageName(), dexModule,
+ isSharedModule, callbackDelegate);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
}
diff --git a/core/java/android/app/AuthenticationRequiredException.java b/core/java/android/app/AuthenticationRequiredException.java
index 8960979..04e5e0a 100644
--- a/core/java/android/app/AuthenticationRequiredException.java
+++ b/core/java/android/app/AuthenticationRequiredException.java
@@ -56,10 +56,7 @@
* {@link Activity#setResult(int)} before finishing to
* communicate the final status of the recovery. For example,
* apps that observe {@link Activity#RESULT_OK} may choose to
- * immediately retry their operation. If this exception was
- * thrown from a {@link ContentProvider}, you should also send
- * any relevant {@link ContentResolver#notifyChange} events to
- * trigger reloading of data.
+ * immediately retry their operation.
*/
public AuthenticationRequiredException(Throwable cause, PendingIntent userAction) {
super(cause.getMessage());
diff --git a/core/java/android/app/FragmentContainer.java b/core/java/android/app/FragmentContainer.java
index 77c9c31..f8836bc8 100644
--- a/core/java/android/app/FragmentContainer.java
+++ b/core/java/android/app/FragmentContainer.java
@@ -42,6 +42,8 @@
* Creates an instance of the specified fragment, can be overridden to construct fragments
* with dependencies, or change the fragment being constructed. By default just calls
* {@link Fragment#instantiate(Context, String, Bundle)}.
+ *
+ * @hide
*/
public Fragment instantiate(Context context, String className, Bundle arguments) {
return Fragment.instantiate(context, className, arguments);
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index f369955..4994fbb 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -39,8 +39,11 @@
* Called whenever IActivityManager.startActivity is called on an activity that is already
* running in the pinned stack and the activity is not actually started, but the task is either
* brought to the front or a new Intent is delivered to it.
+ *
+ * @param clearedTask whether or not the launch activity also cleared the task as a part of
+ * starting
*/
- void onPinnedActivityRestartAttempt();
+ void onPinnedActivityRestartAttempt(boolean clearedTask);
/**
* Called whenever the pinned stack is starting animating a resize.
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 4de6e44..fcf0aab 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -362,28 +362,7 @@
}
}
- /**
- * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to
- * be dismissed.
- * <p>
- * If the Keyguard is not secure or the device is currently in a trusted state, calling this
- * method will immediately dismiss the Keyguard without any user interaction.
- * <p>
- * If the Keyguard is secure and the device is not in a trusted state, this will bring up the
- * UI so the user can enter their credentials.
- *
- * @param activity The activity requesting the dismissal. The activity must be either visible
- * by using {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} or must be in a state in
- * which it would be visible if Keyguard would not be hiding it. If that's not
- * the case, the request will fail immediately and
- * {@link KeyguardDismissCallback#onDismissError} will be invoked.
- * @param callback The callback to be called if the request to dismiss Keyguard was successful
- * or {@code null} if the caller isn't interested in knowing the result.
- * @param handler The handler to invoke the callback on, or {@code null} to use the main
- * handler.
- *
- * TO BE REMOVED
- */
+ /** @removed */
@Deprecated
public void dismissKeyguard(@NonNull Activity activity,
@Nullable KeyguardDismissCallback callback, @Nullable Handler handler) {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 3de5245..3d7d687 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1221,6 +1221,7 @@
private Intent mCurIntent;
private final boolean mOrdered;
private boolean mDispatched;
+ private Throwable mPreviousRunStacktrace; // To investigate b/37809561. STOPSHIP remove.
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, int sendingUser) {
@@ -1246,11 +1247,14 @@
final IActivityManager mgr = ActivityManager.getService();
final Intent intent = mCurIntent;
if (intent == null) {
- Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
+ Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
+ + ": run() previously called at "
+ + Log.getStackTraceString(mPreviousRunStacktrace));
}
mCurIntent = null;
mDispatched = true;
+ mPreviousRunStacktrace = new Throwable("Previous stacktrace");
if (receiver == null || intent == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 28fe319..2e56bcf 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2494,9 +2494,8 @@
}
}
- /**
- * Returns the id of the channel this notification posts to.
- */
+ /** @removed */
+ @Deprecated
public String getChannel() {
return mChannelId;
}
@@ -2508,10 +2507,8 @@
return mChannelId;
}
- /**
- * Returns the time at which this notification should be canceled by the system, if it's not
- * canceled already.
- */
+ /** @removed */
+ @Deprecated
public long getTimeout() {
return mTimeout;
}
@@ -2811,9 +2808,8 @@
return this;
}
- /**
- * Specifies the channel the notification should be delivered on.
- */
+ /** @removed */
+ @Deprecated
public Builder setChannel(String channelId) {
mN.mChannelId = channelId;
return this;
@@ -2827,10 +2823,8 @@
return this;
}
- /**
- * Specifies a duration in milliseconds after which this notification should be canceled,
- * if it is not already canceled.
- */
+ /** @removed */
+ @Deprecated
public Builder setTimeout(long durationMs) {
mN.mTimeout = durationMs;
return this;
@@ -4364,6 +4358,8 @@
mN.mLargeIcon = null;
Bitmap largeIconLegacy = mN.largeIcon;
mN.largeIcon = null;
+ ArrayList<Action> actions = mActions;
+ mActions = new ArrayList<>();
Bundle publicExtras = new Bundle();
publicExtras.putBoolean(EXTRA_SHOW_WHEN,
savedBundle.getBoolean(EXTRA_SHOW_WHEN));
@@ -4379,6 +4375,7 @@
mN.extras = savedBundle;
mN.mLargeIcon = largeIcon;
mN.largeIcon = largeIconLegacy;
+ mActions = actions;
mStyle = style;
return view;
}
@@ -8040,9 +8037,8 @@
return this;
}
- /**
- * Returns the id of the channel this notification posts to on TV.
- */
+ /** @removed */
+ @Deprecated
public String getChannel() {
return mChannelId;
}
diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java
index 63db86a..d7317f4 100644
--- a/core/java/android/app/PictureInPictureArgs.java
+++ b/core/java/android/app/PictureInPictureArgs.java
@@ -16,49 +16,164 @@
package android.app;
+import android.annotation.Nullable;
import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.Rational;
import java.util.ArrayList;
import java.util.List;
-/**
- * TO BE REMOVED
- */
+/** @removed */
@Deprecated
-public final class PictureInPictureArgs extends PictureInPictureParams {
+public final class PictureInPictureArgs implements Parcelable {
/**
- * Creates a new set of picture-in-picture arguments.
- *
- * TODO: Remove once we remove PictureInPictureArgs.
+ * Builder class for {@link PictureInPictureArgs} objects.
*/
- @Deprecated
- public PictureInPictureArgs() {
- // Empty constructor
- }
+ public static class Builder {
- /**
- * Creates a new set of picture-in-picture arguments from the given {@param aspectRatio} and
- * {@param actions}.
- *
- * TODO: Remove once we remove PictureInPictureArgs.
- */
- @Deprecated
- public PictureInPictureArgs(float aspectRatio, List<RemoteAction> actions) {
- setAspectRatio(aspectRatio);
- if (actions != null) {
- setActions(actions);
+ @Nullable
+ private Rational mAspectRatio;
+
+ @Nullable
+ private List<RemoteAction> mUserActions;
+
+ @Nullable
+ private Rect mSourceRectHint;
+
+ /**
+ * Sets the aspect ratio. This aspect ratio is defined as the desired width / height, and
+ * does not change upon device rotation.
+ *
+ * @param aspectRatio the new aspect ratio for the activity in picture-in-picture, must be
+ * between 2.39:1 and 1:2.39 (inclusive).
+ *
+ * @return this builder instance.
+ */
+ public Builder setAspectRatio(Rational aspectRatio) {
+ mAspectRatio = aspectRatio;
+ return this;
+ }
+
+ /**
+ * Sets the user actions. If there are more than
+ * {@link Activity#getMaxNumPictureInPictureActions()} actions, then the input list
+ * will be truncated to that number.
+ *
+ * @param actions the new actions to show in the picture-in-picture menu.
+ *
+ * @return this builder instance.
+ *
+ * @see RemoteAction
+ */
+ public Builder setActions(List<RemoteAction> actions) {
+ if (mUserActions != null) {
+ mUserActions = null;
+ }
+ if (actions != null) {
+ mUserActions = new ArrayList<>(actions);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the source bounds hint. These bounds are only used when an activity first enters
+ * picture-in-picture, and describe the bounds in window coordinates of activity entering
+ * picture-in-picture that will be visible following the transition. For the best effect,
+ * these bounds should also match the aspect ratio in the arguments.
+ *
+ * @param launchBounds window-coordinate bounds indicating the area of the activity that
+ * will still be visible following the transition into picture-in-picture (eg. the video
+ * view bounds in a video player)
+ *
+ * @return this builder instance.
+ */
+ public Builder setSourceRectHint(Rect launchBounds) {
+ if (launchBounds == null) {
+ mSourceRectHint = null;
+ } else {
+ mSourceRectHint = new Rect(launchBounds);
+ }
+ return this;
+ }
+
+ public PictureInPictureArgs build() {
+ PictureInPictureArgs args = new PictureInPictureArgs(mAspectRatio, mUserActions,
+ mSourceRectHint);
+ return args;
}
}
/**
- * Sets the aspect ratio.
- *
- * @param aspectRatio the new aspect ratio for picture-in-picture, must be within 2.39:1 and
- * 1:2.39.
- *
- * TODO: Remove once we remove PictureInPictureArgs.
+ * The expected aspect ratio of the picture-in-picture.
+ */
+ @Nullable
+ private Rational mAspectRatio;
+
+ /**
+ * The set of actions that are associated with this activity when in picture-in-picture.
+ */
+ @Nullable
+ private List<RemoteAction> mUserActions;
+
+ /**
+ * The source bounds hint used when entering picture-in-picture, relative to the window bounds.
+ * We can use this internally for the transition into picture-in-picture to ensure that a
+ * particular source rect is visible throughout the whole transition.
+ */
+ @Nullable
+ private Rect mSourceRectHint;
+
+ /**
+ * The content insets that are used with the source hint rect for the transition into PiP where
+ * the insets are removed at the beginning of the transition.
+ */
+ @Nullable
+ private Rect mSourceRectHintInsets;
+
+ /**
+ * @hide
+ */
+ @Deprecated
+ public PictureInPictureArgs() {
+ }
+
+ /**
+ * @hide
+ */
+ @Deprecated
+ public PictureInPictureArgs(float aspectRatio, List<RemoteAction> actions) {
+ setAspectRatio(aspectRatio);
+ setActions(actions);
+ }
+
+ private PictureInPictureArgs(Parcel in) {
+ if (in.readInt() != 0) {
+ mAspectRatio = new Rational(in.readInt(), in.readInt());
+ }
+ if (in.readInt() != 0) {
+ mUserActions = new ArrayList<>();
+ in.readParcelableList(mUserActions, RemoteAction.class.getClassLoader());
+ }
+ if (in.readInt() != 0) {
+ mSourceRectHint = Rect.CREATOR.createFromParcel(in);
+ }
+ if (in.readInt() != 0) {
+ mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in);
+ }
+ }
+
+ private PictureInPictureArgs(Rational aspectRatio, List<RemoteAction> actions,
+ Rect sourceRectHint) {
+ mAspectRatio = aspectRatio;
+ mUserActions = actions;
+ mSourceRectHint = sourceRectHint;
+ }
+
+ /**
+ * @hide
*/
@Deprecated
public void setAspectRatio(float aspectRatio) {
@@ -67,15 +182,7 @@
}
/**
- * Sets the user actions. If there are more than
- * {@link ActivityManager#getMaxNumPictureInPictureActions()} actions, then the input will be
- * truncated to that number.
- *
- * @param actions the new actions to show in the picture-in-picture menu.
- *
- * @see RemoteAction
- *
- * TODO: Remove once we remove PictureInPictureArgs.
+ * @hide
*/
@Deprecated
public void setActions(List<RemoteAction> actions) {
@@ -88,12 +195,7 @@
}
/**
- * Sets the source bounds hint. These bounds are only used when an activity first enters
- * picture-in-picture, and describe the bounds in window coordinates of activity entering
- * picture-in-picture that will be visible following the transition. For the best effect, these
- * bounds should also match the aspect ratio in the arguments.
- *
- * TODO: Remove once we remove PictureInPictureArgs.
+ * @hide
*/
@Deprecated
public void setSourceRectHint(Rect launchBounds) {
@@ -103,4 +205,172 @@
mSourceRectHint = new Rect(launchBounds);
}
}
-}
\ No newline at end of file
+
+ /**
+ * Copies the set parameters from the other picture-in-picture args.
+ * @hide
+ */
+ public void copyOnlySet(PictureInPictureArgs otherArgs) {
+ if (otherArgs.hasSetAspectRatio()) {
+ mAspectRatio = otherArgs.mAspectRatio;
+ }
+ if (otherArgs.hasSetActions()) {
+ mUserActions = otherArgs.mUserActions;
+ }
+ if (otherArgs.hasSourceBoundsHint()) {
+ mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
+ }
+ if (otherArgs.hasSourceBoundsHintInsets()) {
+ mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets());
+ }
+ }
+
+ /**
+ * @return the aspect ratio. If none is set, return 0.
+ * @hide
+ */
+ public float getAspectRatio() {
+ if (mAspectRatio != null) {
+ return mAspectRatio.floatValue();
+ }
+ return 0f;
+ }
+
+ /** {@hide} */
+ public Rational getAspectRatioRational() {
+ return mAspectRatio;
+ }
+
+ /**
+ * @return whether the aspect ratio is set.
+ * @hide
+ */
+ public boolean hasSetAspectRatio() {
+ return mAspectRatio != null;
+ }
+
+ /**
+ * @return the set of user actions.
+ * @hide
+ */
+ public List<RemoteAction> getActions() {
+ return mUserActions;
+ }
+
+ /**
+ * @return whether the user actions are set.
+ * @hide
+ */
+ public boolean hasSetActions() {
+ return mUserActions != null;
+ }
+
+ /**
+ * Truncates the set of actions to the given {@param size}.
+ * @hide
+ */
+ public void truncateActions(int size) {
+ if (hasSetActions()) {
+ mUserActions = mUserActions.subList(0, Math.min(mUserActions.size(), size));
+ }
+ }
+
+ /**
+ * Sets the insets to be used with the source rect hint bounds.
+ * @hide
+ */
+ @Deprecated
+ public void setSourceRectHintInsets(Rect insets) {
+ if (insets == null) {
+ mSourceRectHintInsets = null;
+ } else {
+ mSourceRectHintInsets = new Rect(insets);
+ }
+ }
+
+ /**
+ * @return the source rect hint
+ * @hide
+ */
+ public Rect getSourceRectHint() {
+ return mSourceRectHint;
+ }
+
+ /**
+ * @return the source rect hint insets.
+ * @hide
+ */
+ public Rect getSourceRectHintInsets() {
+ return mSourceRectHintInsets;
+ }
+
+ /**
+ * @return whether there are launch bounds set
+ * @hide
+ */
+ public boolean hasSourceBoundsHint() {
+ return mSourceRectHint != null && !mSourceRectHint.isEmpty();
+ }
+
+ /**
+ * @return whether there are source rect hint insets set
+ * @hide
+ */
+ public boolean hasSourceBoundsHintInsets() {
+ return mSourceRectHintInsets != null;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ if (mAspectRatio != null) {
+ out.writeInt(1);
+ out.writeInt(mAspectRatio.getNumerator());
+ out.writeInt(mAspectRatio.getDenominator());
+ } else {
+ out.writeInt(0);
+ }
+ if (mUserActions != null) {
+ out.writeInt(1);
+ out.writeParcelableList(mUserActions, 0);
+ } else {
+ out.writeInt(0);
+ }
+ if (mSourceRectHint != null) {
+ out.writeInt(1);
+ mSourceRectHint.writeToParcel(out, 0);
+ } else {
+ out.writeInt(0);
+ }
+ if (mSourceRectHintInsets != null) {
+ out.writeInt(1);
+ mSourceRectHintInsets.writeToParcel(out, 0);
+ } else {
+ out.writeInt(0);
+ }
+ }
+
+ public static final Creator<PictureInPictureArgs> CREATOR =
+ new Creator<PictureInPictureArgs>() {
+ public PictureInPictureArgs createFromParcel(Parcel in) {
+ return new PictureInPictureArgs(in);
+ }
+ public PictureInPictureArgs[] newArray(int size) {
+ return new PictureInPictureArgs[size];
+ }
+ };
+
+ public static PictureInPictureArgs convert(PictureInPictureParams params) {
+ return new PictureInPictureArgs(params.getAspectRatioRational(), params.getActions(),
+ params.getSourceRectHint());
+ }
+
+ public static PictureInPictureParams convert(PictureInPictureArgs args) {
+ return new PictureInPictureParams(args.getAspectRatioRational(), args.getActions(),
+ args.getSourceRectHint());
+ }
+}
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index e1df33b..323a0fb 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -28,10 +28,8 @@
/**
* Represents a set of parameters used to initialize and update an Activity in picture-in-picture
* mode.
- *
- * TODO: Make this final after we remove PictureInPictureArgs
*/
-public class PictureInPictureParams implements Parcelable {
+public final class PictureInPictureParams implements Parcelable {
/**
* Builder class for {@link PictureInPictureParams} objects.
@@ -63,7 +61,7 @@
/**
* Sets the user actions. If there are more than
- * {@link ActivityManager#getMaxNumPictureInPictureActions()} actions, then the input list
+ * {@link Activity#getMaxNumPictureInPictureActions()} actions, then the input list
* will be truncated to that number.
*
* @param actions the new actions to show in the picture-in-picture menu.
@@ -120,25 +118,22 @@
/**
* The expected aspect ratio of the picture-in-picture.
*/
- // TODO: Make private once we removed PictureInPictureArgs
@Nullable
- protected Rational mAspectRatio;
+ private Rational mAspectRatio;
/**
* The set of actions that are associated with this activity when in picture-in-picture.
*/
- // TODO: Make private once we removed PictureInPictureArgs
@Nullable
- protected List<RemoteAction> mUserActions;
+ private List<RemoteAction> mUserActions;
/**
* The source bounds hint used when entering picture-in-picture, relative to the window bounds.
* We can use this internally for the transition into picture-in-picture to ensure that a
* particular source rect is visible throughout the whole transition.
*/
- // TODO: Make private once we removed PictureInPictureArgs
@Nullable
- protected Rect mSourceRectHint;
+ private Rect mSourceRectHint;
/**
* The content insets that are used with the source hint rect for the transition into PiP where
@@ -147,15 +142,12 @@
@Nullable
private Rect mSourceRectHintInsets;
- /**
- * TO BE REMOVED
- */
- @Deprecated
+ /** {@hide} */
PictureInPictureParams() {
- // TODO: Remove once we remove PictureInPictureArgs
}
- private PictureInPictureParams(Parcel in) {
+ /** {@hide} */
+ PictureInPictureParams(Parcel in) {
if (in.readInt() != 0) {
mAspectRatio = new Rational(in.readInt(), in.readInt());
}
@@ -171,7 +163,8 @@
}
}
- private PictureInPictureParams(Rational aspectRatio, List<RemoteAction> actions,
+ /** {@hide} */
+ PictureInPictureParams(Rational aspectRatio, List<RemoteAction> actions,
Rect sourceRectHint) {
mAspectRatio = aspectRatio;
mUserActions = actions;
@@ -208,6 +201,11 @@
return 0f;
}
+ /** @hide */
+ public Rational getAspectRatioRational() {
+ return mAspectRatio;
+ }
+
/**
* @return whether the aspect ratio is set.
* @hide
diff --git a/core/java/android/app/RecoverableSecurityException.java b/core/java/android/app/RecoverableSecurityException.java
index a503a46..6747004 100644
--- a/core/java/android/app/RecoverableSecurityException.java
+++ b/core/java/android/app/RecoverableSecurityException.java
@@ -76,10 +76,7 @@
* {@link Activity#setResult(int)} before finishing to
* communicate the final status of the recovery. For example,
* apps that observe {@link Activity#RESULT_OK} may choose to
- * immediately retry their operation. If this exception was
- * thrown from a {@link ContentProvider}, you should also send
- * any relevant {@link ContentResolver#notifyChange} events to
- * trigger reloading of data.
+ * immediately retry their operation.
*/
public RecoverableSecurityException(Throwable cause, CharSequence userMessage,
RemoteAction userAction) {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 527314c..b560910 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -95,7 +95,6 @@
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Build;
-import android.os.Debug;
import android.os.DropBoxManager;
import android.os.HardwarePropertiesManager;
import android.os.IBatteryPropertiesRegistrar;
@@ -118,9 +117,6 @@
import android.os.storage.StorageManager;
import android.print.IPrintManager;
import android.print.PrintManager;
-import android.telephony.euicc.EuiccManager;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.IAutoFillManager;
import android.service.oemlock.IOemLockService;
import android.service.oemlock.OemLockManager;
import android.service.persistentdata.IPersistentDataBlockService;
@@ -130,6 +126,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -137,6 +134,8 @@
import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.CaptioningManager;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.IAutoFillManager;
import android.view.inputmethod.InputMethodManager;
import android.view.textclassifier.TextClassificationManager;
import android.view.textservice.TextServicesManager;
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 307fc91..2df011f 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -39,7 +39,7 @@
}
@Override
- public void onPinnedActivityRestartAttempt() throws RemoteException {
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) throws RemoteException {
}
@Override
diff --git a/core/java/android/app/CompatibilityDisplayProperties.aidl b/core/java/android/app/Vr2dDisplayProperties.aidl
similarity index 93%
rename from core/java/android/app/CompatibilityDisplayProperties.aidl
rename to core/java/android/app/Vr2dDisplayProperties.aidl
index 626a63e..1e04943 100644
--- a/core/java/android/app/CompatibilityDisplayProperties.aidl
+++ b/core/java/android/app/Vr2dDisplayProperties.aidl
@@ -17,4 +17,4 @@
package android.app;
/** @hide */
-parcelable CompatibilityDisplayProperties;
+parcelable Vr2dDisplayProperties;
diff --git a/core/java/android/app/CompatibilityDisplayProperties.java b/core/java/android/app/Vr2dDisplayProperties.java
similarity index 75%
rename from core/java/android/app/CompatibilityDisplayProperties.java
rename to core/java/android/app/Vr2dDisplayProperties.java
index 9a9bc2c..a608bb0 100644
--- a/core/java/android/app/CompatibilityDisplayProperties.java
+++ b/core/java/android/app/Vr2dDisplayProperties.java
@@ -27,7 +27,7 @@
*
* @hide
*/
-public class CompatibilityDisplayProperties implements Parcelable {
+public class Vr2dDisplayProperties implements Parcelable {
/**
* The actual width, height and dpi.
@@ -36,7 +36,7 @@
private final int mHeight;
private final int mDpi;
- public CompatibilityDisplayProperties(int width, int height, int dpi) {
+ public Vr2dDisplayProperties(int width, int height, int dpi) {
mWidth = width;
mHeight = height;
mDpi = dpi;
@@ -52,7 +52,7 @@
@Override
public String toString() {
- return "CompatibilityDisplayProperties{" +
+ return "Vr2dDisplayProperties{" +
"mWidth=" + mWidth +
", mHeight=" + mHeight +
", mDpi=" + mDpi +
@@ -64,7 +64,7 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- CompatibilityDisplayProperties that = (CompatibilityDisplayProperties) o;
+ Vr2dDisplayProperties that = (Vr2dDisplayProperties) o;
if (getWidth() != that.getWidth()) return false;
if (getHeight() != that.getHeight()) return false;
@@ -83,27 +83,27 @@
dest.writeInt(mDpi);
}
- public static final Parcelable.Creator<CompatibilityDisplayProperties> CREATOR
- = new Parcelable.Creator<CompatibilityDisplayProperties>() {
+ public static final Parcelable.Creator<Vr2dDisplayProperties> CREATOR
+ = new Parcelable.Creator<Vr2dDisplayProperties>() {
@Override
- public CompatibilityDisplayProperties createFromParcel(Parcel source) {
- return new CompatibilityDisplayProperties(source);
+ public Vr2dDisplayProperties createFromParcel(Parcel source) {
+ return new Vr2dDisplayProperties(source);
}
@Override
- public CompatibilityDisplayProperties[] newArray(int size) {
- return new CompatibilityDisplayProperties[size];
+ public Vr2dDisplayProperties[] newArray(int size) {
+ return new Vr2dDisplayProperties[size];
}
};
- private CompatibilityDisplayProperties(Parcel source) {
+ private Vr2dDisplayProperties(Parcel source) {
mWidth = source.readInt();
mHeight = source.readInt();
mDpi = source.readInt();
}
public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "CompatibilityDisplayProperties:");
+ pw.println(prefix + "Vr2dDisplayProperties:");
pw.println(prefix + " width=" + mWidth);
pw.println(prefix + " height=" + mHeight);
pw.println(prefix + " dpi=" + mDpi);
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 878c8c3..040b330 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -45,20 +45,20 @@
}
/**
- * Sets the resolution and DPI of the compatibility virtual display used to display 2D
+ * Sets the resolution and DPI of the vr2d virtual display used to display 2D
* applications in VR mode.
*
* <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
*
- * @param {@link android.app.CompatibilityDisplayProperties} properties to be set to the
- * virtual display for 2D applications in VR mode.
+ * @param vr2dDisplayProp properties to be set to the virtual display for
+ * 2D applications in VR mode.
*
* {@hide}
*/
- public void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp) {
+ public void setVr2dDisplayProperties(
+ Vr2dDisplayProperties vr2dDisplayProp) {
try {
- mService.setCompatibilityDisplayProperties(compatDisplayProp);
+ mService.setVr2dDisplayProperties(vr2dDisplayProp);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a202848..d26d7e5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -7656,6 +7656,7 @@
* empty set if none have been set.
*/
public @NonNull Set<String> getAffiliationIds(@NonNull ComponentName admin) {
+ throwIfParentInstance("getAffiliationIds");
try {
return new ArraySet<>(mService.getAffiliationIds(admin));
} catch (RemoteException e) {
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 3353530..7261dfa 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -1559,14 +1559,14 @@
@Override
public void setText(CharSequence text) {
ViewNodeText t = getNodeText();
- t.mText = text;
+ t.mText = TextUtils.trimNoCopySpans(text);
t.mTextSelectionStart = t.mTextSelectionEnd = -1;
}
@Override
public void setText(CharSequence text, int selectionStart, int selectionEnd) {
ViewNodeText t = getNodeText();
- t.mText = text;
+ t.mText = TextUtils.trimNoCopySpans(text);
t.mTextSelectionStart = selectionStart;
t.mTextSelectionEnd = selectionEnd;
}
@@ -1737,13 +1737,6 @@
}
@Override
- public void setUrl(String url) {
- if (url == null) return;
-
- setWebDomain(url);
- }
-
- @Override
public void setWebDomain(@Nullable String domain) {
if (domain == null) {
mNode.mWebDomain = null;
diff --git a/core/java/android/app/timezone/Callback.java b/core/java/android/app/timezone/Callback.java
new file mode 100644
index 0000000..b51e5ba
--- /dev/null
+++ b/core/java/android/app/timezone/Callback.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Callback interface for receiving information about an async time zone operation.
+ * The methods will be called on your application's main thread.
+ *
+ * @hide
+ */
+// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
+public abstract class Callback {
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({SUCCESS, ERROR_UNKNOWN_FAILURE, ERROR_INSTALL_BAD_DISTRO_STRUCTURE,
+ ERROR_INSTALL_BAD_DISTRO_FORMAT_VERSION, ERROR_INSTALL_RULES_TOO_OLD,
+ ERROR_INSTALL_VALIDATION_ERROR})
+ public @interface AsyncResultCode {}
+
+ /**
+ * Indicates that an operation succeeded.
+ */
+ public static final int SUCCESS = 0;
+
+ /**
+ * Indicates an install / uninstall did not fully succeed for an unknown reason.
+ */
+ public static final int ERROR_UNKNOWN_FAILURE = 1;
+
+ /**
+ * Indicates an install failed because of a structural issue with the provided distro,
+ * e.g. it wasn't in the right format or the contents were structured incorrectly.
+ */
+ public static final int ERROR_INSTALL_BAD_DISTRO_STRUCTURE = 2;
+
+ /**
+ * Indicates an install failed because of a versioning issue with the provided distro,
+ * e.g. it was created for a different version of Android.
+ */
+ public static final int ERROR_INSTALL_BAD_DISTRO_FORMAT_VERSION = 3;
+
+ /**
+ * Indicates an install failed because the rules provided are too old for the device,
+ * e.g. the Android device shipped with a newer rules version.
+ */
+ public static final int ERROR_INSTALL_RULES_TOO_OLD = 4;
+
+ /**
+ * Indicates an install failed because the distro contents failed validation.
+ */
+ public static final int ERROR_INSTALL_VALIDATION_ERROR = 5;
+
+ /**
+ * Reports the result of an async time zone operation.
+ */
+ public abstract void onFinished(@AsyncResultCode int status);
+}
diff --git a/core/java/android/app/timezone/DistroFormatVersion.java b/core/java/android/app/timezone/DistroFormatVersion.java
new file mode 100644
index 0000000..e879e8f
--- /dev/null
+++ b/core/java/android/app/timezone/DistroFormatVersion.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Versioning information about a distro's format or a device's supported format.
+ *
+ * <p>The following properties are included:
+ * <dl>
+ * <dt>majorVersion</dt>
+ * <dd>the major distro format version. Major versions differences are not compatible - e.g.
+ * 2 is not compatible with 1 or 3.</dd>
+ * <dt>minorVersion</dt>
+ * <dd>the minor distro format version. Minor versions should be backwards compatible iff the
+ * major versions match exactly, i.e. version 2.2 will be compatible with 2.1 devices but not
+ * 2.3 devices.</dd>
+ * </dl>
+ *
+ * @hide
+ */
+// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
+public final class DistroFormatVersion implements Parcelable {
+
+ private final int mMajorVersion;
+ private final int mMinorVersion;
+
+ public DistroFormatVersion(int majorVersion, int minorVersion) {
+ mMajorVersion = Utils.validateVersion("major", majorVersion);
+ mMinorVersion = Utils.validateVersion("minor", minorVersion);
+ }
+
+ public static final Creator<DistroFormatVersion> CREATOR = new Creator<DistroFormatVersion>() {
+ public DistroFormatVersion createFromParcel(Parcel in) {
+ int majorVersion = in.readInt();
+ int minorVersion = in.readInt();
+ return new DistroFormatVersion(majorVersion, minorVersion);
+ }
+
+ public DistroFormatVersion[] newArray(int size) {
+ return new DistroFormatVersion[size];
+ }
+ };
+
+ public int getMajorVersion() {
+ return mMajorVersion;
+ }
+
+ public int getMinorVersion() {
+ return mMinorVersion;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mMajorVersion);
+ out.writeInt(mMinorVersion);
+ }
+
+ /**
+ * If this object describes a device's supported version and the parameter describes a distro's
+ * version, this method returns whether the device would accept the distro.
+ */
+ public boolean supports(DistroFormatVersion distroFormatVersion) {
+ return mMajorVersion == distroFormatVersion.mMajorVersion
+ && mMinorVersion <= distroFormatVersion.mMinorVersion;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ DistroFormatVersion that = (DistroFormatVersion) o;
+
+ if (mMajorVersion != that.mMajorVersion) {
+ return false;
+ }
+ return mMinorVersion == that.mMinorVersion;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mMajorVersion;
+ result = 31 * result + mMinorVersion;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "DistroFormatVersion{"
+ + "mMajorVersion=" + mMajorVersion
+ + ", mMinorVersion=" + mMinorVersion
+ + '}';
+ }
+}
diff --git a/core/java/android/app/timezone/DistroRulesVersion.java b/core/java/android/app/timezone/DistroRulesVersion.java
new file mode 100644
index 0000000..5503ce1
--- /dev/null
+++ b/core/java/android/app/timezone/DistroRulesVersion.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import static android.app.timezone.Utils.validateRulesVersion;
+import static android.app.timezone.Utils.validateVersion;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Versioning information about a set of time zone rules.
+ *
+ * <p>The following properties are included:
+ * <dl>
+ * <dt>rulesVersion</dt>
+ * <dd>the IANA rules version. e.g. "2017a"</dd>
+ * <dt>revision</dt>
+ * <dd>the revision for the rules. Allows there to be several revisions for a given IANA rules
+ * release. Numerically higher is newer.</dd>
+ * </dl>
+ *
+ * @hide
+ */
+// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
+public final class DistroRulesVersion implements Parcelable {
+
+ private final String mRulesVersion;
+ private final int mRevision;
+
+ public DistroRulesVersion(String rulesVersion, int revision) {
+ mRulesVersion = validateRulesVersion("rulesVersion", rulesVersion);
+ mRevision = validateVersion("revision", revision);
+ }
+
+ public static final Creator<DistroRulesVersion> CREATOR = new Creator<DistroRulesVersion>() {
+ public DistroRulesVersion createFromParcel(Parcel in) {
+ String rulesVersion = in.readString();
+ int revision = in.readInt();
+ return new DistroRulesVersion(rulesVersion, revision);
+ }
+
+ public DistroRulesVersion[] newArray(int size) {
+ return new DistroRulesVersion[size];
+ }
+ };
+
+ public String getRulesVersion() {
+ return mRulesVersion;
+ }
+
+ public int getRevision() {
+ return mRevision;
+ }
+
+ /**
+ * Returns true if this DistroRulesVersion is older than the one supplied. It returns false if
+ * it is the same or newer. This method compares the {@code rulesVersion} and the
+ * {@code revision}.
+ */
+ public boolean isOlderThan(DistroRulesVersion distroRulesVersion) {
+ int rulesComparison = mRulesVersion.compareTo(distroRulesVersion.mRulesVersion);
+ if (rulesComparison < 0) {
+ return true;
+ }
+ if (rulesComparison > 0) {
+ return false;
+ }
+ return mRevision < distroRulesVersion.mRevision;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mRulesVersion);
+ out.writeInt(mRevision);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ DistroRulesVersion that = (DistroRulesVersion) o;
+
+ if (mRevision != that.mRevision) {
+ return false;
+ }
+ return mRulesVersion.equals(that.mRulesVersion);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mRulesVersion.hashCode();
+ result = 31 * result + mRevision;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "DistroRulesVersion{"
+ + "mRulesVersion='" + mRulesVersion + '\''
+ + ", mRevision='" + mRevision + '\''
+ + '}';
+ }
+}
diff --git a/core/java/android/app/CompatibilityDisplayProperties.aidl b/core/java/android/app/timezone/ICallback.aidl
similarity index 70%
copy from core/java/android/app/CompatibilityDisplayProperties.aidl
copy to core/java/android/app/timezone/ICallback.aidl
index 626a63e..519ef1a 100644
--- a/core/java/android/app/CompatibilityDisplayProperties.aidl
+++ b/core/java/android/app/timezone/ICallback.aidl
@@ -14,7 +14,14 @@
* limitations under the License.
*/
-package android.app;
+package android.app.timezone;
-/** @hide */
-parcelable CompatibilityDisplayProperties;
+/**
+ * Callback interface for a timezone updater to receive information about the success or failure of
+ * an installation/uninstallation attempt.
+ *
+ * {@hide}
+ */
+oneway interface ICallback {
+ void onFinished(int error);
+}
\ No newline at end of file
diff --git a/core/java/android/app/timezone/IRulesManager.aidl b/core/java/android/app/timezone/IRulesManager.aidl
new file mode 100644
index 0000000..40f3fd2
--- /dev/null
+++ b/core/java/android/app/timezone/IRulesManager.aidl
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import android.app.timezone.ICallback;
+import android.app.timezone.RulesState;
+import android.os.ParcelFileDescriptor;
+
+ /**
+ * Interface to the TimeZone Rules Manager Service.
+ *
+ * <p>This interface is only intended for system apps to call. They should use the
+ * {@link android.app.timezone.RulesManager} class rather than going through this
+ * Binder interface directly. See {@link android.app.timezone.RulesManager} for more complete
+ * documentation.
+ *
+ * {@hide}
+ */
+interface IRulesManager {
+
+ /**
+ * Returns information about the current time zone rules state such as the IANA version of
+ * the system and any currently installed distro. This method is intended to allow clients to
+ * determine if the current state can be improved; for example by passing the information to a
+ * server that may provide a new distro for download.
+ */
+ RulesState getRulesState();
+
+ /**
+ * Requests installation of the supplied distro. The distro must have been checked for integrity
+ * by the caller or have been received via a trusted mechanism.
+ *
+ * @param distroFileDescriptor the file descriptor for the distro
+ * @param checkToken an optional token provided if the install was triggered in response to a
+ * {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent
+ * @param callback the {@link ICallback} to receive callbacks related to the
+ * installation
+ * @return zero if the installation will be attempted; nonzero on error
+ */
+ int requestInstall(in ParcelFileDescriptor distroFileDescriptor, in byte[] checkToken,
+ ICallback callback);
+
+ /**
+ * Requests uninstallation of the currently installed distro (leaving the device with no
+ * distro installed).
+ *
+ * @param checkToken an optional token provided if the uninstall was triggered in response to a
+ * {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent
+ * @param callback the {@link ICallback} to receive callbacks related to the
+ * uninstall
+ * @return zero if the uninstallation will be attempted; nonzero on error
+ */
+ int requestUninstall(in byte[] checkToken, ICallback callback);
+
+ /**
+ * Requests the system does not modify the currently installed time zone distro, if any. This
+ * method records the fact that a time zone check operation triggered by the system is now
+ * complete and there was nothing to do. The token passed should be the one presented when the
+ * check was triggered.
+ *
+ * <p>Note: Passing {@code success == false} may result in more checks being triggered. Clients
+ * should be careful not to pass false if the failure is unlikely to resolve by itself.
+ *
+ * @param checkToken an optional token provided if the install was triggered in response to a
+ * {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent
+ * @param success true if the check was successful, false if it was not successful but may
+ * succeed if it is retried
+ */
+ void requestNothing(in byte[] token, boolean success);
+}
diff --git a/core/java/android/app/timezone/RulesManager.java b/core/java/android/app/timezone/RulesManager.java
new file mode 100644
index 0000000..649d894
--- /dev/null
+++ b/core/java/android/app/timezone/RulesManager.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import android.annotation.IntDef;
+import android.content.Context;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/**
+ * The interface through which a time zone update application interacts with the Android system
+ * to handle time zone rule updates.
+ *
+ * <p>This interface is intended for use with the default APK-based time zone rules update
+ * application but it can also be used by OEMs if that mechanism is turned off using configuration.
+ * All callers must possess the {@link android.Manifest.permission#UPDATE_TIME_ZONE_RULES} system
+ * permission.
+ *
+ * <p>When using the default mechanism, when properly configured the Android system will send a
+ * {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent with a
+ * {@link RulesUpdaterContract#EXTRA_CHECK_TOKEN} extra to the time zone rules updater application
+ * when it detects that it or the OEM's APK containing time zone rules data has been modified. The
+ * updater application is then responsible for calling one of
+ * {@link #requestInstall(ParcelFileDescriptor, byte[], Callback)},
+ * {@link #requestUninstall(byte[], Callback)} or
+ * {@link #requestNothing(byte[], boolean)}, indicating, respectively, whether a new time zone rules
+ * distro should be installed, the current distro should be uninstalled, or there is nothing to do
+ * (or that the correct operation could not be determined due to an error). In each case the updater
+ * must pass the {@link RulesUpdaterContract#EXTRA_CHECK_TOKEN} value it received from the intent
+ * back so the system in the {@code checkToken} parameter.
+ *
+ * <p>If OEMs want to handle their own time zone rules updates, perhaps via a server-side component
+ * rather than an APK, then they should disable the default triggering mechanism in config and are
+ * responsible for triggering their own update checks / installs / uninstalls. In this case the
+ * "check token" parameter can be left null and there is never any need to call
+ * {@link #requestNothing(byte[], boolean)}.
+ *
+ * <p>OEMs should not mix the default mechanism and their own as this could lead to conflicts and
+ * unnecessary checks being triggered.
+ *
+ * <p>Applications obtain this using {@link android.app.Activity#getSystemService(String)} with
+ * {@link Context#TIME_ZONE_RULES_MANAGER_SERVICE}.
+ * @hide
+ */
+// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
+public final class RulesManager {
+ private static final String TAG = "timezone.RulesManager";
+ private static final boolean DEBUG = false;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({SUCCESS, ERROR_UNKNOWN_FAILURE, ERROR_OPERATION_IN_PROGRESS})
+ public @interface ResultCode {}
+
+ /**
+ * Indicates that an operation succeeded.
+ */
+ public static final int SUCCESS = 0;
+
+ /**
+ * Indicates that an install/uninstall cannot be initiated because there is one already in
+ * progress.
+ */
+ public static final int ERROR_OPERATION_IN_PROGRESS = 1;
+
+ /**
+ * Indicates an install / uninstall did not fully succeed for an unknown reason.
+ */
+ public static final int ERROR_UNKNOWN_FAILURE = 2;
+
+ private final Context mContext;
+ private final IRulesManager mIRulesManager;
+
+ public RulesManager(Context context) {
+ mContext = context;
+ mIRulesManager = IRulesManager.Stub.asInterface(
+ ServiceManager.getService(Context.TIME_ZONE_RULES_MANAGER_SERVICE));
+ }
+
+ /**
+ * Returns information about the current time zone rules state such as the IANA version of
+ * the system and any currently installed distro. This method is intended to allow clients to
+ * determine if the current state can be improved; for example by passing the information to a
+ * server that may provide a new distro for download.
+ */
+ public RulesState getRulesState() {
+ try {
+ logDebug("sIRulesManager.getRulesState()");
+ RulesState rulesState = mIRulesManager.getRulesState();
+ logDebug("sIRulesManager.getRulesState() returned " + rulesState);
+ return rulesState;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Requests installation of the supplied distro. The distro must have been checked for integrity
+ * by the caller or have been received via a trusted mechanism.
+ *
+ * @param distroFileDescriptor the file descriptor for the distro
+ * @param checkToken an optional token provided if the install was triggered in response to a
+ * {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent
+ * @param callback the {@link Callback} to receive callbacks related to the installation
+ * @return {@link #SUCCESS} if the installation will be attempted
+ */
+ @ResultCode
+ public int requestInstall(
+ ParcelFileDescriptor distroFileDescriptor, byte[] checkToken, Callback callback)
+ throws IOException {
+
+ ICallback iCallback = new CallbackWrapper(mContext, callback);
+ try {
+ logDebug("sIRulesManager.requestInstall()");
+ return mIRulesManager.requestInstall(distroFileDescriptor, checkToken, iCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Requests uninstallation of the currently installed distro (leaving the device with no
+ * distro installed).
+ *
+ * @param checkToken an optional token provided if the uninstall was triggered in response to a
+ * {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent
+ * @param callback the {@link Callback} to receive callbacks related to the uninstall
+ * @return {@link #SUCCESS} if the uninstallation will be attempted
+ */
+ @ResultCode
+ public int requestUninstall(byte[] checkToken, Callback callback) {
+ ICallback iCallback = new CallbackWrapper(mContext, callback);
+ try {
+ logDebug("sIRulesManager.requestUninstall()");
+ return mIRulesManager.requestUninstall(checkToken, iCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /*
+ * We wrap incoming binder calls with a private class implementation that
+ * redirects them into main-thread actions. This serializes the backup
+ * progress callbacks nicely within the usual main-thread lifecycle pattern.
+ */
+ private class CallbackWrapper extends ICallback.Stub {
+ final Handler mHandler;
+ final Callback mCallback;
+
+ CallbackWrapper(Context context, Callback callback) {
+ mCallback = callback;
+ mHandler = new Handler(context.getMainLooper());
+ }
+
+ // Binder calls into this object just enqueue on the main-thread handler
+ @Override
+ public void onFinished(int status) {
+ logDebug("mCallback.onFinished(status), status=" + status);
+ mHandler.post(() -> mCallback.onFinished(status));
+ }
+ }
+
+ /**
+ * Requests the system does not modify the currently installed time zone distro, if any. This
+ * method records the fact that a time zone check operation triggered by the system is now
+ * complete and there was nothing to do. The token passed should be the one presented when the
+ * check was triggered.
+ *
+ * <p>Note: Passing {@code success == false} may result in more checks being triggered. Clients
+ * should be careful not to pass false if the failure is unlikely to resolve by itself.
+ *
+ * @param checkToken an optional token provided if the install was triggered in response to a
+ * {@link RulesUpdaterContract#ACTION_TRIGGER_RULES_UPDATE_CHECK} intent
+ * @param succeeded true if the check was successful, false if it was not successful but may
+ * succeed if it is retried
+ */
+ public void requestNothing(byte[] checkToken, boolean succeeded) {
+ try {
+ logDebug("sIRulesManager.requestNothing() with token=" + Arrays.toString(checkToken));
+ mIRulesManager.requestNothing(checkToken, succeeded);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ static void logDebug(String msg) {
+ if (DEBUG) {
+ Log.v(TAG, msg);
+ }
+ }
+}
diff --git a/core/java/android/app/CompatibilityDisplayProperties.aidl b/core/java/android/app/timezone/RulesState.aidl
similarity index 88%
copy from core/java/android/app/CompatibilityDisplayProperties.aidl
copy to core/java/android/app/timezone/RulesState.aidl
index 626a63e..f789120 100644
--- a/core/java/android/app/CompatibilityDisplayProperties.aidl
+++ b/core/java/android/app/timezone/RulesState.aidl
@@ -14,7 +14,4 @@
* limitations under the License.
*/
-package android.app;
-
-/** @hide */
-parcelable CompatibilityDisplayProperties;
+parcelable RulesState;
\ No newline at end of file
diff --git a/core/java/android/app/timezone/RulesState.java b/core/java/android/app/timezone/RulesState.java
new file mode 100644
index 0000000..33f4e80
--- /dev/null
+++ b/core/java/android/app/timezone/RulesState.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import static android.app.timezone.Utils.validateConditionalNull;
+import static android.app.timezone.Utils.validateNotNull;
+import static android.app.timezone.Utils.validateRulesVersion;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Description of the state of time zone rules on a device.
+ *
+ * <p>The following properties are included:
+ * <dl>
+ * <dt>systemRulesVersion</dt>
+ * <dd>the IANA rules version that shipped with the OS. Always present. e.g. "2017a".</dd>
+ * <dt>distroFormatVersionSupported</dt>
+ * <dd>the distro format version supported by this device. Always present.</dd>
+ * <dt>operationInProgress</dt>
+ * <dd>{@code true} if there is an install / uninstall operation currently happening.</dd>
+ * <dt>stagedOperationType</dt>
+ * <dd>one of {@link #STAGED_OPERATION_UNKNOWN}, {@link #STAGED_OPERATION_NONE},
+ * {@link #STAGED_OPERATION_UNINSTALL} and {@link #STAGED_OPERATION_INSTALL} indicating whether
+ * there is a currently staged time zone distro operation. {@link #STAGED_OPERATION_UNKNOWN} is
+ * used when {@link #isOperationInProgress()} is {@code true}. Staged operations currently
+ * require a reboot to become active.</dd>
+ * <dt>stagedDistroRulesVersion</dt>
+ * <dd>[present if distroStagedState == STAGED_STATE_INSTALL], the rules version of the distro
+ * currently staged for installation.</dd>
+ * <dt>distroStatus</dt>
+ * <dd>{@link #DISTRO_STATUS_INSTALLED} if there is a time zone distro installed and active,
+ * {@link #DISTRO_STATUS_NONE} if there is no active installed distro.
+ * {@link #DISTRO_STATUS_UNKNOWN} is used when {@link #isOperationInProgress()} is {@code true}.
+ * </dd>
+ * <dt>installedDistroRulesVersion</dt>
+ * <dd>[present if distroStatus == {@link #DISTRO_STATUS_INSTALLED}], the rules version of the
+ * installed and active distro.</dd>
+ * </dl>
+ *
+ * @hide
+ */
+// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
+public final class RulesState implements Parcelable {
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ STAGED_OPERATION_UNKNOWN,
+ STAGED_OPERATION_NONE,
+ STAGED_OPERATION_UNINSTALL,
+ STAGED_OPERATION_INSTALL })
+ private @interface StagedOperationType {}
+
+ /** Staged state could not be determined. */
+ public static final int STAGED_OPERATION_UNKNOWN = 0;
+ /** Nothing is staged. */
+ public static final int STAGED_OPERATION_NONE = 1;
+ /** An uninstall is staged. */
+ public static final int STAGED_OPERATION_UNINSTALL = 2;
+ /** An install is staged. */
+ public static final int STAGED_OPERATION_INSTALL = 3;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ DISTRO_STATUS_UNKNOWN,
+ DISTRO_STATUS_NONE,
+ DISTRO_STATUS_INSTALLED })
+ private @interface DistroStatus {}
+
+ /** The current distro status could not be determined. */
+ public static final int DISTRO_STATUS_UNKNOWN = 0;
+ /** There is no active installed time zone distro. */
+ public static final int DISTRO_STATUS_NONE = 1;
+ /** The is an active, installed time zone distro. */
+ public static final int DISTRO_STATUS_INSTALLED = 2;
+
+ private static final byte BYTE_FALSE = 0;
+ private static final byte BYTE_TRUE = 1;
+
+ private final String mSystemRulesVersion;
+ private final DistroFormatVersion mDistroFormatVersionSupported;
+ private final boolean mOperationInProgress;
+ @StagedOperationType private final int mStagedOperationType;
+ @Nullable private final DistroRulesVersion mStagedDistroRulesVersion;
+ @DistroStatus private final int mDistroStatus;
+ @Nullable private final DistroRulesVersion mInstalledDistroRulesVersion;
+
+ public RulesState(String systemRulesVersion, DistroFormatVersion distroFormatVersionSupported,
+ boolean operationInProgress,
+ @StagedOperationType int stagedOperationType,
+ @Nullable DistroRulesVersion stagedDistroRulesVersion,
+ @DistroStatus int distroStatus,
+ @Nullable DistroRulesVersion installedDistroRulesVersion) {
+ this.mSystemRulesVersion = validateRulesVersion("systemRulesVersion", systemRulesVersion);
+ this.mDistroFormatVersionSupported =
+ validateNotNull("distroFormatVersionSupported", distroFormatVersionSupported);
+ this.mOperationInProgress = operationInProgress;
+
+ if (operationInProgress && stagedOperationType != STAGED_OPERATION_UNKNOWN) {
+ throw new IllegalArgumentException(
+ "stagedOperationType != STAGED_OPERATION_UNKNOWN");
+ }
+ this.mStagedOperationType = validateStagedOperation(stagedOperationType);
+ this.mStagedDistroRulesVersion = validateConditionalNull(
+ mStagedOperationType == STAGED_OPERATION_INSTALL /* requireNotNull */,
+ "stagedDistroRulesVersion", stagedDistroRulesVersion);
+
+ if (operationInProgress && distroStatus != DISTRO_STATUS_UNKNOWN) {
+ throw new IllegalArgumentException("distroInstalled != DISTRO_STATUS_UNKNOWN");
+ }
+ this.mDistroStatus = validateDistroStatus(distroStatus);
+ this.mInstalledDistroRulesVersion = validateConditionalNull(
+ mDistroStatus == DISTRO_STATUS_INSTALLED/* requireNotNull */,
+ "installedDistroRulesVersion", installedDistroRulesVersion);
+ }
+
+ public String getSystemRulesVersion() {
+ return mSystemRulesVersion;
+ }
+
+ public boolean isOperationInProgress() {
+ return mOperationInProgress;
+ }
+
+ public @StagedOperationType int getStagedOperationType() {
+ return mStagedOperationType;
+ }
+
+ /**
+ * Returns the staged rules version when {@link #getStagedOperationType()} is
+ * {@link #STAGED_OPERATION_INSTALL}.
+ */
+ public @Nullable DistroRulesVersion getStagedDistroRulesVersion() {
+ return mStagedDistroRulesVersion;
+ }
+
+ public @DistroStatus int getDistroStatus() {
+ return mDistroStatus;
+ }
+
+ /**
+ * Returns the installed rules version when {@link #getDistroStatus()} is
+ * {@link #DISTRO_STATUS_INSTALLED}.
+ */
+ public @Nullable DistroRulesVersion getInstalledDistroRulesVersion() {
+ return mInstalledDistroRulesVersion;
+ }
+
+ /**
+ * Returns true if a distro in the specified format is supported on this device.
+ */
+ public boolean isDistroFormatVersionSupported(DistroFormatVersion distroFormatVersion) {
+ return mDistroFormatVersionSupported.supports(distroFormatVersion);
+ }
+
+ /**
+ * Returns true if the distro IANA rules version supplied is newer or the same as the version in
+ * the system image data files.
+ */
+ public boolean isSystemVersionOlderThan(DistroRulesVersion distroRulesVersion) {
+ return mSystemRulesVersion.compareTo(distroRulesVersion.getRulesVersion()) < 0;
+ }
+
+ public boolean isDistroInstalled() {
+ return mDistroStatus == DISTRO_STATUS_INSTALLED;
+ }
+
+ /**
+ * Returns true if the rules version supplied is newer than the one currently installed. If
+ * there is no installed distro this method throws IllegalStateException.
+ */
+ public boolean isInstalledDistroOlderThan(DistroRulesVersion distroRulesVersion) {
+ if (mOperationInProgress) {
+ throw new IllegalStateException("Distro state not known: operation in progress.");
+ }
+ if (!isDistroInstalled()) {
+ throw new IllegalStateException("No distro installed.");
+ }
+ return mInstalledDistroRulesVersion.isOlderThan(distroRulesVersion);
+ }
+
+ public static final Parcelable.Creator<RulesState> CREATOR =
+ new Parcelable.Creator<RulesState>() {
+ public RulesState createFromParcel(Parcel in) {
+ return RulesState.createFromParcel(in);
+ }
+
+ public RulesState[] newArray(int size) {
+ return new RulesState[size];
+ }
+ };
+
+ private static RulesState createFromParcel(Parcel in) {
+ String systemRulesVersion = in.readString();
+ DistroFormatVersion distroFormatVersionSupported = in.readParcelable(null);
+ boolean operationInProgress = in.readByte() == BYTE_TRUE;
+ int distroStagedState = in.readByte();
+ DistroRulesVersion stagedDistroRulesVersion = in.readParcelable(null);
+ int installedDistroStatus = in.readByte();
+ DistroRulesVersion installedDistroRulesVersion = in.readParcelable(null);
+ return new RulesState(systemRulesVersion, distroFormatVersionSupported, operationInProgress,
+ distroStagedState, stagedDistroRulesVersion,
+ installedDistroStatus, installedDistroRulesVersion);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mSystemRulesVersion);
+ out.writeParcelable(mDistroFormatVersionSupported, 0);
+ out.writeByte(mOperationInProgress ? BYTE_TRUE : BYTE_FALSE);
+ out.writeByte((byte) mStagedOperationType);
+ out.writeParcelable(mStagedDistroRulesVersion, 0);
+ out.writeByte((byte) mDistroStatus);
+ out.writeParcelable(mInstalledDistroRulesVersion, 0);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ RulesState that = (RulesState) o;
+
+ if (mOperationInProgress != that.mOperationInProgress) {
+ return false;
+ }
+ if (mStagedOperationType != that.mStagedOperationType) {
+ return false;
+ }
+ if (mDistroStatus != that.mDistroStatus) {
+ return false;
+ }
+ if (!mSystemRulesVersion.equals(that.mSystemRulesVersion)) {
+ return false;
+ }
+ if (!mDistroFormatVersionSupported.equals(that.mDistroFormatVersionSupported)) {
+ return false;
+ }
+ if (mStagedDistroRulesVersion != null ? !mStagedDistroRulesVersion
+ .equals(that.mStagedDistroRulesVersion) : that.mStagedDistroRulesVersion != null) {
+ return false;
+ }
+ return mInstalledDistroRulesVersion != null ? mInstalledDistroRulesVersion
+ .equals(that.mInstalledDistroRulesVersion)
+ : that.mInstalledDistroRulesVersion == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mSystemRulesVersion.hashCode();
+ result = 31 * result + mDistroFormatVersionSupported.hashCode();
+ result = 31 * result + (mOperationInProgress ? 1 : 0);
+ result = 31 * result + mStagedOperationType;
+ result = 31 * result + (mStagedDistroRulesVersion != null ? mStagedDistroRulesVersion
+ .hashCode()
+ : 0);
+ result = 31 * result + mDistroStatus;
+ result = 31 * result + (mInstalledDistroRulesVersion != null ? mInstalledDistroRulesVersion
+ .hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "RulesState{"
+ + "mSystemRulesVersion='" + mSystemRulesVersion + '\''
+ + ", mDistroFormatVersionSupported=" + mDistroFormatVersionSupported
+ + ", mOperationInProgress=" + mOperationInProgress
+ + ", mStagedOperationType=" + mStagedOperationType
+ + ", mStagedDistroRulesVersion=" + mStagedDistroRulesVersion
+ + ", mDistroStatus=" + mDistroStatus
+ + ", mInstalledDistroRulesVersion=" + mInstalledDistroRulesVersion
+ + '}';
+ }
+
+ private static int validateStagedOperation(int stagedOperationType) {
+ if (stagedOperationType < STAGED_OPERATION_UNKNOWN
+ || stagedOperationType > STAGED_OPERATION_INSTALL) {
+ throw new IllegalArgumentException("Unknown operation type=" + stagedOperationType);
+ }
+ return stagedOperationType;
+ }
+
+ private static int validateDistroStatus(int distroStatus) {
+ if (distroStatus < DISTRO_STATUS_UNKNOWN || distroStatus > DISTRO_STATUS_INSTALLED) {
+ throw new IllegalArgumentException("Unknown distro status=" + distroStatus);
+ }
+ return distroStatus;
+ }
+}
diff --git a/core/java/android/app/timezone/RulesUpdaterContract.java b/core/java/android/app/timezone/RulesUpdaterContract.java
new file mode 100644
index 0000000..4e77818
--- /dev/null
+++ b/core/java/android/app/timezone/RulesUpdaterContract.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Constants related to the contract between the Android system and the privileged time zone updater
+ * application.
+ *
+ * @hide
+ */
+// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
+public final class RulesUpdaterContract {
+
+ /**
+ * The system permission possessed by the Android system that allows it to trigger time zone
+ * update checks. The updater should be configured to require this permission when registering
+ * for {@link #ACTION_TRIGGER_RULES_UPDATE_CHECK} intents.
+ */
+ public static final String TRIGGER_TIME_ZONE_RULES_CHECK_PERMISSION =
+ android.Manifest.permission.TRIGGER_TIME_ZONE_RULES_CHECK;
+
+ /**
+ * The system permission possessed by the time zone rules updater app that allows it to update
+ * device time zone rules. The Android system requires this permission for calls made to
+ * {@link RulesManager}.
+ */
+ public static final String UPDATE_TIME_ZONE_RULES_PERMISSION =
+ android.Manifest.permission.UPDATE_TIME_ZONE_RULES;
+
+ /**
+ * The action of the intent that the Android system will broadcast. The intent will be targeted
+ * at the configured updater application's package meaning the term "broadcast" only loosely
+ * applies.
+ */
+ public static final String ACTION_TRIGGER_RULES_UPDATE_CHECK =
+ "android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK";
+
+ /**
+ * The extra containing the {@code byte[]} that should be passed to
+ * {@link RulesManager#requestInstall(ParcelFileDescriptor, byte[], Callback)},
+ * {@link RulesManager#requestUninstall(byte[], Callback)} and
+ * {@link RulesManager#requestNothing(byte[], boolean)} methods when the
+ * {@link #ACTION_TRIGGER_RULES_UPDATE_CHECK} intent has been processed.
+ */
+ public static final String EXTRA_CHECK_TOKEN =
+ "android.intent.extra.timezone.CHECK_TOKEN";
+
+ /**
+ * Creates an intent that would trigger a time zone rules update check.
+ */
+ public static Intent createUpdaterIntent(String updaterPackageName) {
+ Intent intent = new Intent(RulesUpdaterContract.ACTION_TRIGGER_RULES_UPDATE_CHECK);
+ intent.setPackage(updaterPackageName);
+ intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ return intent;
+ }
+
+ /**
+ * Broadcasts an {@link #ACTION_TRIGGER_RULES_UPDATE_CHECK} intent with the
+ * {@link #EXTRA_CHECK_TOKEN} that triggers an update check, including the required receiver
+ * permission.
+ */
+ public static void sendBroadcast(Context context, String updaterAppPackageName,
+ byte[] checkTokenBytes) {
+ Intent intent = createUpdaterIntent(updaterAppPackageName);
+ intent.putExtra(EXTRA_CHECK_TOKEN, checkTokenBytes);
+ context.sendBroadcast(intent, RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION);
+ }
+}
diff --git a/core/java/android/app/timezone/Utils.java b/core/java/android/app/timezone/Utils.java
new file mode 100644
index 0000000..8dd3fb7
--- /dev/null
+++ b/core/java/android/app/timezone/Utils.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.timezone;
+
+/**
+ * Shared code for android.app.timezone classes.
+ */
+final class Utils {
+ private Utils() {}
+
+ static int validateVersion(String type, int version) {
+ if (version < 0 || version > 999) {
+ throw new IllegalArgumentException("Invalid " + type + " version=" + version);
+ }
+ return version;
+ }
+
+ static String validateRulesVersion(String type, String rulesVersion) {
+ validateNotNull(type, rulesVersion);
+
+ if (rulesVersion.isEmpty()) {
+ throw new IllegalArgumentException(type + " must not be empty");
+ }
+ return rulesVersion;
+ }
+
+ /** Validates that {@code object} is not null. Always returns {@code object}. */
+ static <T> T validateNotNull(String type, T object) {
+ if (object == null) {
+ throw new NullPointerException(type + " == null");
+ }
+ return object;
+ }
+
+ /**
+ * If {@code requireNotNull} is {@code true} calls {@link #validateNotNull(String, Object)},
+ * and {@link #validateNull(String, Object)} otherwise. Returns {@code object}.
+ */
+ static <T> T validateConditionalNull(boolean requireNotNull, String type, T object) {
+ if (requireNotNull) {
+ return validateNotNull(type, object);
+ } else {
+ return validateNull(type, object);
+ }
+ }
+
+ /** Validates that {@code object} is null. Always returns null. */
+ static <T> T validateNull(String type, T object) {
+ if (object != null) {
+ throw new IllegalArgumentException(type + " != null");
+ }
+ return null;
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index d1ad8de..c58eaa1 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -136,6 +136,38 @@
*/
public static final int STATE_NOT_PLAYING = 11;
+ /**
+ * We don't have a stored preference for whether or not the given A2DP sink device supports
+ * optional codecs.
+ * @hide */
+ public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
+
+ /**
+ * The given A2DP sink device does not support optional codecs.
+ * @hide */
+ public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
+
+ /**
+ * The given A2DP sink device does support optional codecs.
+ * @hide */
+ public static final int OPTIONAL_CODECS_SUPPORTED = 1;
+
+ /**
+ * We don't have a stored preference for whether optional codecs should be enabled or disabled
+ * for the given A2DP device.
+ * @hide */
+ public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
+
+ /**
+ * Optional codecs should be disabled for the given A2DP device.
+ * @hide */
+ public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
+
+ /**
+ * Optional codecs should be enabled for the given A2DP device.
+ * @hide */
+ public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
+
private Context mContext;
private ServiceListener mServiceListener;
private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
@@ -655,6 +687,88 @@
}
/**
+ * Returns whether this device supports optional codecs.
+ *
+ * @param device The device to check
+ * @return one of OPTIONAL_CODECS_SUPPORT_UNKNOWN, OPTIONAL_CODECS_NOT_SUPPORTED, or
+ * OPTIONAL_CODECS_SUPPORTED.
+ *
+ * @hide
+ */
+ public int supportsOptionalCodecs(BluetoothDevice device) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ return mService.supportsOptionalCodecs(device);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Returns whether this device should have optional codecs enabled.
+ *
+ * @param device The device in question.
+ * @return one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
+ * OPTIONAL_CODECS_PREF_DISABLED.
+ *
+ * @hide
+ */
+ public int getOptionalCodecsEnabled(BluetoothDevice device) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ return mService.getOptionalCodecsEnabled(device);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return OPTIONAL_CODECS_PREF_UNKNOWN;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ return OPTIONAL_CODECS_PREF_UNKNOWN;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Sets a persistent preference for whether a given device should have optional codecs enabled.
+ *
+ * @param device The device to set this preference for.
+ * @param value Whether the optional codecs should be enabled for this device. This should be
+ * one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
+ * OPTIONAL_CODECS_PREF_DISABLED.
+ * @hide
+ */
+ public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+ try {
+ if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN &&
+ value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED &&
+ value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) {
+ Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
+ return;
+ }
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ mService.setOptionalCodecsEnabled(device, value);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
* Helper for converting a state to a string.
*
* For debug use only - strings are not internationalized.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index c427268..e8ad69d 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1703,7 +1703,7 @@
* an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect
* if {@code autoConnect} is set to true.
* @param handler The handler to use for the callback. If {@code null}, callbacks will happen
- * on the service's main thread.
+ * on an un-specified background thread.
* @throws NullPointerException if callback is null
*/
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
@@ -1712,9 +1712,6 @@
if (callback == null)
throw new NullPointerException("callback is null");
- if (handler == null)
- handler = new Handler(Looper.getMainLooper());
-
// TODO(Bluetooth) check whether platform support BLE
// Do the check here or in GattServer?
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 0f01d62..5fabbb6 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -156,7 +156,7 @@
}
mClientIf = clientIf;
if (status != GATT_SUCCESS) {
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -191,7 +191,7 @@
return;
}
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -213,7 +213,7 @@
return;
}
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -238,7 +238,7 @@
int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
BluetoothProfile.STATE_DISCONNECTED;
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -300,7 +300,7 @@
}
}
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -352,7 +352,7 @@
if (status == 0) characteristic.setValue(value);
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -401,7 +401,7 @@
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -430,7 +430,7 @@
characteristic.setValue(value);
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -477,7 +477,7 @@
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -523,7 +523,7 @@
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -549,7 +549,7 @@
mDeviceBusy = false;
}
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -570,7 +570,7 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -592,7 +592,7 @@
return;
}
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -616,7 +616,7 @@
return;
}
- mHandler.post(new Runnable() {
+ runOrQueueCallback(new Runnable() {
@Override
public void run() {
if (mCallback != null) {
@@ -703,6 +703,22 @@
}
/**
+ * Queue the runnable on a {@link Handler} provided by the user, or execute the runnable
+ * immediately if no Handler was provided.
+ */
+ private void runOrQueueCallback(final Runnable cb) {
+ if (mHandler == null) {
+ try {
+ cb.run();
+ } catch (Exception ex) {
+ Log.w(TAG, "Unhandled exception in callback", ex);
+ }
+ } else {
+ mHandler.post(cb);
+ }
+ }
+
+ /**
* Register an application callback to start using GATT.
*
* <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index a775a1f..1b533cb 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -42,4 +42,7 @@
oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig);
oneway void enableOptionalCodecs();
oneway void disableOptionalCodecs();
+ int supportsOptionalCodecs(in BluetoothDevice device);
+ int getOptionalCodecsEnabled(in BluetoothDevice device);
+ oneway void setOptionalCodecsEnabled(in BluetoothDevice device, int value);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a8214fa..08c7f18 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -34,7 +34,6 @@
import android.annotation.UserIdInt;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
-import android.app.Notification;
import android.app.VrManager;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -2660,8 +2659,8 @@
/**
* Similar to {@link #startService(Intent)}, but with an implicit promise that the
- * Service will call {@link android.app.Service#startForeground(int, Notification)
- * startForeground(int, Notification)} once it begins running. The service is given
+ * Service will call {@link android.app.Service#startForeground(int, android.app.Notification)
+ * startForeground(int, android.app.Notification)} once it begins running. The service is given
* an amount of time comparable to the ANR interval to do this, otherwise the system
* will automatically stop the service and declare the app ANR.
*
@@ -2682,7 +2681,7 @@
* or the service can not be found.
*
* @see #stopService
- * @see android.app.Service#startForeground(int, Notification)
+ * @see android.app.Service#startForeground(int, android.app.Notification)
*/
@Nullable
public abstract ComponentName startForegroundService(Intent service);
@@ -2865,6 +2864,7 @@
STORAGE_SERVICE,
STORAGE_STATS_SERVICE,
WALLPAPER_SERVICE,
+ TIME_ZONE_RULES_MANAGER_SERVICE,
VIBRATOR_SERVICE,
//@hide: STATUS_BAR_SERVICE,
CONNECTIVITY_SERVICE,
@@ -3968,6 +3968,15 @@
public static final String VR_SERVICE = "vrmanager";
/**
+ * Use with {@link #getSystemService} to retrieve an
+ * {@link android.app.timezone.ITimeZoneRulesManager}.
+ * @hide
+ *
+ * @see #getSystemService
+ */
+ public static final String TIME_ZONE_RULES_MANAGER_SERVICE = "timezone";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0be0885..587ab3b 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -883,9 +883,12 @@
/**
* Screen rotation animation desired by the activity, with values as defined
* for {@link android.view.WindowManager.LayoutParams#rotationAnimation}.
+ *
+ * -1 means to use the system default.
+ *
* @hide
*/
- public int rotationAnimation = ROTATION_ANIMATION_ROTATE;
+ public int rotationAnimation = -1;
/** @hide */
public static final int LOCK_TASK_LAUNCH_MODE_DEFAULT = 0;
@@ -985,10 +988,18 @@
* @hide
*/
boolean isFixedOrientationLandscape() {
- return screenOrientation == SCREEN_ORIENTATION_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_USER_LANDSCAPE;
+ return isFixedOrientationLandscape(screenOrientation);
+ }
+
+ /**
+ * Returns true if the activity's orientation is fixed to landscape.
+ * @hide
+ */
+ public static boolean isFixedOrientationLandscape(@ScreenOrientation int orientation) {
+ return orientation == SCREEN_ORIENTATION_LANDSCAPE
+ || orientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE
+ || orientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE
+ || orientation == SCREEN_ORIENTATION_USER_LANDSCAPE;
}
/**
@@ -996,10 +1007,18 @@
* @hide
*/
boolean isFixedOrientationPortrait() {
- return screenOrientation == SCREEN_ORIENTATION_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_USER_PORTRAIT;
+ return isFixedOrientationPortrait(screenOrientation);
+ }
+
+ /**
+ * Returns true if the activity's orientation is fixed to portrait.
+ * @hide
+ */
+ public static boolean isFixedOrientationPortrait(@ScreenOrientation int orientation) {
+ return orientation == SCREEN_ORIENTATION_PORTRAIT
+ || orientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
+ || orientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
+ || orientation == SCREEN_ORIENTATION_USER_PORTRAIT;
}
/**
diff --git a/core/java/android/content/pm/IDexModuleRegisterCallback.aidl b/core/java/android/content/pm/IDexModuleRegisterCallback.aidl
new file mode 100644
index 0000000..4af6999
--- /dev/null
+++ b/core/java/android/content/pm/IDexModuleRegisterCallback.aidl
@@ -0,0 +1,28 @@
+/*
+** Copyright 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.content.pm;
+
+import android.os.Bundle;
+
+/**
+ * Callback for registering a dex module with the Package Manager.
+ *
+ * @hide
+ */
+oneway interface IDexModuleRegisterCallback {
+ void onDexModuleRegistered(in String dexModulePath, in boolean success, in String message);
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c7dd1fa..1d5377b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -25,6 +25,7 @@
import android.content.pm.ChangedPackages;
import android.content.pm.InstantAppInfo;
import android.content.pm.FeatureInfo;
+import android.content.pm.IDexModuleRegisterCallback;
import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageDeleteObserver;
@@ -462,7 +463,7 @@
*
* See PackageManager.NOTIFY_PACKAGE_USE_* for reasons.
*/
- void notifyPackageUse(String packageName, int reason);
+ oneway void notifyPackageUse(String packageName, int reason);
/**
* Notify the package manager that a list of dex files have been loaded.
@@ -471,7 +472,40 @@
* @param dexPats the list of the dex files paths that have been loaded
* @param loaderIsa the ISA of the loader process
*/
- void notifyDexLoad(String loadingPackageName, in List<String> dexPaths, String loaderIsa);
+ oneway void notifyDexLoad(String loadingPackageName, in List<String> dexPaths,
+ String loaderIsa);
+
+ /**
+ * Register an application dex module with the package manager.
+ * The package manager will keep track of the given module for future optimizations.
+ *
+ * Dex module optimizations will disable the classpath checking at runtime. The client bares
+ * the responsibility to ensure that the static assumptions on classes in the optimized code
+ * hold at runtime (e.g. there's no duplicate classes in the classpath).
+ *
+ * Note that the package manager already keeps track of dex modules loaded with
+ * {@link dalvik.system.DexClassLoader} and {@link dalvik.system.PathClassLoader}.
+ * This can be called for an eager registration.
+ *
+ * The call might take a while and the results will be posted on the main thread, using
+ * the given callback.
+ *
+ * If the module is intended to be shared with other apps, make sure that the file
+ * permissions allow for it.
+ * If at registration time the permissions allow for others to read it, the module would
+ * be marked as a shared module which might undergo a different optimization strategy.
+ * (usually shared modules will generated larger optimizations artifacts,
+ * taking more disk space).
+ *
+ * @param packageName the package name to which the dex module belongs
+ * @param dexModulePath the absolute path of the dex module.
+ * @param isSharedModule whether or not the module is intended to be used by other apps.
+ * @param callback if not null,
+ * {@link android.content.pm.IDexModuleRegisterCallback.IDexModuleRegisterCallback#onDexModuleRegistered}
+ * will be called once the registration finishes.
+ */
+ oneway void registerDexModule(in String packageName, in String dexModulePath,
+ in boolean isSharedModule, IDexModuleRegisterCallback callback);
/**
* Ask the package manager to perform a dex-opt for the given reason. The package
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 2d8fec3..4e11233 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -26,6 +26,7 @@
import android.app.ActivityManager;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.PackageManager.InstallReason;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.FileBridge;
@@ -948,7 +949,7 @@
/** {@hide} */
public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
/** {@hide} */
- public int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
+ public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
/** {@hide} */
public long sizeBytes = -1;
/** {@hide} */
@@ -1147,11 +1148,9 @@
}
/**
- * Set the reason for installing this package. Currently,
- * {@code PackageManager#INSTALL_REASON_UNKNOWN} and
- * {@code PackageManager#INSTALL_REASON_POLICY} are defined.
+ * Set the reason for installing this package.
*/
- public void setInstallReason(int installReason) {
+ public void setInstallReason(@InstallReason int installReason) {
this.installReason = installReason;
}
@@ -1241,7 +1240,7 @@
/** {@hide} */
public int mode;
/** {@hide} */
- public int installReason;
+ public @InstallReason int installReason;
/** {@hide} */
public long sizeBytes;
/** {@hide} */
@@ -1329,13 +1328,9 @@
/**
* Return the reason for installing this package.
*
- * @return The install reason, currently one of
- * {@code PackageManager#INSTALL_REASON_UNKNOWN} and
- * {@code PackageManager#INSTALL_REASON_POLICY}.
- *
- * @see PackageManager#INSTALL_REASON_UNKNOWN
+ * @return The install reason.
*/
- public int getInstallReason() {
+ public @InstallReason int getInstallReason() {
return installReason;
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 10b7965..07125e0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5725,4 +5725,48 @@
* @hide
*/
public abstract String getInstantAppAndroidId(String packageName, @NonNull UserHandle user);
+
+ /**
+ * Callback use to notify the callers of module registration that the operation
+ * has finished.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static abstract class DexModuleRegisterCallback {
+ public abstract void onDexModuleRegistered(String dexModulePath, boolean success,
+ String message);
+ }
+
+ /**
+ * Register an application dex module with the package manager.
+ * The package manager will keep track of the given module for future optimizations.
+ *
+ * Dex module optimizations will disable the classpath checking at runtime. The client bares
+ * the responsibility to ensure that the static assumptions on classes in the optimized code
+ * hold at runtime (e.g. there's no duplicate classes in the classpath).
+ *
+ * Note that the package manager already keeps track of dex modules loaded with
+ * {@link dalvik.system.DexClassLoader} and {@link dalvik.system.PathClassLoader}.
+ * This can be called for an eager registration.
+ *
+ * The call might take a while and the results will be posted on the main thread, using
+ * the given callback.
+ *
+ * If the module is intended to be shared with other apps, make sure that the file
+ * permissions allow for it.
+ * If at registration time the permissions allow for others to read it, the module would
+ * be marked as a shared module which might undergo a different optimization strategy.
+ * (usually shared modules will generated larger optimizations artifacts,
+ * taking more disk space).
+ *
+ * @param dexModulePath the absolute path of the dex module.
+ * @param callback if not null, {@link DexModuleRegisterCallback#onDexModuleRegistered} will
+ * be called once the registration finishes.
+ *
+ * @hide
+ */
+ @SystemApi
+ public abstract void registerDexModule(String dexModulePath,
+ @Nullable DexModuleRegisterCallback callback);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 1013177..9b0bab4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -201,10 +201,10 @@
private static final String META_DATA_INSTANT_APPS = "instantapps.clients.allowed";
/**
- * Bit mask of all the valid bits that can be set in restartOnConfigChanges.
+ * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
* @hide
*/
- private static final int RESTART_ON_CONFIG_CHANGES_MASK =
+ private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
// These are the tags supported by child packages
@@ -4219,7 +4219,7 @@
ActivityManager.getDefaultAppRecentsLimitStatic());
a.info.configChanges = getActivityConfigChanges(
sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
- sa.getInt(R.styleable.AndroidManifestActivity_restartOnConfigChanges, 0));
+ sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
a.info.softInputMode = sa.getInt(
R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
@@ -4523,13 +4523,13 @@
/**
* @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
- * @param restartOnConfigChanges The bit mask restartOnConfigChanges fetched from
- * AndroidManifest.xml.
+ * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
+ * AndroidManifest.xml.
* @hide Exposed for unit testing only.
*/
@TestApi
- public static int getActivityConfigChanges(int configChanges, int restartOnConfigChanges) {
- return configChanges | ((~restartOnConfigChanges) & RESTART_ON_CONFIG_CHANGES_MASK);
+ public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
+ return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
}
private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index ee56a18..4e53914 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -44,7 +44,6 @@
public boolean notLaunched;
public boolean hidden; // Is the app restricted by owner / admin
public boolean suspended;
- public boolean blockUninstall;
public boolean instantApp;
public int enabled;
public String lastDisableAppCaller;
@@ -75,7 +74,6 @@
notLaunched = o.notLaunched;
hidden = o.hidden;
suspended = o.suspended;
- blockUninstall = o.blockUninstall;
instantApp = o.instantApp;
enabled = o.enabled;
lastDisableAppCaller = o.lastDisableAppCaller;
@@ -193,9 +191,6 @@
if (suspended != oldState.suspended) {
return false;
}
- if (blockUninstall != oldState.blockUninstall) {
- return false;
- }
if (instantApp != oldState.instantApp) {
return false;
}
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 650b4c0..f312204 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -71,6 +71,10 @@
/**
* Whether or not an instant app is available for the resolved intent.
*/
+ public boolean isInstantAppAvailable;
+
+ /** @removed */
+ @Deprecated
public boolean instantAppAvailable;
/**
@@ -330,7 +334,8 @@
system = orig.system;
targetUserId = orig.targetUserId;
handleAllWebDataURI = orig.handleAllWebDataURI;
- instantAppAvailable = orig.instantAppAvailable;
+ isInstantAppAvailable = orig.isInstantAppAvailable;
+ instantAppAvailable = isInstantAppAvailable;
}
public String toString() {
@@ -394,7 +399,7 @@
dest.writeInt(noResourceId ? 1 : 0);
dest.writeInt(iconResourceId);
dest.writeInt(handleAllWebDataURI ? 1 : 0);
- dest.writeInt(instantAppAvailable ? 1 : 0);
+ dest.writeInt(isInstantAppAvailable ? 1 : 0);
}
public static final Creator<ResolveInfo> CREATOR
@@ -442,7 +447,7 @@
noResourceId = source.readInt() != 0;
iconResourceId = source.readInt();
handleAllWebDataURI = source.readInt() != 0;
- instantAppAvailable = source.readInt() != 0;
+ instantAppAvailable = isInstantAppAvailable = source.readInt() != 0;
}
public static class DisplayNameComparator
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 0ad4874..5032e6a 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -131,7 +131,7 @@
*
* @return The version.
*/
- public @IntRange(from = -1) long getVersion() {
+ public @IntRange(from = -1) int getVersion() {
return mVersion;
}
diff --git a/core/java/android/content/res/FontResourcesParser.java b/core/java/android/content/res/FontResourcesParser.java
index 0edbc70..b21ccf1 100644
--- a/core/java/android/content/res/FontResourcesParser.java
+++ b/core/java/android/content/res/FontResourcesParser.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
@@ -34,6 +35,7 @@
* @hide
*/
public class FontResourcesParser {
+ private static final String TAG = "FontResourcesParser";
private static final int NORMAL_WEIGHT = 400;
private static final int ITALIC = 1;
@@ -79,12 +81,10 @@
private boolean mItalic;
private int mResourceId;
- public FontFileResourceEntry(@NonNull String fileName, int weight, boolean italic,
- int resourceId) {
+ public FontFileResourceEntry(@NonNull String fileName, int weight, boolean italic) {
mFileName = fileName;
mWeight = weight;
mItalic = italic;
- mResourceId = resourceId;
}
public @NonNull String getFileName() {
@@ -98,10 +98,6 @@
public boolean isItalic() {
return mItalic;
}
-
- public int getResourceId() {
- return mResourceId;
- }
}
// A class represents file based font-family element in xml file.
@@ -140,6 +136,7 @@
return readFamily(parser, resources);
} else {
skip(parser);
+ Log.e(TAG, "Failed to find font-family tag");
return null;
}
}
@@ -184,7 +181,10 @@
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
String tag = parser.getName();
if (tag.equals("font")) {
- fonts.add(readFont(parser, resources));
+ final FontFileResourceEntry entry = readFont(parser, resources);
+ if (entry != null) {
+ fonts.add(entry);
+ }
} else {
skip(parser);
}
@@ -203,12 +203,14 @@
int weight = array.getInt(R.styleable.FontFamilyFont_fontWeight, NORMAL_WEIGHT);
boolean isItalic = ITALIC == array.getInt(R.styleable.FontFamilyFont_fontStyle, 0);
String filename = array.getString(R.styleable.FontFamilyFont_font);
- int resourceId = array.getResourceId(R.styleable.FontFamilyFont_font, 0);
array.recycle();
while (parser.next() != XmlPullParser.END_TAG) {
skip(parser);
}
- return new FontFileResourceEntry(filename, weight, isItalic, resourceId);
+ if (filename == null) {
+ return null;
+ }
+ return new FontFileResourceEntry(filename, weight, isItalic);
}
private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 02ddc89..bdfef83 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -789,7 +789,6 @@
final FontResourcesParser.FamilyResourceEntry familyEntry =
FontResourcesParser.parse(rp, wrapper);
if (familyEntry == null) {
- Log.e(TAG, "Failed to find font-family tag");
return null;
}
return Typeface.createFromResources(familyEntry, mAssets, file);
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index bdb278b..4586316 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -34,6 +34,11 @@
InputDevice getInputDevice(int deviceId);
int[] getInputDeviceIds();
+ // Enable/disable input device.
+ boolean isInputDeviceEnabled(int deviceId);
+ void enableInputDevice(int deviceId);
+ void disableInputDevice(int deviceId);
+
// Reports whether the hardware supports the given keys; returns true if successful
boolean hasKeys(int deviceId, int sourceMask, in int[] keyCodes, out boolean[] keyExists);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 631b77d..22b3638 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,8 +16,6 @@
package android.hardware.input;
-import com.android.internal.os.SomeArgs;
-
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
@@ -31,10 +29,10 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.Vibrator;
-import android.os.VibrationEffect;
import android.os.ServiceManager.ServiceNotFoundException;
+import android.os.SystemClock;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
@@ -46,6 +44,8 @@
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
+import com.android.internal.os.SomeArgs;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -323,6 +323,62 @@
}
/**
+ * Returns true if an input device is enabled. Should return true for most
+ * situations. Some system apps may disable an input device, for
+ * example to prevent unwanted touch events.
+ *
+ * @param id The input device Id.
+ *
+ * @hide
+ */
+ public boolean isInputDeviceEnabled(int id) {
+ try {
+ return mIm.isInputDeviceEnabled(id);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not check enabled status of input device with id = " + id);
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Enables an InputDevice.
+ * <p>
+ * Requires {@link android.Manifest.permissions.DISABLE_INPUT_DEVICE}.
+ * </p>
+ *
+ * @param id The input device Id.
+ *
+ * @hide
+ */
+ public void enableInputDevice(int id) {
+ try {
+ mIm.enableInputDevice(id);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not enable input device with id = " + id);
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Disables an InputDevice.
+ * <p>
+ * Requires {@link android.Manifest.permissions.DISABLE_INPUT_DEVICE}.
+ * </p>
+ *
+ * @param id The input device Id.
+ *
+ * @hide
+ */
+ public void disableInputDevice(int id) {
+ try {
+ mIm.disableInputDevice(id);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not disable input device with id = " + id);
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Registers an input device listener to receive notifications about when
* input devices are added, removed or changed.
*
diff --git a/core/java/android/hardware/radio/ITuner.aidl b/core/java/android/hardware/radio/ITuner.aidl
index 68257ff..c08f41f 100644
--- a/core/java/android/hardware/radio/ITuner.aidl
+++ b/core/java/android/hardware/radio/ITuner.aidl
@@ -22,5 +22,12 @@
interface ITuner {
void close();
+ /**
+ * @throws IllegalArgumentException if config is not valid or null
+ */
+ void setConfiguration(in RadioManager.BandConfig config);
+
+ RadioManager.BandConfig getConfiguration();
+
int getProgramInformation(out RadioManager.ProgramInfo[] infoOut);
}
diff --git a/core/java/android/hardware/radio/TunerAdapter.java b/core/java/android/hardware/radio/TunerAdapter.java
index 10bbf9f..1156fe8 100644
--- a/core/java/android/hardware/radio/TunerAdapter.java
+++ b/core/java/android/hardware/radio/TunerAdapter.java
@@ -58,14 +58,28 @@
@Override
public int setConfiguration(RadioManager.BandConfig config) {
- // TODO(b/36863239): forward to mTuner
- throw new RuntimeException("Not implemented");
+ try {
+ mTuner.setConfiguration(config);
+ return RadioManager.STATUS_OK;
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Can't set configuration", e);
+ return RadioManager.STATUS_BAD_VALUE;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
@Override
public int getConfiguration(RadioManager.BandConfig[] config) {
- // TODO(b/36863239): forward to mTuner
- throw new RuntimeException("Not implemented");
+ if (config == null || config.length != 1) {
+ throw new IllegalArgumentException("The argument must be an array of length 1");
+ }
+ try {
+ config[0] = mTuner.getConfiguration();
+ return RadioManager.STATUS_OK;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
@Override
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 94e9470..5edefb5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3381,6 +3381,22 @@
}
/**
+ * Requests that the system open the captive portal app on the specified network.
+ *
+ * @param network The network to log into.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
+ public void startCaptivePortalApp(Network network) {
+ try {
+ mService.startCaptivePortalApp(network);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* It is acceptable to briefly use multipath data to provide seamless connectivity for
* time-sensitive user-facing operations when the system default network is temporarily
* unresponsive. The amount of data should be limited (less than one megabyte for every call to
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 63a1f051..27729dc 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -161,6 +161,7 @@
void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
void setAvoidUnvalidated(in Network network);
+ void startCaptivePortalApp(in Network network);
int getMultipathPreference(in Network Network);
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 73e52c8..d163a44 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -45,7 +45,7 @@
* Set the active scorer and clear existing scores.
* @param packageName the package name of the new scorer to use.
* @return true if the operation succeeded, or false if the new package is not a valid scorer.
- * @throws SecurityException if the caller is not the system.
+ * @throws SecurityException if the caller is not the system or a network scorer.
*/
boolean setActiveScorer(in String packageName);
diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java
index b4ef695..6de28b7 100644
--- a/core/java/android/net/NetworkBadging.java
+++ b/core/java/android/net/NetworkBadging.java
@@ -35,9 +35,10 @@
/**
* Utility methods for working with network badging.
*
- * @hide
+ * @removed
+ *
*/
-@SystemApi
+@Deprecated
public class NetworkBadging {
@IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K})
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index 1eaa1f9..d7b58f7 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package android.net;
import android.Manifest.permission;
@@ -41,11 +57,13 @@
private static final boolean VERBOSE = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
/** The key into the callback Bundle where the RecommendationResult will be found.
* @deprecated to be removed.
+ * @removed
*/
public static final String EXTRA_RECOMMENDATION_RESULT =
"android.net.extra.RECOMMENDATION_RESULT";
/** The key into the callback Bundle where the sequence will be found.
* @deprecated to be removed.
+ * @removed
*/
public static final String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
private final IBinder mService;
@@ -54,6 +72,7 @@
* Constructs a new instance.
* @param handler indicates which thread to use when handling requests. Cannot be {@code null}.
* @deprecated use {@link #NetworkRecommendationProvider(Context, Executor)}
+ * @removed
*/
public NetworkRecommendationProvider(Handler handler) {
if (handler == null) {
@@ -82,6 +101,7 @@
* available it must be passed into
* {@link ResultCallback#onResult(RecommendationResult)}.
* @deprecated to be removed.
+ * @removed
*/
public void onRequestRecommendation(RecommendationRequest request, ResultCallback callback) {}
@@ -107,6 +127,7 @@
* is available.
*
* @deprecated to be removed.
+ * @removed
*/
public static class ResultCallback {
private final IRemoteCallback mCallback;
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index eeb426a..9f6e45c 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -16,27 +16,20 @@
package android.net;
-import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
-
+import android.Manifest.permission;
import android.annotation.IntDef;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
-import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
-import java.util.concurrent.CompletableFuture;
/**
* Class that manages communication between network subsystems and a network scorer.
@@ -49,9 +42,9 @@
*
* <p>A network scorer is any application which:
* <ul>
- * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+ * <li>Declares the {@link permission#SCORE_NETWORKS} permission.
* <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
- * protected by the {@link android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
+ * protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
* permission.
* </ul>
*
@@ -319,7 +312,7 @@
*
* @return true if the operation succeeded, or false if the new package is not a valid scorer.
* @throws SecurityException if the caller is not a system process or does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission
+ * {@link permission#SCORE_NETWORKS} permission
* @hide
*/
@SystemApi
@@ -351,7 +344,7 @@
*
* @return true if the broadcast was sent, or false if there is no active scorer.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
* @hide
*/
public boolean requestScores(NetworkKey[] networks) throws SecurityException {
@@ -368,7 +361,7 @@
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
* @hide
@@ -385,7 +378,7 @@
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
* @param filterType the {@link CacheUpdateFilter} to apply
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
@@ -404,7 +397,7 @@
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
@@ -417,25 +410,6 @@
}
/**
- * Request a recommendation for which network to connect to.
- *
- * <p>It is not safe to call this method from the main thread.
- *
- * @param request a {@link RecommendationRequest} instance containing additional
- * request details
- * @return a {@link RecommendationResult} instance containing the recommended network
- * to connect to
- * @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
- * @hide
- * @deprecated to be removed.
- */
- public RecommendationResult requestRecommendation(RecommendationRequest request)
- throws SecurityException {
- return null;
- }
-
- /**
* Determine whether the application with the given UID is the enabled scorer.
*
* @param callingUid the UID to check
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
index 45ee3a5..21641d9 100644
--- a/core/java/android/net/RecommendationRequest.java
+++ b/core/java/android/net/RecommendationRequest.java
@@ -17,7 +17,6 @@
package android.net;
-import android.annotation.SystemApi;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.os.Parcel;
@@ -31,8 +30,8 @@
* @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
* @hide
* @deprecated to be removed.
+ * @removed
*/
-@SystemApi
public final class RecommendationRequest implements Parcelable {
private final ScanResult[] mScanResults;
private final WifiConfiguration mDefaultConfig;
@@ -45,8 +44,8 @@
* Builder class for constructing {@link RecommendationRequest} instances.
* @hide
* @deprecated to be removed.
+ * @removed
*/
- @SystemApi
public static final class Builder {
private ScanResult[] mScanResults;
private WifiConfiguration mDefaultConfig;
diff --git a/core/java/android/net/RecommendationResult.java b/core/java/android/net/RecommendationResult.java
index ce4d83a..d66dd22 100644
--- a/core/java/android/net/RecommendationResult.java
+++ b/core/java/android/net/RecommendationResult.java
@@ -18,12 +18,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.net.wifi.WifiConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
/**
@@ -32,8 +30,8 @@
* @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
* @hide
* @deprecated to be removed.
+ * @removed
*/
-@SystemApi
public final class RecommendationResult implements Parcelable {
private final WifiConfiguration mWifiConfiguration;
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 83c4691..3fd9f19 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -372,6 +372,8 @@
((DiscoveryListener) listener).onServiceLost((NsdServiceInfo) message.obj);
break;
case STOP_DISCOVERY_FAILED:
+ // TODO: failure to stop discovery should be internal and retried internally, as
+ // the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED
removeListener(message.arg2);
((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns),
message.arg1);
@@ -393,6 +395,8 @@
((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1);
break;
case UNREGISTER_SERVICE_SUCCEEDED:
+ // TODO: do not unregister listener until service is unregistered, or provide
+ // alternative way for unregistering ?
removeListener(message.arg2);
((RegistrationListener) listener).onServiceUnregistered(ns);
break;
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index 44addfc..a01b8ed 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -87,16 +87,6 @@
public abstract void setScreenBrightnessOverrideFromWindowManager(int brightness);
/**
- * Used by the window manager to override the button brightness based on the
- * current foreground activity.
- *
- * This method must only be called by the window manager.
- *
- * @param brightness The overridden brightness, or -1 to disable the override.
- */
- public abstract void setButtonBrightnessOverrideFromWindowManager(int brightness);
-
- /**
* Used by the window manager to override the user activity timeout based on the
* current foreground activity. It can only be used to make the timeout shorter
* than usual, not longer.
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 447f280..e063855 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -812,9 +812,11 @@
int timeTotal = -1;
int uncryptTime = -1;
int sourceVersion = -1;
- int temperature_start = -1;
- int temperature_end = -1;
- int temperature_max = -1;
+ int temperatureStart = -1;
+ int temperatureEnd = -1;
+ int temperatureMax = -1;
+ int errorCode = -1;
+ int causeCode = -1;
while ((line = in.readLine()) != null) {
// Here is an example of lines in last_install:
@@ -861,11 +863,15 @@
bytesStashedInMiB = (bytesStashedInMiB == -1) ? scaled :
bytesStashedInMiB + scaled;
} else if (line.startsWith("temperature_start")) {
- temperature_start = scaled;
+ temperatureStart = scaled;
} else if (line.startsWith("temperature_end")) {
- temperature_end = scaled;
+ temperatureEnd = scaled;
} else if (line.startsWith("temperature_max")) {
- temperature_max = scaled;
+ temperatureMax = scaled;
+ } else if (line.startsWith("error")) {
+ errorCode = scaled;
+ } else if (line.startsWith("cause")) {
+ causeCode = scaled;
}
}
@@ -885,14 +891,20 @@
if (bytesStashedInMiB != -1) {
MetricsLogger.histogram(context, "ota_stashed_in_MiBs", bytesStashedInMiB);
}
- if (temperature_start != -1) {
- MetricsLogger.histogram(context, "ota_temperature_start", temperature_start);
+ if (temperatureStart != -1) {
+ MetricsLogger.histogram(context, "ota_temperature_start", temperatureStart);
}
- if (temperature_end != -1) {
- MetricsLogger.histogram(context, "ota_temperature_end", temperature_end);
+ if (temperatureEnd != -1) {
+ MetricsLogger.histogram(context, "ota_temperature_end", temperatureEnd);
}
- if (temperature_max != -1) {
- MetricsLogger.histogram(context, "ota_temperature_max", temperature_max);
+ if (temperatureMax != -1) {
+ MetricsLogger.histogram(context, "ota_temperature_max", temperatureMax);
+ }
+ if (errorCode != -1) {
+ MetricsLogger.histogram(context, "ota_non_ab_error_code", errorCode);
+ }
+ if (causeCode != -1) {
+ MetricsLogger.histogram(context, "ota_non_ab_cause_code", causeCode);
}
} catch (IOException e) {
diff --git a/core/java/android/os/TestLooperManager.java b/core/java/android/os/TestLooperManager.java
index 745642e..5e7549f 100644
--- a/core/java/android/os/TestLooperManager.java
+++ b/core/java/android/os/TestLooperManager.java
@@ -58,11 +58,17 @@
/**
* Returns the {@link MessageQueue} this object is wrapping.
*/
- public MessageQueue getQueue() {
+ public MessageQueue getMessageQueue() {
checkReleased();
return mQueue;
}
+ /** @removed */
+ @Deprecated
+ public MessageQueue getQueue() {
+ return getMessageQueue();
+ }
+
/**
* Returns the next message that should be executed by this queue, may block
* if no messages are ready.
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index 1ef3916..8302ece 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -26,17 +26,12 @@
private static final String LOG_TAG = "VintfObject";
/**
- * Slurps all device information (both manifests)
- * and report it.
+ * Slurps all device information (both manifests and both matrices)
+ * and report them.
* If any error in getting one of the manifests, it is not included in
* the list.
*/
- public static String[] report() {
- ArrayList<String> ret = new ArrayList<>();
- put(ret, getDeviceManifest(), "device manifest");
- put(ret, getFrameworkManifest(), "framework manifest");
- return ret.toArray(new String[0]);
- }
+ public static native String[] report();
/**
* Verify that the given metadata for an OTA package is compatible with
@@ -50,15 +45,4 @@
*/
public static native int verify(String[] packageInfo);
- // return null if any error, otherwise XML string.
- private static native String getDeviceManifest();
- private static native String getFrameworkManifest();
-
- private static void put(ArrayList<String> list, String content, String message) {
- if (content == null || content.length() == 0) {
- Log.e(LOG_TAG, "Cannot get;" + message + "; check native logs for details.");
- return;
- }
- list.add(content);
- }
}
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 8208438..0d81bd9 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -19,6 +19,7 @@
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.util.Log;
+import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.Zygote;
import com.android.internal.util.Preconditions;
@@ -529,4 +530,27 @@
return (state.inputStream.readInt() == 0);
}
}
+
+ /**
+ * Try connecting to the Zygote over and over again until we hit a time-out.
+ * @param socketName The name of the socket to connect to.
+ */
+ public static void waitForConnectionToZygote(String socketName) {
+ for (int n = 20; n >= 0; n--) {
+ try {
+ final ZygoteState zs = ZygoteState.connect(socketName);
+ zs.close();
+ return;
+ } catch (IOException ioe) {
+ Log.w(LOG_TAG,
+ "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
+ }
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ }
+ }
+ Slog.wtf(LOG_TAG, "Failed to connect to Zygote through socket " + socketName);
+ }
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 8630f16..5c4fe96 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -333,6 +333,13 @@
public static final String TRANSCRIPTION = "transcription";
/**
+ * State of voicemail transcription entry. This will only be populated for call log
+ * entries of type {@link #VOICEMAIL_TYPE}.
+ * @hide
+ */
+ public static final String TRANSCRIPTION_STATE = "transcription_state";
+
+ /**
* Whether this item has been read or otherwise consumed by the user.
* <p>
* Unlike the {@link #NEW} field, which requires the user to have acknowledged the
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ea58925..4a6d8ce 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5176,13 +5176,6 @@
public static final String AUTOFILL_SERVICE = "autofill_service";
/**
- * bluetooth HCI snoop log configuration
- * @hide
- */
- public static final String BLUETOOTH_HCI_LOG =
- "bluetooth_hci_log";
-
- /**
* @deprecated Use {@link android.provider.Settings.Global#DEVICE_PROVISIONED} instead
*/
@Deprecated
@@ -6811,7 +6804,8 @@
* Represented as milliseconds from midnight (e.g. 79200000 == 10pm).
* @hide
*/
- public static final String NIGHT_DISPLAY_CUSTOM_START_TIME = "night_display_custom_start_time";
+ public static final String NIGHT_DISPLAY_CUSTOM_START_TIME =
+ "night_display_custom_start_time";
/**
* Custom time when Night display is scheduled to deactivate.
@@ -6821,6 +6815,14 @@
public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
/**
+ * Time in milliseconds (since epoch) when Night display was last activated. Use to decide
+ * whether to apply the current activated state after a reboot or user change.
+ * @hide
+ */
+ public static final String NIGHT_DISPLAY_LAST_ACTIVATED_TIME =
+ "night_display_last_activated_time";
+
+ /**
* Names of the service components that the current user has explicitly allowed to
* be a VR mode listener, separated by ':'.
*
@@ -7046,6 +7048,7 @@
NIGHT_DISPLAY_CUSTOM_END_TIME,
NIGHT_DISPLAY_COLOR_TEMPERATURE,
NIGHT_DISPLAY_AUTO_MODE,
+ NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
NIGHT_DISPLAY_ACTIVATED,
SYNC_PARENT_SOUNDS,
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
@@ -8993,6 +8996,12 @@
public static final String
BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX = "bluetooth_a2dp_src_priority_";
/** {@hide} */
+ public static final String BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX =
+ "bluetooth_a2dp_supports_optional_codecs_";
+ /** {@hide} */
+ public static final String BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX =
+ "bluetooth_a2dp_optional_codecs_enabled_";
+ /** {@hide} */
public static final String
BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX = "bluetooth_input_device_priority_";
/** {@hide} */
@@ -9259,6 +9268,25 @@
}
/**
+ * Get the key that retrieves a bluetooth a2dp device's ability to support optional codecs.
+ * @hide
+ */
+ public static final String getBluetoothA2dpSupportsOptionalCodecsKey(String address) {
+ return BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX +
+ address.toUpperCase(Locale.ROOT);
+ }
+
+ /**
+ * Get the key that retrieves whether a bluetooth a2dp device should have optional codecs
+ * enabled.
+ * @hide
+ */
+ public static final String getBluetoothA2dpOptionalCodecsEnabledKey(String address) {
+ return BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX +
+ address.toUpperCase(Locale.ROOT);
+ }
+
+ /**
* Get the key that retrieves a bluetooth Input Device's priority.
* @hide
*/
@@ -10409,6 +10437,15 @@
public static final String MAX_NOTIFICATION_ENQUEUE_RATE = "max_notification_enqueue_rate";
/**
+ * Displays toasts when an app posts a notification that does not specify a valid channel.
+ *
+ * The value 1 - enable, 0 - disable
+ * @hide
+ */
+ public static final String SHOW_NOTIFICATION_CHANNEL_WARNINGS =
+ "show_notification_channel_warnings";
+
+ /**
* Whether cell is enabled/disabled
* @hide
*/
diff --git a/core/java/android/provider/TimeZoneRulesDataContract.java b/core/java/android/provider/TimeZoneRulesDataContract.java
new file mode 100644
index 0000000..19e914b
--- /dev/null
+++ b/core/java/android/provider/TimeZoneRulesDataContract.java
@@ -0,0 +1,114 @@
+/*
+ * 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.provider;
+
+import android.net.Uri;
+
+/**
+ * A set of constants for implementing a time zone data content provider, which is used by the time
+ * zone updater application.
+ *
+ * @hide
+ */
+// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
+public final class TimeZoneRulesDataContract {
+
+ private TimeZoneRulesDataContract() {}
+
+ /**
+ * The authority that <em>must</em> be used for the time zone data content provider.
+ * To be accepted by the time zone updater application it <em>must</em> be exposed by the
+ * package specified in the config_timeZoneRulesDataPackage config value.
+ */
+ public static final String AUTHORITY = "com.android.timezone";
+
+ /** A content:// style uri to the authority for the time zone data content provider */
+ private static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
+
+ /**
+ * The content:// style URI for determining what type of update is available.
+ *
+ * <p>The URI can be queried using
+ * {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)};
+ * the result will be a cursor with a single row. If the {@link #COLUMN_OPERATION}
+ * column is {@link #OPERATION_INSTALL} then see {@link #DATA_URI} for how to obtain the
+ * binary data.
+ */
+ public static final Uri OPERATION_URI = Uri.withAppendedPath(AUTHORITY_URI, "operation");
+
+ /**
+ * The {@code String} column of the {@link #OPERATION_URI} that provides an int specifying the
+ * type of operation to perform. See {@link #OPERATION_NO_OP}, {@link #OPERATION_UNINSTALL} and
+ * {@link #OPERATION_INSTALL}.
+ */
+ public static final String COLUMN_OPERATION = "operation";
+
+ /**
+ * An operation type used when the time zone rules on device should be left as they are.
+ * This is not expected to be used in normal operation but a safe result in the event of an
+ * error that cannot be recovered from.
+ */
+ public static final String OPERATION_NO_OP = "NOOP";
+
+ /**
+ * An operation type used when the current time zone rules on device should be uninstalled,
+ * returning to the values held in the system partition.
+ */
+ public static final String OPERATION_UNINSTALL = "UNINSTALL";
+
+ /**
+ * An operation type used when the current time zone rules on device should be replaced by
+ * a new set obtained via the {@link android.content.ContentProvider#openFile(Uri, String)}
+ * method.
+ */
+ public static final String OPERATION_INSTALL = "INSTALL";
+
+ /**
+ * The {@code nullable int} column of the {@link #OPERATION_URI} that describes the major
+ * version of the distro to be installed.
+ * Only non-null if {@link #COLUMN_OPERATION} contains {@link #OPERATION_INSTALL}.
+ */
+ public static final String COLUMN_DISTRO_MAJOR_VERSION = "distro_major_version";
+
+ /**
+ * The {@code nullable int} column of the {@link #OPERATION_URI} that describes the minor
+ * version of the distro to be installed.
+ * Only non-null if {@link #COLUMN_OPERATION} contains {@link #OPERATION_INSTALL}.
+ */
+ public static final String COLUMN_DISTRO_MINOR_VERSION = "distro_minor_version";
+
+ /**
+ * The {@code nullable String} column of the {@link #OPERATION_URI} that describes the IANA
+ * rules version of the distro to be installed.
+ * Only non-null if {@link #COLUMN_OPERATION} contains {@link #OPERATION_INSTALL}.
+ */
+ public static final String COLUMN_RULES_VERSION = "rules_version";
+
+ /**
+ * The {@code nullable int} column of the {@link #OPERATION_URI} that describes the revision
+ * number of the distro to be installed.
+ * Only non-null if {@link #COLUMN_OPERATION} contains {@link #OPERATION_INSTALL}.
+ */
+ public static final String COLUMN_REVISION = "revision";
+
+ /**
+ * The content:// style URI for obtaining time zone bundle data.
+ *
+ * <p>Use {@link android.content.ContentProvider#openFile(Uri, String)} with "r" mode.
+ */
+ public static final Uri DATA_URI = Uri.withAppendedPath(AUTHORITY_URI, "data");
+}
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 4c61c2f..864a0fd 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -232,6 +232,39 @@
*/
public static final String TRANSCRIPTION = "transcription";
/**
+ * The state of the voicemail transcription.
+ * <P> Possible values: {@link #TRANSCRIPTION_NOT_STARTED},
+ * {@link #TRANSCRIPTION_IN_PROGRESS}, {@link #TRANSCRIPTION_FAILED},
+ * {@link #TRANSCRIPTION_AVAILABLE}.
+ * <P>Type: INTEGER</P>
+ * @hide
+ */
+ public static final String TRANSCRIPTION_STATE = "transcription_state";
+ /**
+ * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has not yet
+ * been attempted.
+ * @hide
+ */
+ public static final int TRANSCRIPTION_NOT_STARTED = 0;
+ /**
+ * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has begun
+ * but is not yet complete.
+ * @hide
+ */
+ public static final int TRANSCRIPTION_IN_PROGRESS = 1;
+ /**
+ * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has
+ * been attempted and failed.
+ * @hide
+ */
+ public static final int TRANSCRIPTION_FAILED = 2;
+ /**
+ * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has
+ * completed and the result has been stored in the {@link #TRANSCRIPTION} column.
+ * @hide
+ */
+ public static final int TRANSCRIPTION_AVAILABLE = 3;
+ /**
* Path to the media content file. Internal only field.
* @hide
*/
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 416455d..88d17ef 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -119,7 +119,7 @@
try {
onFillRequest(request, cancellation, fillCallback);
} catch (AbstractMethodError e) {
- final ArrayList<FillContext> contexts = request.getFillContexts();
+ final List<FillContext> contexts = request.getFillContexts();
onFillRequest(contexts.get(contexts.size() - 1).getStructure(),
request.getClientState(), request.getFlags(), cancellation,
fillCallback);
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 8ac399c..b1145ee 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -29,6 +29,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.List;
/**
* This class represents a request to an {@link AutofillService autofill provider}
@@ -96,7 +97,7 @@
/**
* @return The contexts associated with each previous fill request.
*/
- public @NonNull ArrayList<FillContext> getFillContexts() {
+ public @NonNull List<FillContext> getFillContexts() {
return mContexts;
}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 42c0151..1914db9 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -30,6 +30,7 @@
import android.widget.RemoteViews;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* Response for a {@link
@@ -258,12 +259,17 @@
* @param ids id of Views that when focused will display the authentication UI affordance.
*
* @return This builder.
+ * @throw {@link IllegalArgumentException} if {@code ids} is {@code null} or empty, or if
+ * neither {@code authentication} nor {@code presentation} is non-{@code null}.
+ *
* @see android.app.PendingIntent#getIntentSender()
*/
public @NonNull Builder setAuthentication(@NonNull AutofillId[] ids,
@Nullable IntentSender authentication, @Nullable RemoteViews presentation) {
throwIfDestroyed();
- // TODO(b/37424539): assert ids is not null nor empty once old version is removed
+ if (ids == null || ids.length == 0) {
+ throw new IllegalArgumentException("ids cannot be null or empry");
+ }
if (authentication == null ^ presentation == null) {
throw new IllegalArgumentException("authentication and presentation"
+ " must be both non-null or null");
@@ -275,17 +281,6 @@
}
/**
- * TODO(b/37424539): will be removed once clients use the version that takes ids
- * @hide
- * @deprecated
- */
- @Deprecated
- public @NonNull Builder setAuthentication(@Nullable IntentSender authentication,
- @Nullable RemoteViews presentation) {
- return setAuthentication(null, authentication, presentation);
- }
-
- /**
* Specifies views that should not trigger new
* {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
* FillCallback)} requests.
@@ -396,6 +391,7 @@
public String toString() {
if (!sDebug) return super.toString();
+ // TODO: create a dump() method instead
return new StringBuilder(
"FillResponse : [mRequestId=" + mRequestId)
.append(", datasets=").append(mDatasets)
@@ -403,10 +399,8 @@
.append(", clientState=").append(mClientState != null)
.append(", hasPresentation=").append(mPresentation != null)
.append(", hasAuthentication=").append(mAuthentication != null)
- .append(", authenticationSize=").append(mAuthenticationIds != null
- ? mAuthenticationIds.length : "N/A")
- .append(", ignoredIdsSize=").append(mIgnoredIds != null
- ? mIgnoredIds.length : "N/A")
+ .append(", authenticationIds=").append(Arrays.toString(mAuthenticationIds))
+ .append(", ignoredIds=").append(Arrays.toString(mIgnoredIds))
.append("]")
.toString();
}
@@ -447,8 +441,16 @@
}
builder.setSaveInfo(parcel.readParcelable(null));
builder.setClientState(parcel.readParcelable(null));
- builder.setAuthentication(parcel.readParcelableArray(null, AutofillId.class),
- parcel.readParcelable(null), parcel.readParcelable(null));
+
+ // Sets authentication state.
+ final AutofillId[] authenticationIds = parcel.readParcelableArray(null,
+ AutofillId.class);
+ final IntentSender authentication = parcel.readParcelable(null);
+ final RemoteViews presentation = parcel.readParcelable(null);
+ if (authenticationIds != null) {
+ builder.setAuthentication(authenticationIds, authentication, presentation);
+ }
+
builder.setIgnoredIds(parcel.readParcelableArray(null, AutofillId.class));
final FillResponse response = builder.build();
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
index 8b2d0c6..fc8afe9 100644
--- a/core/java/android/service/vr/IVrManager.aidl
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -16,7 +16,7 @@
package android.service.vr;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.service.vr.IVrStateCallbacks;
import android.service.vr.IPersistentVrStateCallbacks;
@@ -68,16 +68,16 @@
void setPersistentVrModeEnabled(in boolean enabled);
/**
- * Sets the resolution and DPI of the compatibility virtual display used to display
+ * Sets the resolution and DPI of the vr2d virtual display used to display
* 2D applications in VR mode.
*
* <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
*
- * @param compatDisplayProperties Compatibitlity display properties to be set for
+ * @param vr2dDisplayProperties Vr2d display properties to be set for
* the VR virtual display
*/
- void setCompatibilityDisplayProperties(
- in CompatibilityDisplayProperties compatDisplayProperties);
+ void setVr2dDisplayProperties(
+ in Vr2dDisplayProperties vr2dDisplayProperties);
/**
* Return current virtual display id.
@@ -85,7 +85,7 @@
* @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display
* currently, else return the display id of the virtual display
*/
- int getCompatibilityDisplayId();
+ int getVr2dDisplayId();
/**
* Initiate connection for system controller data.
diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java
index ef81f12..7381a12 100644
--- a/core/java/android/speech/tts/UtteranceProgressListener.java
+++ b/core/java/android/speech/tts/UtteranceProgressListener.java
@@ -144,9 +144,8 @@
onUtteranceRangeStart(utteranceId, start, end);
}
- /**
- * @deprecated Due to internal API changes. Remove when apps catch up.
- */
+ /** @removed */
+ @Deprecated
public void onUtteranceRangeStart(String utteranceId, int start, int end) {
}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index ee2b38e..91f43d6 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -40,6 +40,7 @@
import android.text.style.LeadingMarginSpan;
import android.text.style.LocaleSpan;
import android.text.style.MetricAffectingSpan;
+import android.text.style.ParagraphStyle;
import android.text.style.QuoteSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.ReplacementSpan;
@@ -56,6 +57,7 @@
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
+import android.text.style.UpdateAppearance;
import android.util.Log;
import android.util.Printer;
import android.view.View;
@@ -1903,6 +1905,38 @@
return Resources.getSystem().getQuantityString(R.plurals.selected_count, count, count);
}
+ /**
+ * Returns whether or not the specified spanned text has a style span.
+ * @hide
+ */
+ public static boolean hasStyleSpan(@NonNull Spanned spanned) {
+ Preconditions.checkArgument(spanned != null);
+ final Class<?>[] styleClasses = {
+ CharacterStyle.class, ParagraphStyle.class, UpdateAppearance.class};
+ for (Class<?> clazz : styleClasses) {
+ if (spanned.nextSpanTransition(-1, spanned.length(), clazz) < spanned.length()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * If the {@code charSequence} is instance of {@link Spanned}, creates a new copy and
+ * {@link NoCopySpan}'s are removed from the copy. Otherwise the given {@code charSequence} is
+ * returned as it is.
+ *
+ * @hide
+ */
+ @Nullable
+ public static CharSequence trimNoCopySpans(@Nullable CharSequence charSequence) {
+ if (charSequence != null && charSequence instanceof Spanned) {
+ // SpannableStringBuilder copy constructor trims NoCopySpans.
+ return new SpannableStringBuilder(charSequence);
+ }
+ return charSequence;
+ }
+
private static Object sLock = new Object();
private static char[] sTemp = null;
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 1ccf16a..48e5ca9 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -193,10 +193,14 @@
private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
// check for user specified next focus
View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
- if (userSetNextFocus != null && userSetNextFocus.isFocusable()
- && (!userSetNextFocus.isInTouchMode()
- || userSetNextFocus.isFocusableInTouchMode())) {
- return userSetNextFocus;
+ while (userSetNextFocus != null) {
+ if (userSetNextFocus.isFocusable()
+ && userSetNextFocus.getVisibility() == View.VISIBLE
+ && (!userSetNextFocus.isInTouchMode()
+ || userSetNextFocus.isFocusableInTouchMode())) {
+ return userSetNextFocus;
+ }
+ userSetNextFocus = userSetNextFocus.findUserSetNextFocus(root, direction);
}
return null;
}
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index ea2434e..8405d9e 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -16,6 +16,8 @@
package android.view;
+import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
@@ -768,6 +770,36 @@
}
/**
+ * Returns true if input device is enabled.
+ * @return Whether the input device is enabled.
+ */
+ public boolean isEnabled() {
+ return InputManager.getInstance().isInputDeviceEnabled(mId);
+ }
+
+ /**
+ * Enables the input device.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE)
+ @TestApi
+ public void enable() {
+ InputManager.getInstance().enableInputDevice(mId);
+ }
+
+ /**
+ * Disables the input device.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE)
+ @TestApi
+ public void disable() {
+ InputManager.getInstance().disableInputDevice(mId);
+ }
+
+ /**
* Reports whether the device has a built-in microphone.
* @return Whether the device has a built-in microphone.
*/
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index f71589c..6bdc9ff 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -374,13 +374,6 @@
public abstract Rect getTempRect();
/**
- * @deprecated - use {@link #setWebDomain(String)} instead.
- * @hide
- */
- @Deprecated
- public abstract void setUrl(String url);
-
- /**
* Sets the Web domain represented by this node.
*
* <p>Typically used when the view is a container for an HTML document.
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 4c266a6..c8f297a 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -23,10 +23,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -1113,6 +1115,19 @@
}
}
+ /**
+ * Determines if the accessibility button within the system navigation area is supported.
+ *
+ * @return {@code true} if the accessibility button is supported on this device,
+ * {@code false} otherwise
+ * @hide
+ */
+ @SystemApi
+ public static boolean isAccessibilityButtonSupported() {
+ final Resources res = Resources.getSystem();
+ return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
+ }
+
private final class MyCallback implements Handler.Callback {
public static final int MSG_SET_STATE = 1;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 0a24bfb0..d0133ed 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -95,7 +95,7 @@
* Type: {@link android.os.Bundle}
*/
public static final String EXTRA_CLIENT_STATE =
- "android.view.autofill.extra.EXTRA_CLIENT_STATE";
+ "android.view.autofill.extra.CLIENT_STATE";
static final String SESSION_ID_TAG = "android:sessionId";
static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData";
diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java
index b57dab5..3beae11 100644
--- a/core/java/android/view/autofill/AutofillValue.java
+++ b/core/java/android/view/autofill/AutofillValue.java
@@ -26,6 +26,7 @@
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.view.View;
import com.android.internal.util.Preconditions;
@@ -257,7 +258,8 @@
* <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
*/
public static AutofillValue forText(@Nullable CharSequence value) {
- return value == null ? null : new AutofillValue(AUTOFILL_TYPE_TEXT, value);
+ return value == null ? null : new AutofillValue(AUTOFILL_TYPE_TEXT,
+ TextUtils.trimNoCopySpans(value));
}
/**
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 108107e..209ff09 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -183,7 +183,9 @@
}
if (mSmartSelection == null || !Objects.equals(mLocale, locale)) {
destroySmartSelectionIfExistsLocked();
- mSmartSelection = new SmartSelection(getFdLocked(locale));
+ final ParcelFileDescriptor fd = getFdLocked(locale);
+ mSmartSelection = new SmartSelection(fd.getFd());
+ closeAndLogError(fd);
mLocale = locale;
}
return mSmartSelection;
@@ -191,7 +193,7 @@
}
@GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
- private int getFdLocked(Locale locale) throws FileNotFoundException {
+ private ParcelFileDescriptor getFdLocked(Locale locale) throws FileNotFoundException {
ParcelFileDescriptor updateFd;
try {
updateFd = ParcelFileDescriptor.open(
@@ -214,7 +216,7 @@
if (updateFd == null) {
if (factoryFd != null) {
- return factoryFd.getFd();
+ return factoryFd;
} else {
throw new FileNotFoundException(
String.format("No model file found for %s", locale));
@@ -227,7 +229,7 @@
SmartSelection.getLanguage(updateFdInt).trim().toLowerCase());
if (factoryFd == null) {
if (localeMatches) {
- return updateFdInt;
+ return updateFd;
} else {
closeAndLogError(updateFd);
throw new FileNotFoundException(
@@ -237,18 +239,17 @@
if (!localeMatches) {
closeAndLogError(updateFd);
- return factoryFd.getFd();
+ return factoryFd;
}
final int updateVersion = SmartSelection.getVersion(updateFdInt);
- final int factoryFdInt = factoryFd.getFd();
- final int factoryVersion = SmartSelection.getVersion(factoryFdInt);
+ final int factoryVersion = SmartSelection.getVersion(factoryFd.getFd());
if (updateVersion > factoryVersion) {
closeAndLogError(factoryFd);
- return updateFdInt;
+ return updateFd;
} else {
closeAndLogError(updateFd);
- return factoryFdInt;
+ return factoryFd;
}
}
@@ -606,6 +607,7 @@
@Nullable
public static Intent create(Context context, String type, String text) {
type = type.trim().toLowerCase(Locale.ENGLISH);
+ text = text.trim();
switch (type) {
case TextClassifier.TYPE_EMAIL:
return new Intent(Intent.ACTION_SENDTO)
@@ -617,6 +619,9 @@
return new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(String.format("geo:0,0?q=%s", text)));
case TextClassifier.TYPE_URL:
+ if (!text.startsWith("https://") && !text.startsWith("http://")) {
+ text = "http://" + text;
+ }
return new Intent(Intent.ACTION_VIEW, Uri.parse(text))
.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
default:
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index b519ec9..0204dff 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -218,7 +218,7 @@
final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
TextUtils.join(File.pathSeparator, zipPaths);
- waitForZygote();
+ ZygoteProcess.waitForConnectionToZygote(WEBVIEW_ZYGOTE_SOCKET);
Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath);
sZygote.preloadPackageForAbi(zip, librarySearchPath, sPackageCacheKey,
@@ -228,25 +228,4 @@
sZygote = null;
}
}
-
- /**
- * Wait until a connection to the Zygote can be established.
- */
- private static void waitForZygote() {
- while (true) {
- try {
- final ZygoteProcess.ZygoteState zs =
- ZygoteProcess.ZygoteState.connect(WEBVIEW_ZYGOTE_SOCKET);
- zs.close();
- break;
- } catch (IOException ioe) {
- Log.w(LOGTAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
- }
-
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ie) {
- }
- }
- }
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 1c87726..5476ab2 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -7088,7 +7088,8 @@
final int size = scrapViews.size();
if (size > 0) {
// See if we still have a view for this position or ID.
- for (int i = 0; i < size; i++) {
+ // Traverse backwards to find the most recently used scrap view
+ for (int i = size - 1; i >= 0; i--) {
final View view = scrapViews.get(i);
final AbsListView.LayoutParams params =
(AbsListView.LayoutParams) view.getLayoutParams();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 481c160..b0d6395 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -154,10 +154,10 @@
private static final int MENU_ITEM_ORDER_COPY = 5;
private static final int MENU_ITEM_ORDER_PASTE = 6;
private static final int MENU_ITEM_ORDER_SHARE = 7;
- private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 8;
- private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
- private static final int MENU_ITEM_ORDER_REPLACE = 10;
- private static final int MENU_ITEM_ORDER_AUTOFILL = 11;
+ private static final int MENU_ITEM_ORDER_SELECT_ALL = 8;
+ private static final int MENU_ITEM_ORDER_REPLACE = 9;
+ private static final int MENU_ITEM_ORDER_AUTOFILL = 10;
+ private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 11;
private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 100;
// Each Editor manages its own undo stack.
@@ -841,7 +841,7 @@
* Adjusts selection to the word under last touch offset. Return true if the operation was
* successfully performed.
*/
- private boolean selectCurrentWord() {
+ boolean selectCurrentWord() {
if (!mTextView.canSelectText()) {
return false;
}
@@ -1404,6 +1404,11 @@
// or double-clicks that could "dismiss" the floating toolbar.
int delay = ViewConfiguration.getDoubleTapTimeout();
mTextView.postDelayed(mShowFloatingToolbar, delay);
+
+ // This classifies the text and most likely returns before the toolbar is actually
+ // shown. If not, it will update the toolbar with the result when classification
+ // returns. We would rather not wait for a long running classification process.
+ invalidateActionModeAsync();
}
}
@@ -1853,7 +1858,7 @@
mInsertionPointCursorController.invalidateHandle();
}
if (mTextActionMode != null) {
- invalidateActionModeAsync();
+ invalidateActionMode();
}
}
@@ -1945,12 +1950,12 @@
if (mRestartActionModeOnNextRefresh) {
// To avoid distraction, newly start action mode only when selection action
// mode is being restarted.
- startSelectionActionMode();
+ startSelectionActionModeAsync(false);
}
} else if (selectionController == null || !selectionController.isActive()) {
// Insertion action mode is active. Avoid dismissing the selection.
stopTextActionModeWithPreservingSelection();
- startSelectionActionMode();
+ startSelectionActionModeAsync(false);
} else {
mTextActionMode.invalidateContentRect();
}
@@ -2004,15 +2009,8 @@
/**
* Asynchronously starts a selection action mode using the TextClassifier.
*/
- void startSelectionActionModeAsync() {
- getSelectionActionModeHelper().startActionModeAsync();
- }
-
- /**
- * Synchronously starts a selection action mode without the TextClassifier.
- */
- void startSelectionActionMode() {
- getSelectionActionModeHelper().startActionMode();
+ void startSelectionActionModeAsync(boolean adjustSelection) {
+ getSelectionActionModeHelper().startActionModeAsync(adjustSelection);
}
/**
@@ -2022,6 +2020,15 @@
getSelectionActionModeHelper().invalidateActionModeAsync();
}
+ /**
+ * Synchronously invalidates an action mode without the TextClassifier.
+ */
+ private void invalidateActionMode() {
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidate();
+ }
+ }
+
private SelectionActionModeHelper getSelectionActionModeHelper() {
if (mSelectionActionModeHelper == null) {
mSelectionActionModeHelper = new SelectionActionModeHelper(this);
@@ -2075,7 +2082,7 @@
}
if (mTextActionMode != null) {
// Text action mode is already started
- invalidateActionModeAsync();
+ invalidateActionMode();
return false;
}
@@ -2186,7 +2193,7 @@
}
void onTouchUpEvent(MotionEvent event) {
- if (getSelectionActionModeHelper().resetOriginalSelection(
+ if (getSelectionActionModeHelper().resetSelection(
getTextView().getOffsetForPosition(event.getX(), event.getY()))) {
return;
}
@@ -2634,9 +2641,9 @@
.setAlphabeticShortcut('v')
.setEnabled(mTextView.canPaste())
.setOnMenuItemClickListener(mOnContextMenuItemClickListener);
- menu.add(Menu.NONE, TextView.ID_PASTE, MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT,
+ menu.add(Menu.NONE, TextView.ID_PASTE_AS_PLAIN_TEXT, MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT,
com.android.internal.R.string.paste_as_plain_text)
- .setEnabled(mTextView.canPaste())
+ .setEnabled(mTextView.canPasteAsPlainText())
.setOnMenuItemClickListener(mOnContextMenuItemClickListener);
menu.add(Menu.NONE, TextView.ID_SHARE, MENU_ITEM_ORDER_SHARE,
com.android.internal.R.string.share)
@@ -3775,7 +3782,6 @@
mode.setSubtitle(null);
mode.setTitleOptionalHint(true);
populateMenuWithItems(menu);
- updateAssistMenuItem(menu);
Callback customCallback = getCustomCallback();
if (customCallback != null) {
@@ -3843,8 +3849,18 @@
.setShowAsAction(mode);
}
+ if (mTextView.canPasteAsPlainText()) {
+ menu.add(
+ Menu.NONE,
+ TextView.ID_PASTE_AS_PLAIN_TEXT,
+ MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT,
+ com.android.internal.R.string.paste_as_plain_text)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ }
+
updateSelectAllItem(menu);
updateReplaceItem(menu);
+ updateAssistMenuItem(menu);
}
@Override
@@ -4694,7 +4710,7 @@
}
positionAtCursorOffset(offset, false);
if (mTextActionMode != null) {
- invalidateActionModeAsync();
+ invalidateActionMode();
}
}
@@ -4778,7 +4794,7 @@
}
updateDrawable();
if (mTextActionMode != null) {
- invalidateActionModeAsync();
+ invalidateActionMode();
}
}
@@ -5405,13 +5421,8 @@
resetDragAcceleratorState();
if (mTextView.hasSelection()) {
- // Do not invoke the text assistant if this was a drag selection.
- if (mHaventMovedEnoughToStartDrag) {
- startSelectionActionModeAsync();
- } else {
- startSelectionActionMode();
- }
-
+ // Drag selection should not be adjusted by the text classifier.
+ startSelectionActionModeAsync(mHaventMovedEnoughToStartDrag);
}
break;
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index beff1b0..16a1087 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -33,6 +33,7 @@
import com.android.internal.util.Preconditions;
+import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -64,7 +65,7 @@
textView.getTextClassifier(), textView.getText(), 0, 1, textView.getTextLocales());
}
- public void startActionModeAsync() {
+ public void startActionModeAsync(boolean adjustSelection) {
cancelAsyncTask();
if (isNoOpTextClassifier() || !hasSelection()) {
// No need to make an async call for a no-op TextClassifier.
@@ -73,16 +74,16 @@
} else {
resetTextClassificationHelper();
mTextClassificationAsyncTask = new TextClassificationAsyncTask(
- mEditor.getTextView(), TIMEOUT_DURATION,
- mTextClassificationHelper::suggestSelection, this::startActionMode)
+ mEditor.getTextView(),
+ TIMEOUT_DURATION,
+ adjustSelection
+ ? mTextClassificationHelper::suggestSelection
+ : mTextClassificationHelper::classifyText,
+ this::startActionMode)
.execute();
}
}
- public void startActionMode() {
- startActionMode(null);
- }
-
public void invalidateActionModeAsync() {
cancelAsyncTask();
if (isNoOpTextClassifier() || !hasSelection()) {
@@ -98,8 +99,8 @@
}
}
- public boolean resetOriginalSelection(int textIndex) {
- if (mSelectionInfo.resetOriginalSelection(textIndex, mEditor.getTextView().getText())) {
+ public boolean resetSelection(int textIndex) {
+ if (mSelectionInfo.resetSelection(textIndex, mEditor)) {
invalidateActionModeAsync();
return true;
}
@@ -177,9 +178,9 @@
/**
* Holds information about the selection and uses it to decide on whether or not to update
- * the selection when resetOriginalSelection is called.
- * The expected UX here is to allow the user to re-snap the selection back to the original word
- * that was selected with one tap on that word.
+ * the selection when resetSelection is called.
+ * The expected UX here is to allow the user to select a word inside of the "smart selection" on
+ * a single tap.
*/
private static final class SelectionInfo {
@@ -212,14 +213,14 @@
mResetOriginal = false;
}
- public boolean resetOriginalSelection(int textIndex, CharSequence text) {
+ public boolean resetSelection(int textIndex, Editor editor) {
+ final CharSequence text = editor.getTextView().getText();
if (mResetOriginal
- && textIndex >= mOriginalStart && textIndex <= mOriginalEnd
+ && textIndex >= mSelectionStart && textIndex <= mSelectionEnd
&& text instanceof Spannable) {
- Selection.setSelection((Spannable) text, mOriginalStart, mOriginalEnd);
// Only allow a reset once.
mResetOriginal = false;
- return true;
+ return editor.selectCurrentWord();
}
return false;
}
@@ -310,6 +311,13 @@
/** End index relative to mTrimmedText */
private int mRelativeEnd;
+ /** Information about the last classified text to avoid re-running a query. */
+ private CharSequence mLastClassificationText;
+ private int mLastClassificationSelectionStart;
+ private int mLastClassificationSelectionEnd;
+ private LocaleList mLastClassificationLocales;
+ private SelectionResult mLastClassificationResult;
+
TextClassificationHelper(TextClassifier textClassifier,
CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
reset(textClassifier, text, selectionStart, selectionEnd, locales);
@@ -328,12 +336,25 @@
@WorkerThread
public SelectionResult classifyText() {
- trimText();
- return new SelectionResult(
- mSelectionStart,
- mSelectionEnd,
- mTextClassifier.classifyText(
- mTrimmedText, mRelativeStart, mRelativeEnd, mLocales));
+ if (!Objects.equals(mText, mLastClassificationText)
+ || mSelectionStart != mLastClassificationSelectionStart
+ || mSelectionEnd != mLastClassificationSelectionEnd
+ || !Objects.equals(mLocales, mLastClassificationLocales)) {
+
+ mLastClassificationText = mText;
+ mLastClassificationSelectionStart = mSelectionStart;
+ mLastClassificationSelectionEnd = mSelectionEnd;
+ mLastClassificationLocales = mLocales;
+
+ trimText();
+ mLastClassificationResult = new SelectionResult(
+ mSelectionStart,
+ mSelectionEnd,
+ mTextClassifier.classifyText(
+ mTrimmedText, mRelativeStart, mRelativeEnd, mLocales));
+
+ }
+ return mLastClassificationResult;
}
@WorkerThread
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 629216e..eaf1115 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -35,6 +35,7 @@
import android.app.Activity;
import android.app.assist.AssistStructure;
import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
@@ -10578,7 +10579,7 @@
Selection.setSelection((Spannable) text, start, end);
// Make sure selection mode is engaged.
if (mEditor != null) {
- mEditor.startSelectionActionMode();
+ mEditor.startSelectionActionModeAsync(false);
}
return true;
}
@@ -11042,6 +11043,26 @@
.hasPrimaryClip());
}
+ boolean canPasteAsPlainText() {
+ if (!canPaste()) {
+ return false;
+ }
+
+ final ClipData clipData =
+ ((ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE))
+ .getPrimaryClip();
+ final ClipDescription description = clipData.getDescription();
+ final boolean isPlainType = description.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN);
+ final CharSequence text = clipData.getItemAt(0).getText();
+ if (isPlainType && (text instanceof Spanned)) {
+ Spanned spanned = (Spanned) text;
+ if (TextUtils.hasStyleSpan(spanned)) {
+ return true;
+ }
+ }
+ return description.hasMimeType(ClipDescription.MIMETYPE_TEXT_HTML);
+ }
+
boolean canProcessText() {
if (getId() == View.NO_ID) {
return false;
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 7b2efea..58a2b0f 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -708,18 +708,20 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (isInPlaybackState() && mMediaController != null) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN
+ && isInPlaybackState() && mMediaController != null) {
toggleMediaControlsVisiblity();
}
- return false;
+ return super.onTouchEvent(ev);
}
@Override
public boolean onTrackballEvent(MotionEvent ev) {
- if (isInPlaybackState() && mMediaController != null) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN
+ && isInPlaybackState() && mMediaController != null) {
toggleMediaControlsVisiblity();
}
- return false;
+ return super.onTrackballEvent(ev);
}
@Override
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index e8bebb7..ee5f6fd 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -97,7 +97,8 @@
final List<ResolveInfo> infos = mpm.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY
| (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
- | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0));
+ | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0)
+ | PackageManager.MATCH_INSTANT);
if (infos != null) {
if (resolvedComponents == null) {
resolvedComponents = new ArrayList<>();
diff --git a/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java b/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
index 2d0ad66..56d60a1 100644
--- a/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
+++ b/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
@@ -376,7 +376,9 @@
for (int i = mLowerIndex, count = 0; i <= mUpperIndex; i++) {
count += hist[colors[i]];
if (count >= midPoint) {
- return i;
+ // we never want to split on the upperIndex, as this will result in the same
+ // box
+ return Math.min(mUpperIndex - 1, i);
}
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 142effb..4ce6ec5 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -786,21 +786,7 @@
private static void waitForSecondaryZygote(String socketName) {
String otherZygoteName = Process.ZYGOTE_SOCKET.equals(socketName) ?
Process.SECONDARY_ZYGOTE_SOCKET : Process.ZYGOTE_SOCKET;
- while (true) {
- try {
- final ZygoteProcess.ZygoteState zs =
- ZygoteProcess.ZygoteState.connect(otherZygoteName);
- zs.close();
- break;
- } catch (IOException ioe) {
- Log.w(TAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
- }
-
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ie) {
- }
- }
+ ZygoteProcess.waitForConnectionToZygote(otherZygoteName);
}
static boolean isPreloadComplete() {
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 324f923..6af41a5 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -256,7 +256,7 @@
final int hgrav = Gravity.getAbsoluteGravity(mDropDownGravity,
mAnchorView.getLayoutDirection()) & Gravity.HORIZONTAL_GRAVITY_MASK;
if (hgrav == Gravity.RIGHT) {
- xOffset -= mAnchorView.getWidth();
+ xOffset += mAnchorView.getWidth();
}
popup.setHorizontalOffset(xOffset);
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 169caa5..d9ca5be 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -263,6 +263,7 @@
mShownAnchorView, mOverflowOnly, mPopupStyleAttr, mPopupStyleRes);
subPopup.setPresenterCallback(mPresenterCallback);
subPopup.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(subMenu));
+ subPopup.setGravity(mDropDownGravity);
// Pass responsibility for handling onDismiss to the submenu.
subPopup.setOnDismissListener(mOnDismissListener);
diff --git a/core/jni/android/graphics/Movie.h b/core/jni/android/graphics/Movie.h
index c0fbe4f..736890d 100644
--- a/core/jni/android/graphics/Movie.h
+++ b/core/jni/android/graphics/Movie.h
@@ -10,8 +10,9 @@
#ifndef Movie_DEFINED
#define Movie_DEFINED
-#include "SkRefCnt.h"
+#include "SkBitmap.h"
#include "SkCanvas.h"
+#include "SkRefCnt.h"
class SkStreamRewindable;
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 14bad0f..9242b70 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -286,9 +286,7 @@
createProcessUniqueId()));
// If the current context is protected, inform the producer.
- if (isProtectedContext()) {
- consumer->setConsumerUsageBits(GRALLOC_USAGE_PROTECTED);
- }
+ consumer->setConsumerIsProtected(isProtectedContext());
SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
SurfaceTexture_setProducer(env, thiz, producer);
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index c11ce0f..d8eb7d2 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -442,10 +442,12 @@
if (threadRet != 0) {
close(writeFd);
+ close(readFd);
jniThrowExceptionFmt(env, "java/io/IOException",
"Failed to create thread for writing (errno = %#x, message = '%s')",
threadRet, strerror(threadRet));
+ return;
}
}
@@ -476,6 +478,8 @@
} else if (!logLine.isEmpty()) {
ALOGD("%s", logLine.string());
}
+
+ close(readFd);
}
int res;
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 9491a1e..033f2df 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,10 @@
#define LOG_TAG "VintfObject"
//#define LOG_NDEBUG 0
+#include <android-base/logging.h>
+
+#include <vector>
+#include <string>
#include <JNIHelp.h>
#include <vintf/VintfObject.h>
@@ -23,31 +27,48 @@
#include "core_jni_helpers.h"
+static jclass gString;
+
namespace android {
-using vintf::HalManifest;
-using vintf::RuntimeInfo;
using vintf::VintfObject;
using vintf::gHalManifestConverter;
+using vintf::gCompatibilityMatrixConverter;
+using vintf::XmlConverter;
-static jstring android_os_VintfObject_getDeviceManifest(JNIEnv* env, jclass clazz)
-{
- const HalManifest *manifest = VintfObject::GetDeviceHalManifest();
- if (manifest == nullptr) {
- return nullptr;
+static inline jobjectArray toJavaStringArray(JNIEnv* env, const std::vector<std::string>& v) {
+ jobjectArray ret = env->NewObjectArray(v.size(), gString, NULL /* init element */);
+ for (size_t i = 0; i < v.size(); ++i) {
+ env->SetObjectArrayElement(ret, i, env->NewStringUTF(v[i].c_str()));
}
- std::string xml = gHalManifestConverter(*manifest);
- return env->NewStringUTF(xml.c_str());
+ return ret;
}
-static jstring android_os_VintfObject_getFrameworkManifest(JNIEnv* env, jclass clazz)
-{
- const HalManifest *manifest = VintfObject::GetFrameworkHalManifest();
- if (manifest == nullptr) {
- return nullptr;
+template<typename T>
+static void tryAddSchema(const T* object, const XmlConverter<T>& converter,
+ const std::string& description,
+ std::vector<std::string>* cStrings) {
+ if (object == nullptr) {
+ LOG(WARNING) << __FUNCTION__ << "Cannot get " << description;
+ } else {
+ cStrings->push_back(converter(*object));
}
- std::string xml = gHalManifestConverter(*manifest);
- return env->NewStringUTF(xml.c_str());
+}
+
+static jobjectArray android_os_VintfObject_report(JNIEnv* env, jclass clazz)
+{
+ std::vector<std::string> cStrings;
+
+ tryAddSchema(VintfObject::GetDeviceHalManifest(), gHalManifestConverter,
+ "device manifest", &cStrings);
+ tryAddSchema(VintfObject::GetFrameworkHalManifest(), gHalManifestConverter,
+ "framework manifest", &cStrings);
+ tryAddSchema(VintfObject::GetDeviceCompatibilityMatrix(), gCompatibilityMatrixConverter,
+ "device compatibility matrix", &cStrings);
+ tryAddSchema(VintfObject::GetFrameworkCompatibilityMatrix(), gCompatibilityMatrixConverter,
+ "framework compatibility matrix", &cStrings);
+
+ return toJavaStringArray(env, cStrings);
}
static jint android_os_VintfObject_verify(JNIEnv *env, jclass clazz, jobjectArray packageInfo) {
@@ -66,15 +87,18 @@
// ----------------------------------------------------------------------------
static const JNINativeMethod gVintfObjectMethods[] = {
- {"getDeviceManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getDeviceManifest},
- {"getFrameworkManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getFrameworkManifest},
- {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
+ {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report},
+ {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
};
+
const char* const kVintfObjectPathName = "android/os/VintfObject";
int register_android_os_VintfObject(JNIEnv* env)
{
+
+ gString = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/String"));
+
return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods,
NELEM(gVintfObjectMethods));
}
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index d0ce192..c00d698 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -45,7 +45,6 @@
static jfieldID gDisplay_EGLDisplayFieldID;
static jfieldID gContext_EGLContextFieldID;
static jfieldID gSurface_EGLSurfaceFieldID;
-static jfieldID gSurface_NativePixelRefFieldID;
static jfieldID gConfig_EGLConfigFieldID;
static inline EGLDisplay getDisplay(JNIEnv* env, jobject o) {
@@ -84,7 +83,6 @@
jclass surface_class = _env->FindClass("com/google/android/gles_jni/EGLSurfaceImpl");
gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "J");
- gSurface_NativePixelRefFieldID = _env->GetFieldID(surface_class, "mNativePixelRef", "J");
}
static const jint gNull_attrib_base[] = {EGL_NONE};
@@ -398,14 +396,6 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLSurface sur = getSurface(_env, surface);
-
- if (sur) {
- SkPixelRef* ref = (SkPixelRef*)(_env->GetLongField(surface,
- gSurface_NativePixelRefFieldID));
- if (ref) {
- SkSafeUnref(ref);
- }
- }
return EglBoolToJBool(eglDestroySurface(dpy, sur));
}
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index ce951de..ea40fd5 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -329,6 +329,8 @@
SettingProto max_notification_enqueue_rate = 284;
SettingProto cell_on = 285;
SettingProto network_recommendations_package = 286;
+ SettingProto bluetooth_a2dp_supports_optional_codecs_prefix = 287;
+ SettingProto bluetooth_a2dp_optional_codecs_enabled_prefix = 288;
}
message SecureSettingsProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4811f7a..5f6d820 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1900,20 +1900,20 @@
android:protectionLevel="signature|privileged" />
<!-- Allows a companion app to run in the background.
- <p>Protection level: signature
+ <p>Protection level: normal
-->
<permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND"
android:label="@string/permlab_runInBackground"
android:description="@string/permdesc_runInBackground"
- android:protectionLevel="signature" />
+ android:protectionLevel="normal" />
<!-- Allows a companion app to use data in the background.
- <p>Protection level: signature
+ <p>Protection level: normal
-->
<permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND"
android:label="@string/permlab_useDataInBackground"
android:description="@string/permdesc_useDataInBackground"
- android:protectionLevel="signature" />
+ android:protectionLevel="normal" />
<!-- ================================== -->
@@ -2209,6 +2209,22 @@
<permission android:name="android.permission.UPDATE_CONFIG"
android:protectionLevel="signature|privileged" />
+ <!-- Allows a time zone rule updater application to request
+ the system installs / uninstalls timezone rules.
+ <p>An application requesting this permission is responsible for
+ verifying the source and integrity of the update before passing
+ it off to the installer components.
+ @hide -->
+ <permission android:name="android.permission.UPDATE_TIME_ZONE_RULES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a time zone rule updater application,
+ to ensure that only the system can trigger it.
+ @hide -->
+ <permission android:name="android.permission.TRIGGER_TIME_ZONE_RULES_CHECK"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.TRIGGER_TIME_ZONE_RULES_CHECK"/>
+
<!-- Allows the system to reset throttling in shortcut manager.
@hide -->
<permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING"
@@ -2743,6 +2759,13 @@
<permission android:name="android.permission.ACCESS_INPUT_FLINGER"
android:protectionLevel="signature" />
+ <!-- Allows an application to disable/enable input devices.
+ Could be used to prevent unwanted touch events
+ on a touchscreen, for example during swimming or rain.
+ @hide -->
+ <permission android:name="android.permission.DISABLE_INPUT_DEVICE"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to configure and connect to Wifi displays
@hide -->
<permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index b6cc035..4524b6e 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Opletberigte"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Kleinhandeldemonstrasie"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-verbinding"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Skakel oor na persoonlik"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 03432cb..a3ebecb 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"የችርቻሮ ማሳያ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"የዩኤስቢ ግንኙነት"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
<string name="user_owner_label" msgid="1119010402169916617">"ወደ የግል ቀይር"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 49aeb0a..d1b9dcb 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -277,6 +277,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"عرض توضيحي لبائع التجزئة"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"اتصال USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
<string name="android_system_label" msgid="6577375335728551336">"نظام Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"التبديل إلى الشخصي"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 4d4d157..552c4e3 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Pərakəndə demo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB əlaqə"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Təhlükəsiz rejim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistemi"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Şəxsi profilə keçirin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 81ef908..9fc3a28c 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -268,6 +268,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Obaveštenja"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Režim demonstracije za maloprodajne objekte"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB veza"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Bezbedni režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Pređi na Lični profil"</string>
@@ -1630,7 +1640,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"Instalirao je administrator"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Ažurirao je administrator"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Izbrisao je administrator"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"Da bi produžila vreme trajanja baterije, ušteda baterije smanjuje performanse uređaja i ograničava vibraciju, usluge lokacije i većinu pozadinskih podataka. Imejl, razmena poruka i druge aplikacije koje se oslanjaju na sinhronizaciju možda neće da se ažuriraju ako ih ne otvorite.\n\nUšteda baterije se automatski isključuje kada se uređaj puni."</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"Da bi produžila vreme trajanja baterije, ušteda baterije smanjuje performanse uređaja i ograničava vibraciju, usluge lokacije i većinu pozadinskih podataka. Imejl, razmena poruka i druge aplikacije koje se oslanjaju na sinhronizaciju neće se ažurirati dok ih ne otvorite.\n\nUšteda baterije se automatski isključuje kada se uređaj puni."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Da bi se smanjila potrošnja podataka, Ušteda podataka sprečava neke aplikacije da šalju ili primaju podatke u pozadini. Aplikacija koju trenutno koristite može da pristupa podacima, ali će to činiti ređe. Na primer, slike se neće prikazivati dok ih ne dodirnete."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Uključiti Uštedu podataka?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Uključi"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 3836385..fdd15d3 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Абвесткi"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Дэманстрацыйны рэжым для пунктаў продажу"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Падключэнне USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Бяспечны рэжым"</string>
<string name="android_system_label" msgid="6577375335728551336">"Сістэма Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Пераключыцца на асабісты"</string>
@@ -293,12 +303,12 @@
<string name="permgroupdesc_phone" msgid="6234224354060641055">"рабіць тэлефонныя выклікі і кіраваць імі"</string>
<string name="permgrouplab_sensors" msgid="416037179223226722">"Датчыкі цела"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"атрымліваць з датчыка даныя асноўных фізіялагічных паказчыкаў"</string>
- <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Атрымайце змесцiва акна"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Вывучыце змесцiва акна, з якiм вы працуеце."</string>
- <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Уключыце Explore by Touch"</string>
+ <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Атрымліваць змесціва вакна"</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Аналізаваць змесціва актыўнага вакна."</string>
+ <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Уключаць Азнаямленне дотыкам"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Элементы, да якіх дакрануліся, будуць агучаны, а экранам можна даследаваць пры дапамозе жэстаў."</string>
- <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Глядзiце, што набiраеце"</string>
- <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Уключае ў сябе асабістыя дадзеныя, такія як нумары крэдытных карт і паролі."</string>
+ <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Праглядаць тэкст, які вы набіраеце"</string>
+ <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"У тым ліку асабістыя даныя, такія як нумары крэдытных карт і паролі."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Кіраваць павелічэннем дысплэя"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Кіраваць маштабам дысплэя і пазіцыянаваннем."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Выконваць жэсты"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index c799ca9..b03e09e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Сигнали"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Демонстрационен режим за магазини"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB връзка"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Превключване към личния потребителски профил"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index c8bc6d7..b574890 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"সতর্কতাগুলি"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"খুচরা বিক্রয়ের ডেমো"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB সংযোগ"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"নিরাপদ মোড"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android সিস্টেম"</string>
<string name="user_owner_label" msgid="1119010402169916617">"ব্যক্তিগততে পাল্টান"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index f93c655..37fa55f 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -268,6 +268,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Promotivna demonstracija u maloprodaji"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB veza"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Prebacite se na lični"</string>
@@ -998,7 +1008,7 @@
<string name="inputMethod" msgid="1653630062304567879">"Način unosa"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Akcije za tekst"</string>
<string name="email" msgid="4560673117055050403">"E-pošta"</string>
- <string name="dial" msgid="4204975095406423102">"Telefon"</string>
+ <string name="dial" msgid="4204975095406423102">"Pozovi"</string>
<string name="map" msgid="5441053548030107189">"Mapa"</string>
<string name="browse" msgid="6079864138582486027">"Pretraži"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ponestaje prostora za pohranu"</string>
@@ -1184,7 +1194,7 @@
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Postavljanje vremena"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Postavljanje datuma"</string>
<string name="date_time_set" msgid="5777075614321087758">"Postaviti"</string>
- <string name="date_time_done" msgid="2507683751759308828">"Završeno"</string>
+ <string name="date_time_done" msgid="2507683751759308828">"Gotovo"</string>
<string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOVO: "</font></string>
<string name="perms_description_app" msgid="5139836143293299417">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> omogućava."</string>
<string name="no_permissions" msgid="7283357728219338112">"Nisu potrebne dozvole"</string>
@@ -1436,7 +1446,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"Bežični prikaz"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Prebacuj"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Poveži na uređaj"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Prebaci ekran na uređaj"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Emitiranje ekrana na uređaj"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"Traženje uređajā…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Postavke"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Prekini vezu"</string>
@@ -1615,7 +1625,7 @@
<string name="immersive_cling_title" msgid="8394201622932303336">"Prikazuje se cijeli ekran"</string>
<string name="immersive_cling_description" msgid="3482371193207536040">"Da izađete, prevucite nadolje odozgo."</string>
<string name="immersive_cling_positive" msgid="5016839404568297683">"Razumijem"</string>
- <string name="done_label" msgid="2093726099505892398">"Završeno"</string>
+ <string name="done_label" msgid="2093726099505892398">"Gotovo"</string>
<string name="hour_picker_description" msgid="6698199186859736512">"Kružni klizač za odabir sata"</string>
<string name="minute_picker_description" msgid="8606010966873791190">"Kružni klizač za minute"</string>
<string name="select_hours" msgid="6043079511766008245">"Odaberite sat"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 512f167..0b77c82 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demostració comercial"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Connexió USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Canvia al perfil personal"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0dabc80..31f0826 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornění"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Prodejní ukázka"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Připojení USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Přepnout na osobní profil"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d5b40fb..a258f08 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Underretninger"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo til udstilling i butik"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-forbindelse"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Skift til Tilpasset"</string>
@@ -317,8 +327,8 @@
<string name="permdesc_receiveSms" msgid="6424387754228766939">"Tillader, at appen kan modtage og behandle sms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"modtage tekstbeskeder (mms)"</string>
<string name="permdesc_receiveMms" msgid="533019437263212260">"Tillader, at appen kan modtage og behandle mms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
- <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"læse Cell Broadcast-beskeder"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillader, at appen læser Cell Broadcast-beskeder, der modtages af din enhed. I nogle områder sendes der Cell Broadcast-beskeder for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af din enhed, når der modtages en Cell Broadcast-besked om en nødsituation."</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"læse Cell Broadcast-meddelelser"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillader, at appen læser Cell Broadcast-meddelelser, der modtages af din enhed. I nogle områder sendes der Cell Broadcast-meddelelser for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af din enhed, når der modtages en Cell Broadcast-meddelelse om en nødsituation."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"læse feeds, jeg abonnerer på"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Tillader, at appen kan hente oplysninger om de feeds, der synkroniseres."</string>
<string name="permlab_sendSms" msgid="7544599214260982981">"Send og se sms-beskeder"</string>
@@ -1074,19 +1084,19 @@
<string name="dump_heap_text" msgid="4809417337240334941">"Processen <xliff:g id="PROC">%1$s</xliff:g> har overskredet sin proceshukommelsesgrænse på <xliff:g id="SIZE">%2$s</xliff:g>. En heap dump er tilgængelig og kan deles med udvikleren. Vær forsigtig: Denne heap dump kan indeholde dine personlige oplysninger, som appen har adgang til."</string>
<string name="sendText" msgid="5209874571959469142">"Vælg en handling for teksten"</string>
<string name="volume_ringtone" msgid="6885421406845734650">"Lydstyrke for opkald"</string>
- <string name="volume_music" msgid="5421651157138628171">"Medielydstyrke"</string>
+ <string name="volume_music" msgid="5421651157138628171">"Lydstyrke for medier"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Afspilning via Bluetooth"</string>
<string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Lydløs ringetone er angivet"</string>
<string name="volume_call" msgid="3941680041282788711">"Lydstyrke for opkald"</string>
<string name="volume_bluetooth_call" msgid="2002891926351151534">"Lydstyrke for Bluetooth under opkald"</string>
<string name="volume_alarm" msgid="1985191616042689100">"Lydstyrke for alarm"</string>
- <string name="volume_notification" msgid="2422265656744276715">"Lydstyrke for meddelelser"</string>
+ <string name="volume_notification" msgid="2422265656744276715">"Lydstyrke for underretninger"</string>
<string name="volume_unknown" msgid="1400219669770445902">"Lydstyrke"</string>
<string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"Lydstyrke for bluetooth"</string>
<string name="volume_icon_description_ringer" msgid="3326003847006162496">"Lydstyrke for ringetone"</string>
<string name="volume_icon_description_incall" msgid="8890073218154543397">"Lydstyrke for opkald"</string>
- <string name="volume_icon_description_media" msgid="4217311719665194215">"Medielydstyrke"</string>
- <string name="volume_icon_description_notification" msgid="7044986546477282274">"Lydstyrke for meddelelser"</string>
+ <string name="volume_icon_description_media" msgid="4217311719665194215">"Lydstyrke for medier"</string>
+ <string name="volume_icon_description_notification" msgid="7044986546477282274">"Lydstyrke for underretninger"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Standardringetone"</string>
<string name="ringtone_default_with_actual" msgid="1767304850491060581">"Standard (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
@@ -1609,7 +1619,7 @@
<string name="package_updated_device_owner" msgid="1847154566357862089">"Opdateret af din administrator"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Slettet af din administrator"</string>
<string name="battery_saver_description" msgid="1960431123816253034">"Batterisparefunktionen hjælper med at forlænge batteriets levetid ved at reducere enhedens ydeevne og begrænse vibration, placeringstjenester og det meste baggrundsdata. E-mail, beskedfunktioner og andre apps, der benytter synkronisering, opdateres muligvis ikke, medmindre du åbner dem.\n\nBatterisparefunktionen slukker automatisk, når enheden oplader."</string>
- <string name="data_saver_description" msgid="6015391409098303235">"Datasparefunktion forhindrer nogle apps i at sende eller modtage data i baggrunden for at reducere dataforbruget. En app, der er i brug, kan få adgang til data, men gør det måske ikke så ofte. Dette kan f.eks. betyde, at billeder ikke vises, før du trykker på dem."</string>
+ <string name="data_saver_description" msgid="6015391409098303235">"Datasparefunktionen forhindrer nogle apps i at sende eller modtage data i baggrunden for at reducere dataforbruget. En app, der er i brug, kan få adgang til data, men gør det måske ikke så ofte. Dette kan f.eks. betyde, at billeder ikke vises, før du trykker på dem."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Vil du slå Datasparefunktion til?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Slå til"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
@@ -1731,13 +1741,13 @@
<string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"USB-fejlretning"</string>
<string name="time_picker_hour_label" msgid="2979075098868106450">"time"</string>
<string name="time_picker_minute_label" msgid="5168864173796598399">"minut"</string>
- <string name="time_picker_header_text" msgid="143536825321922567">"Indstil klokkeslæt"</string>
+ <string name="time_picker_header_text" msgid="143536825321922567">"Angiv klokkeslæt"</string>
<string name="time_picker_input_error" msgid="7574999942502513765">"Angiv et gyldigt klokkeslæt"</string>
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Angiv klokkeslæt"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skift til teksttilstand for at angive klokkeslæt."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skift til urtilstand for at angive klokkeslæt."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Valgmuligheder for AutoFyld"</string>
- <string name="autofill_save_accessibility_title" msgid="7244365268417107822">"Gem til AutoFyld"</string>
+ <string name="autofill_save_accessibility_title" msgid="7244365268417107822">"Gem i AutoFyld"</string>
<string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Indhold kan ikke udfyldes automatisk"</string>
<string name="autofill_save_title" msgid="3345527308992082601">"Vil du gemme i <b><xliff:g id="LABEL">%1$s</xliff:g></b>?"</string>
<string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vil du gemme <xliff:g id="TYPE">%1$s</xliff:g> i <b><xliff:g id="LABEL">%2$s</xliff:g></b>?"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 347ebca..5a70d9b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Warnmeldungen"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo für Einzelhandel"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-Verbindung"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Zu \"Privat\" wechseln"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 4d93e5f..0cc6dc6 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ειδοποιήσεις"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Επίδειξη λιανικής"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Σύνδεση USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
<string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Μετάβαση σε προσωπικό προφίλ"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index aa08377..4976b03 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB connection"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index aa08377..4976b03 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB connection"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index aa08377..4976b03 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB connection"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 29a0adc..5515ae1 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo para punto de venta"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Conexión USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Cambiar al perfil personal"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 02c91db..33c0e5c 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo para tiendas"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Conexión USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Cambiar a perfil personal"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index cb63659..1c76b3f 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Poedemo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-ühendus"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Lülita isiklikule profiilile"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 3c79b78..78aed23 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Saltzaileentzako demoa"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB konexioa"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistema"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Aldatu profil pertsonalera"</string>
@@ -289,7 +299,7 @@
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"atzitu bizi-konstanteei buruzko sentsore-datuak"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Eskuratu leihoko edukia"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Arakatu irekita daukazun leihoko edukia."</string>
- <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktibatu ukipen bidez arakatzeko eginbidea"</string>
+ <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktibatu \"Arakatu ukituta\""</string>
<string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Sakatutako elementuak ozen esango dira eta pantaila keinu bidez arakatu ahal izango da."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Behatu idazten duzun testua"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Ez da salbuespenik egiten datu pertsonalekin, hala nola, kreditu-txartelen zenbakiekin eta pasahitzekin."</string>
@@ -1477,7 +1487,7 @@
<string name="user_switched" msgid="3768006783166984410">"Uneko erabiltzailea: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzailera aldatzen…"</string>
<string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzailearen saioa amaitzen…"</string>
- <string name="owner_name" msgid="2716755460376028154">"jabea"</string>
+ <string name="owner_name" msgid="2716755460376028154">"Jabea"</string>
<string name="error_message_title" msgid="4510373083082500195">"Errorea"</string>
<string name="error_message_change_not_allowed" msgid="1238035947357923497">"Administratzaileak ez du eman aldaketa egiteko baimena"</string>
<string name="app_not_found" msgid="3429141853498927379">"Ez da ekintza gauza dezakeen aplikaziorik aurkitu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index beef14c..cd8e750 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"هشدارها"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"نمونه برای خردهفروشان"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"اتصال USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
<string name="android_system_label" msgid="6577375335728551336">"سیستم Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"رفتن به نمایه شخصی"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 44614d7..5690669 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ilmoitukset"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Esittelytila"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-yhteys"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Siirry henkilökohtaiseen profiiliin"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 20780fd..7797274 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Démo en magasin"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Connexion USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
<string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 65f8d78..761947e 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Démonstration en magasin"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Connexion USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
<string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index cb2ad8f..2c58acb 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -29,10 +29,10 @@
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> días"</string>
<string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> hrs"</string>
- <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
<string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hrs"</string>
- <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
- <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
<string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
<string name="durationMinute" msgid="7155301744174623818">"<xliff:g id="MINUTES">%1$d</xliff:g> minuto"</string>
<string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> seg"</string>
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demostración comercial"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"conexión USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Cambiar ao perfil persoal"</string>
@@ -293,8 +303,8 @@
<string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Os elementos que toques pronunciaranse en voz alta e a pantalla poderá explorarse mediante xestos."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Observar o texto que escribes"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inclúe datos persoais como números e contrasinais de tarxetas de crédito."</string>
- <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlar ampliación da pantalla"</string>
- <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla o nivel do zoom e o posicionamento da pantalla"</string>
+ <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlar a ampliación da pantalla"</string>
+ <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla o nivel do zoom e o posicionamento da pantalla."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar xestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Podes tocar, pasar o dedo, beliscar e realizar outros xestos."</string>
<string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Xestos de impresión dixital"</string>
@@ -1609,7 +1619,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"Instalado polo teu administrador"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Actualizado polo teu administrador"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Eliminado polo teu administrador"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"Para axudar a mellorar a duración da batería, a función aforro de batería reduce o rendemento do teu dispositivo e limita a vibración, os servizos de localización e a maioría dos datos en segundo plano. É posible que o correo electrónico, as mensaxes e outras aplicacións que dependen da sincronización non se actualicen a menos que os abras. \n\nA función aforro de batería desactívase automaticamente cando pos a cargar o teu dispositivo."</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"Para axudar a mellorar a duración da batería, a función de aforro da batería reduce o rendemento do teu dispositivo e limita a vibración, os servizos de localización e a maioría dos datos en segundo plano. É posible que o correo electrónico, as mensaxes e outras aplicacións que dependen da sincronización non se actualicen a menos que os abras. \n\nA función de aforro da batería desactívase automaticamente cando pos a cargar o teu dispositivo."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Para contribuír a reducir o uso de datos, o Economizador de datos impide que algunhas aplicacións envíen ou reciban datos en segundo plano. Cando esteas utilizando unha aplicación, esta poderá acceder aos datos, pero é posible que o faga con menos frecuencia. Por exemplo, é posible que as imaxes non se mostren ata que as toques."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Queres activar o economizador de datos?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Activar"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index f70639f..77f7212 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"રિટેલ ડેમો"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB કનેક્શન"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"સુરક્ષિત મોડ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android સિસ્ટમ"</string>
<string name="user_owner_label" msgid="1119010402169916617">"વ્યક્તિગત પર સ્વિચ કરો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 556ba9e..0a672ca 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"सूचनाएं"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"खुदरा डेमो"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB कनेक्शन"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android सिस्टम"</string>
<string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफ़ाइल में स्विच करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index c8083e7..48f4cf7 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -268,6 +268,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Prodajni demo-način"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB veza"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Prijeđite na osobni"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d528e94..8af3ff5 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Értesítések"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Kiskereskedelmi bemutató"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-kapcsolat"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Átváltás személyes profilra"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index f33e777..2ca708d 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ծանուցումներ"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Խանութի ցուցադրական ռեժիմ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB կապակցում"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Անցնել անհատական պրոֆիլին"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 9ba2120b..aa325ac 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Notifikasi"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo promo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Sambungan USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Beralih ke Pribadi"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 30d83e1..e37862b 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Tilkynningar"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Kynningarútgáfa fyrir verslanir"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-tenging"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Örugg stilling"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android kerfið"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Skipta yfir í persónulegt snið"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 61be91c..8057a06 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Avvisi"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo retail"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Connessione USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Passa al profilo personale"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 18518f8..504d3ad 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"הדגמה לקמעונאים"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"חיבור USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
<string name="android_system_label" msgid="6577375335728551336">"מערכת Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"עבור ל\'אישי\'"</string>
@@ -1009,7 +1019,7 @@
<string name="delete" msgid="6098684844021697789">"מחק"</string>
<string name="copyUrl" msgid="2538211579596067402">"העתק כתובת אתר"</string>
<string name="selectTextMode" msgid="1018691815143165326">"בחר טקסט"</string>
- <string name="undo" msgid="7905788502491742328">"בטל"</string>
+ <string name="undo" msgid="7905788502491742328">"ביטול"</string>
<string name="redo" msgid="7759464876566803888">"בצע מחדש"</string>
<string name="autofill" msgid="3035779615680565188">"מילוי אוטומטי"</string>
<string name="textSelectionCABTitle" msgid="5236850394370820357">"בחירת טקסט"</string>
@@ -1066,7 +1076,7 @@
<string name="aerr_application_repeated" msgid="3146328699537439573">"האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> נעצרת שוב ושוב"</string>
<string name="aerr_process_repeated" msgid="6235302956890402259">"האפליקציה <xliff:g id="PROCESS">%1$s</xliff:g> נעצרת שוב ושוב"</string>
<string name="aerr_restart" msgid="7581308074153624475">"פתח שוב את האפליקציה"</string>
- <string name="aerr_report" msgid="5371800241488400617">"שלח משוב"</string>
+ <string name="aerr_report" msgid="5371800241488400617">"משוב"</string>
<string name="aerr_close" msgid="2991640326563991340">"סגור"</string>
<string name="aerr_mute" msgid="1974781923723235953">"השתק עד הפעלה מחדש של המכשיר"</string>
<string name="aerr_wait" msgid="3199956902437040261">"המתן"</string>
@@ -1181,7 +1191,7 @@
<string name="sms_short_code_details" msgid="5873295990846059400">"הדבר "<b>"עלול לגרום לחיובים"</b>" בחשבון המכשיר הנייד שלך."</string>
<string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"הדבר יגרום לחיובים בחשבון המכשיר הנייד שלך."</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"שלח"</string>
- <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"בטל"</string>
+ <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"ביטול"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"זכור את הבחירה שלי"</string>
<string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"ניתן לשנות זאת מאוחר יותר ב\'הגדרות\' > \'אפליקציות\'"</string>
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"אפשר תמיד"</string>
@@ -1198,7 +1208,7 @@
<string name="carrier_app_notification_title" msgid="8921767385872554621">"ה-SIM החדש הוכנס"</string>
<string name="carrier_app_notification_text" msgid="1132487343346050225">"הקש כדי להגדיר"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"הגדרת שעה"</string>
- <string name="date_picker_dialog_title" msgid="5879450659453782278">"הגדר תאריך"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"הגדרת תאריך"</string>
<string name="date_time_set" msgid="5777075614321087758">"הגדר"</string>
<string name="date_time_done" msgid="2507683751759308828">"בוצע"</string>
<string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"חדש: "</font></string>
@@ -1223,7 +1233,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"שתף"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"לא, אין מצב"</string>
<string name="select_input_method" msgid="8547250819326693584">"שינוי מקלדת"</string>
- <string name="show_ime" msgid="2506087537466597099">"השאר אותו במסך בזמן שהמקלדת הפיזית פעילה"</string>
+ <string name="show_ime" msgid="2506087537466597099">"תישאר במסך בזמן שהמקלדת הפיזית פעילה"</string>
<string name="hardware" msgid="194658061510127999">"הצג מקלדת וירטואלית"</string>
<string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"הגדרת מקלדת פיזית"</string>
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"הקש כדי לבחור שפה ופריסה"</string>
@@ -1358,13 +1368,13 @@
<string name="sync_undo_deletes" msgid="2941317360600338602">"בטל את פעולות המחיקה"</string>
<string name="sync_do_nothing" msgid="3743764740430821845">"אל תעשה דבר כרגע"</string>
<string name="choose_account_label" msgid="5655203089746423927">"בחר חשבון"</string>
- <string name="add_account_label" msgid="2935267344849993553">"הוסף חשבון"</string>
- <string name="add_account_button_label" msgid="3611982894853435874">"הוסף חשבון"</string>
+ <string name="add_account_label" msgid="2935267344849993553">"הוספת חשבון"</string>
+ <string name="add_account_button_label" msgid="3611982894853435874">"הוספת חשבון"</string>
<string name="number_picker_increment_button" msgid="2412072272832284313">"הוסף"</string>
<string name="number_picker_decrement_button" msgid="476050778386779067">"הפחת"</string>
<string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"<xliff:g id="VALUE">%s</xliff:g> גע והחזק."</string>
<string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"הסט למעלה כדי להוסיף ולמטה כדי להפחית."</string>
- <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"הוסף דקה"</string>
+ <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"הוספת דקה"</string>
<string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"הפחת דקה"</string>
<string name="time_picker_increment_hour_button" msgid="3652056055810223139">"הוסף שעה"</string>
<string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"הפחת שעה"</string>
@@ -1403,7 +1413,7 @@
<string name="storage_usb_drive_label" msgid="4501418548927759953">"כונן USB של <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb" msgid="3017954059538517278">"אחסון USB"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"ערוך"</string>
- <string name="data_usage_warning_title" msgid="3620440638180218181">"התראה לשימוש בנתונים"</string>
+ <string name="data_usage_warning_title" msgid="3620440638180218181">"התראה על שימוש בנתונים"</string>
<string name="data_usage_warning_body" msgid="6660692274311972007">"הקש כדי להציג נתוני שימוש והגדרות."</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"הגעת למגבלת הנתונים של 2G-3G"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"הגעת למגבלת הנתונים של 4G"</string>
@@ -1487,7 +1497,7 @@
<string name="kg_login_instructions" msgid="1100551261265506448">"כדי לבטל את הנעילה, היכנס באמצעות חשבון Google שלך."</string>
<string name="kg_login_username_hint" msgid="5718534272070920364">"שם משתמש (אימייל)"</string>
<string name="kg_login_password_hint" msgid="9057289103827298549">"סיסמה"</string>
- <string name="kg_login_submit_button" msgid="5355904582674054702">"היכנס"</string>
+ <string name="kg_login_submit_button" msgid="5355904582674054702">"כניסה"</string>
<string name="kg_login_invalid_input" msgid="5754664119319872197">"שם משתמש או סיסמה לא חוקיים."</string>
<string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"שכחת את שם המשתמש או הסיסמה?\nהיכנס לכתובת "<b>"google.com/accounts/recovery"</b></string>
<string name="kg_login_checking_password" msgid="1052685197710252395">"בודק חשבון…"</string>
@@ -1776,7 +1786,7 @@
<string name="demo_restarting_message" msgid="952118052531642451">"מאפס את המכשיר…"</string>
<string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"האם לאפס את המכשיר?"</string>
<string name="demo_user_inactivity_timeout_countdown" msgid="5675588824402569506">"תאבד את כל השינויים וההדגמה תתחיל שוב בעוד <xliff:g id="TIMEOUT">%1$s</xliff:g> שניות…"</string>
- <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"בטל"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"ביטול"</string>
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"אפס עכשיו"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> הושבת"</string>
<string name="conference_call" msgid="3751093130790472426">"שיחת ועידה"</string>
@@ -1793,9 +1803,9 @@
<string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"ניקוי באגים ב-USB"</string>
<string name="time_picker_hour_label" msgid="2979075098868106450">"שעה"</string>
<string name="time_picker_minute_label" msgid="5168864173796598399">"דקה"</string>
- <string name="time_picker_header_text" msgid="143536825321922567">"הגדר שעה"</string>
+ <string name="time_picker_header_text" msgid="143536825321922567">"הגדרת שעה"</string>
<string name="time_picker_input_error" msgid="7574999942502513765">"הזן שעה חוקית"</string>
- <string name="time_picker_prompt_label" msgid="7588093983899966783">"הקלד את השעה"</string>
+ <string name="time_picker_prompt_label" msgid="7588093983899966783">"מהי השעה הנכונה"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"העבר למצב קלט טקסט לצורך הזנת השעה"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"העבר למצב שעון לצורך הזנת השעה"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"אפשרויות מילוי אוטומטי"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index f5da17e..4f18bcb 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"販売店デモ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB 接続"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
<string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
<string name="user_owner_label" msgid="1119010402169916617">"個人用に切り替える"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index bf0f5da..31cd59b 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"გაფრთხილებები"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"დემო-რეჟიმი საცალო მოვაჭრეებისთვის"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB კავშირი"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
<string name="user_owner_label" msgid="1119010402169916617">"პირად პროფილზე გადართვა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 7b30f28..c512e43 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Дабылдар"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Бөлшек саудаға арналған демо нұсқасы"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB байланысы"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Қауіпсіз режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android жүйесі"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Жекеге ауысу"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 59c8c20..64306fd 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"ការជូនដំណឹង"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"របៀបដាក់បង្ហាញក្នុងហាង"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"ការតភ្ជាប់ USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"របៀបសុវត្ថិភាព"</string>
<string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"ប្តូរទៅផ្ទាល់ខ្លួន"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 906c88c..aaabd91 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"ಎಚ್ಚರಿಕೆಗಳು"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"ರಿಟೇಲ್ ಡೆಮೋ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB ಸಂಪರ್ಕ"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"ಸುರಕ್ಷಿತ ಮೋಡ್"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android ಸಿಸ್ಟಂ"</string>
<string name="user_owner_label" msgid="1119010402169916617">"ವೈಯಕ್ತಿಕಗೆ ಬದಲಿಸಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index db2e038..ab61857 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"소매 데모"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB 연결"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
<string name="user_owner_label" msgid="1119010402169916617">"개인으로 전환"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 05ca65e..a24bd7f 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Чекене соода дүкөнү үчүн демо режим"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB аркылуу туташуу"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Коопсуз режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android тутуму"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Жеке профилге которулуу"</string>
@@ -1412,7 +1422,7 @@
<string name="media_route_chooser_title" msgid="1751618554539087622">"Түзмөккө туташуу"</string>
<string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Сырткы экранга чыгаруу"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"Түзмөктөр изделүүдө..."</string>
- <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Тууралоолор"</string>
+ <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Жөндөөлөр"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Ажыратуу"</string>
<string name="media_route_status_scanning" msgid="7279908761758293783">"Скандоодо..."</string>
<string name="media_route_status_connecting" msgid="6422571716007825440">"Туташууда..."</string>
@@ -1466,7 +1476,7 @@
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Алып салуу"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Сунушталган деңгээлден да катуулатып уккуңуз келеби?\n\nМузыканы узакка чейин катуу уксаңыз, угууңуз начарлап кетиши мүмкүн."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"Атайын мүмкүнчүлүктөр функциясынын кыска жолу колдонулсунбу?"</string>
- <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"Кыска жол функциясы күйгүзүлгөн учурда үн көзөмөлдөөчү баскычтарды басып, 3 секунд кармап турсаңыз, атайын мүмкүнчүлүктөр функциясы иштетилет.\n\n Учурдагы атайын мүмкүнчүлүктөр функциясы:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Функцияны Жөндөөлөр > атайын мүмкүнчүлүктөр бөлүмүнөн өзгөртө аласыз."</string>
+ <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн, анын кыска жолу күйгүзүлгөндө, үндү катуулатуу/акырындатуу баскычын үч секунддай кое бербей басып туруңуз.\n\n Учурдагы атайын мүмкүнчүлүктөрдүн жөндөөлөрү:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nЖөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнөн өзгөртө аласыз."</string>
<string name="disable_accessibility_shortcut" msgid="627625354248453445">"Кыска жолду өчүрүү"</string>
<string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"Кыска жолду колдонуу"</string>
<string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"Атайын мүмкүнчүлүктөр кыска жолу <xliff:g id="SERVICE_NAME">%1$s</xliff:g> кызматын күйгүздү"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 4f2eb19..d162fe0 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"ການເຕືອນ"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"ເດໂມສຳລັບຮ້ານຂາຍ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"ການເຊື່ອມຕໍ່ USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"ສະລັບໄປໂປຣໄຟລ໌ສ່ວນຕົວ"</string>
@@ -1608,7 +1618,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"ຖືກຕິດຕັ້ງໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"ຖືກອັບໂຫລດໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"ຖືກລຶບອອກໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"ເພື່ອຊ່ວຍເພີ່ມອາຍຸແບັດເຕີຣີ, ຕົວປະຢັດໄຟແບັດເຕີຣີຫຼຸດປະສິດທິພາບການເຮັດວຽກຂອງອຸປະກອນຂອງທ່ານລົງ ແລະຈຳກັດການສັ່ນ, ການບໍລິການຫາທີ່ຕັ້ງ, ແລະຂໍ້ມູນພື້ນຫຼັງເກືອບທັງໝົດ. ອີເມວ, ການສົ່ງຂໍ້ຄວາມ, ແລະແອັບອື່ນໆທີ່ອາໄສການຊິງຄ໌ອາດຈະບໍ່ອັບເດດ ນອກຈາກວ່າທ່ານເປີດມັນ.\n\nຕົວປະຢັດໄຟແບັດເຕີຣີຈະປິດອັດຕະໂນມັດ ເມື່ອອຸປະກອນຂອງທ່ານກຳລັງສາກຢູ່."</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"ເພື່ອຊ່ວຍເພີ່ມອາຍຸແບັດເຕີຣີ, ຕົວປະຢັດໄຟແບັດເຕີຣີຫຼຸດປະສິດທິພາບການເຮັດວຽກຂອງອຸປະກອນຂອງທ່ານລົງ ແລະຈຳກັດການສັ່ນ, ການບໍລິການຫາທີ່ຕັ້ງ ແລະ ຂໍ້ມູນພື້ນຫຼັງເກືອບທັງໝົດ. ອີເມວ, ການສົ່ງຂໍ້ຄວາມ, ແລະ ແອັບອື່ນໆທີ່ອາໄສການຊິ້ງຂໍ້ມູນອາດຈະບໍ່ອັບເດດ ນອກຈາກວ່າທ່ານເປີດມັນ.\n\nຕົວປະຢັດໄຟແບັດເຕີຣີຈະປິດອັດຕະໂນມັດເມື່ອທ່ານສາກໄຟອຸປະກອນ."</string>
<string name="data_saver_description" msgid="6015391409098303235">"ເພື່ອຊ່ວຍຫຼຸດຜ່ອນການນຳໃຊ້ຂໍ້ມູນ, ຕົວປະຢັດຂໍ້ມູນຈະປ້ອງກັນບໍ່ໃຫ້ບາງແອັບສົ່ງ ຫຼື ຮັບຂໍ້ມູນໃນພື້ນຫຼັງ. ແອັບໃດໜຶ່ງທີ່ທ່ານກຳລັງໃຊ້ຢູ່ຈະສາມາດເຂົ້າເຖິງຂໍ້ມູນໄດ້ ແຕ່ອາດເຂົ້າເຖິງໄດ້ຖີ່ໜ້ອຍລົງ. ນີ້ອາດໝາຍຄວາມວ່າ ຮູບພາບຕ່າງໆອາດບໍ່ສະແດງຈົນກວ່າທ່ານຈະແຕະໃສ່ກ່ອນ."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"ເປີດໃຊ້ຕົວປະຢັດຂໍ້ມູນບໍ?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"ເປີດໃຊ້"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 99ef41ca..0a62d62 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstracinė versija mažmenininkams"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB jungtis"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
<string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Perjungti į asmeninį režimą"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index c01ab61..3bcce6f 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -268,6 +268,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstrācijas versija veikaliem"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB savienojums"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Pārslēgt personīgo profilu"</string>
diff --git a/core/res/res/values-mcc204/config.xml b/core/res/res/values-mcc204/config.xml
new file mode 100644
index 0000000..790f768
--- /dev/null
+++ b/core/res/res/values-mcc204/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <bool name="config_use_sim_language_file">true</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 63431a4..3049488 100755
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -36,4 +36,7 @@
<bool name="config_auto_attach_data_on_creation">false</bool>
<string translatable="false" name="prohibit_manual_network_selection_in_gobal_mode">true</string>
+
+ <bool name="config_use_sim_language_file">true</bool>
+
</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index a210f5b..6f85081 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -62,4 +62,6 @@
<string translatable="false" name="prohibit_manual_network_selection_in_gobal_mode">true</string>
+ <bool name="config_use_sim_language_file">true</bool>
+
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index bb2527c..b5e8c90 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Предупредувања"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Демонстрација за малопродажба"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-врска"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Безбеден режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Систем Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Префрлете на личен профил"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 178bc3d..5dbb334 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"അലേർട്ടുകൾ"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"റീട്ടെയിൽ ഡെമോ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB കണക്ഷൻ"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"സുരക്ഷിത മോഡ്"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android സിസ്റ്റം"</string>
<string name="user_owner_label" msgid="1119010402169916617">"വ്യക്തിഗത പ്രൊഫൈലിലേക്ക് മാറുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 5cf213a..765aa5d 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Жижиглэнгийн жишээ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB холболт"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
<string name="user_owner_label" msgid="1119010402169916617">"\"Хувийн\" руу шилжих"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 7f41449..4191828 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"किरकोळ डेमो"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB कनेक्शन"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android सिस्टम"</string>
<string name="user_owner_label" msgid="1119010402169916617">"वैयक्तिकवर स्विच करा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5d5c4f3..d4cc2d3 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Makluman"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Tunjuk cara runcit"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Sambungan USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Beralih kepada Peribadi"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index d880658..1d89730 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"သတိပေးချက်များ"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"လက်လီအရောင်းဆိုင် သရုပ်ပြမှု"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB ချိတ်ဆက်မှု"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android စနစ်"</string>
<string name="user_owner_label" msgid="1119010402169916617">"ကိုယ်ပိုင်သီးသန့်အဖြစ် ပြောင်းပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index c659435..ab32ff8 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Varsler"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Butikkdemo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-tilkobling"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Bytt til den personlige profilen"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 19e425a..33466bc 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"अलर्टहरू"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"खुद्रा बिक्री सम्बन्धी डेमो"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB जडान"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
<string name="android_system_label" msgid="6577375335728551336">"एन्ड्रोइड प्रणाली"</string>
<string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफाइलमा स्विच गर्नुहोस्"</string>
@@ -1288,7 +1298,7 @@
<string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट अप गर्न ट्याप गर्नुहोस्"</string>
<string name="upload_file" msgid="2897957172366730416">"फाइल छान्नुहोस्"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"कुनै फाइल छानिएको छैन"</string>
- <string name="reset" msgid="2448168080964209908">"पुनःसेट गर्नु"</string>
+ <string name="reset" msgid="2448168080964209908">"रिसेट गर्नुहोस्"</string>
<string name="submit" msgid="1602335572089911941">"पेस गर्नुहोस्"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"कार मोड सक्षम पारियो।"</string>
<string name="car_mode_disable_notification_message" msgid="6301524980144350051">"कार मोडबाट बाहिर निस्कन ट्याप गर्नुहोस्।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 4875b9f..c82219c 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Meldingen"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo voor de detailhandel"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-verbinding"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Overschakelen naar persoonlijk profiel"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 78a5517..5c606ae 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"ਸੁਚੇਤਨਾਵਾਂ"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"ਪ੍ਰਚੂਨ ਸਟੋਰਾਂ ਲਈ ਡੈਮੋ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB ਕਨੈਕਸ਼ਨ"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"ਸੁਰੱਖਿਅਤ ਮੋਡ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
<string name="user_owner_label" msgid="1119010402169916617">"ਨਿੱਜੀ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 5f01dd4..7386f2d 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerty"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Tryb demo dla sklepów"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Połączenie USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
<string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Włącz profil osobisty"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 05ac675..d5dc395 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstração na loja"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Conexão USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e78386e..1f297c2 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstração para retalho"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Ligação USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Mudar para pessoal"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 05ac675..d5dc395 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstração na loja"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Conexão USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 7785e72b..3a2c38d 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -268,6 +268,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerte"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstrație comercială"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Conexiune USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Comutați la Personal"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index b84b808..0bc71eb 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Деморежим для магазина"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-подключение"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Перейти в личный профиль"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 7b0478b..b7e695a 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"සිල්ලර ආදර්ශනය"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB සම්බන්ධතාවය"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"ආරක්ෂිත ආකාරය"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android පද්ධතිය"</string>
<string name="user_owner_label" msgid="1119010402169916617">"පුද්ගලික වෙත මාරු වන්න"</string>
@@ -1610,7 +1620,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"ඔබගේ පරිපාලක මඟින් ස්ථාපනය කර ඇත"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"ඔබගේ පරිපාලක මඟින් යාවත්කාලීන කර ඇත"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"ඔබගේ පරිපාලක මඟින් මකා දමා ඇත"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"බැටරි ආයු කාලය වැඩිදියුණු කිරීමට උදවු කිරීමට, බැටරි සුරැකුම ඔබේ උපාංගයේ ක්රියාකාරීත්වය අඩුකරන අතර කම්පනය, පිහිටීම් සේවා, සහ බොහෝමයක් පසුබිම් දත්ත සීමා කරයි. ඔබ ඒවා විවෘත නොකරන්නේ නම් මිස ඊමේල්, පණිවිඩකරණය, සහ සමමුහුර්ත කිරීම මත රඳා පවතින වෙනත් යෙදුම් යාවත්කාලීන නොවිය හැකිය.\n\nඔබේ උපාංගය ආරෝපණය වන විට බැටරි සුරැකුම ස්වයංක්රියව අක්රිය වේ."</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"බැටරි ආයු කාලය වැඩිදියුණු කිරීමට උදවු කිරීමට, බැටරි සුරැකුම ඔබේ උපාංගයේ ක්රියාකාරීත්වය අඩුකරන අතර කම්පනය, පිහිටීම් සේවා, සහ බොහෝමයක් පසුබිම් දත්ත සීමා කරයි. ඔබ ඒවා විවෘත නොකරන්නේ නම් මිස ඊ-තැපැල්, පණිවිඩකරණය, සහ සමමුහුර්ත කිරීම මත රඳා පවතින වෙනත් යෙදුම් යාවත්කාලීන නොවිය හැකිය.\n\nඔබේ උපාංගය ආරෝපණය වන විට බැටරි සුරැකුම ස්වයංක්රියව ක්රියාත්මක වේ."</string>
<string name="data_saver_description" msgid="6015391409098303235">"දත්ත භාවිතය අඩු කිරීමට උදවු වීමට, දත්ත සුරැකුම සමහර යෙදුම් පසුබිමින් දත්ත යැවීම සහ ලබා ගැනීම වළක්වයි. ඔබ දැනට භාවිත කරන යෙදුමකට දත්ත වෙත පිවිසීමට හැකිය, නමුත් එසේ කරන්නේ කලාතුරකින් විය හැකිය. මෙයින් අදහස් වන්නේ, උදාහරණයක් ලෙස, එම රූප ඔබ ඒවාට තට්ටු කරන තෙක් සංදර්ශනය නොවන බවය."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"දත්ත සුරැකුම ක්රියාත්මක කරන්නද?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"ක්රියාත්මක කරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 8782dc9..018ea4e 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornenia"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Predajná ukážka"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Pripojenie USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Prepnúť na osobný"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index d6643d7..729612f 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Predstavitev za maloprodajo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Povezava USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Preklop na osebni profil"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 1bd2b74..563f4bd 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstrimi i shitjes me pakicë"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Lidhja USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Modaliteti i sigurisë"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemi \"android\""</string>
<string name="user_owner_label" msgid="1119010402169916617">"Ndryshoje te \"Personale\""</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 44abfb9..2d2cc70 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -268,6 +268,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Обавештења"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Режим демонстрације за малопродајне објекте"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB веза"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Пређи на Лични профил"</string>
@@ -1630,7 +1640,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"Инсталирао је администратор"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Ажурирао је администратор"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Избрисао је администратор"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"Да би продужила време трајања батерије, уштеда батерије смањује перформансе уређаја и ограничава вибрацију, услуге локације и већину позадинских података. Имејл, размена порука и друге апликације које се ослањају на синхронизацију можда неће да се ажурирају ако их не отворите.\n\nУштеда батерије се аутоматски искључује када се уређај пуни."</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"Да би продужила време трајања батерије, уштеда батерије смањује перформансе уређаја и ограничава вибрацију, услуге локације и већину позадинских података. Имејл, размена порука и друге апликације које се ослањају на синхронизацију неће се ажурирати док их не отворите.\n\nУштеда батерије се аутоматски искључује када се уређај пуни."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Да би се смањила потрошња података, Уштеда података спречава неке апликације да шаљу или примају податке у позадини. Апликација коју тренутно користите може да приступа подацима, али ће то чинити ређе. На пример, слике се неће приказивати док их не додирнете."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Укључити Уштеду података?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Укључи"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 7f3d212..c480df4 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Varningar"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo för återförsäljare"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB-anslutning"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Byt till din personliga profil"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 52fa3a2..cec75bc 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -263,6 +263,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Onyesho la duka la rejareja"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Muunganisho wa USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
<string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Badili uweke wasifu wa Binafsi"</string>
@@ -1735,7 +1745,7 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Badilisha iwe katika hali ya maandishi wakati wa kuweka muda."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Badilisha umbo liwe la saa ya mishale wakati wa kuweka muda."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Chaguo za kujaza otomatiki"</string>
- <string name="autofill_save_accessibility_title" msgid="7244365268417107822">"Hifadhi kwa ajili ya Kujaza kiotomatiki"</string>
+ <string name="autofill_save_accessibility_title" msgid="7244365268417107822">"Hifadhi kwa ajili ya Kujaza Kiotomatiki"</string>
<string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Maudhui hayawezi kujazwa kiotomatiki"</string>
<string name="autofill_save_title" msgid="3345527308992082601">"Ungependa kuhifadhi kwenye <b><xliff:g id="LABEL">%1$s</xliff:g></b>?"</string>
<string name="autofill_save_title_with_type" msgid="8637809388029313305">"Ungependa kuhifadhi <xliff:g id="TYPE">%1$s</xliff:g> kwenye <b><xliff:g id="LABEL">%2$s</xliff:g></b>?"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 18b097e..7062e98 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"விழிப்பூட்டல்கள்"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"விற்பனையாளர் டெமோ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB இணைப்பு"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"பாதுகாப்பு பயன்முறை"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android அமைப்பு"</string>
<string name="user_owner_label" msgid="1119010402169916617">"தனிப்பட்ட சுயவிவரத்திற்கு மாறு"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index d79e52f..31e2721 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"హెచ్చరికలు"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"రిటైల్ డెమో"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB కనెక్షన్"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"సురక్షిత మోడ్"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android సిస్టమ్"</string>
<string name="user_owner_label" msgid="1119010402169916617">"వ్యక్తిగతానికి మార్చు"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 2179f70..fd7158f 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"การสาธิตสำหรับผู้ค้าปลีก"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"การเชื่อมต่อ USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
<string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"เปลี่ยนไปใช้โปรไฟล์ส่วนตัว"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 90e57c1..e58f62f 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Koneksyon ng USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Lumipat sa Personal"</string>
@@ -277,7 +287,7 @@
<string name="permgroupdesc_calendar" msgid="3889615280211184106">"i-access ang iyong kalendaryo"</string>
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
<string name="permgroupdesc_sms" msgid="4656988620100940350">"magpadala at tumingin ng mga mensaheng SMS"</string>
- <string name="permgrouplab_storage" msgid="1971118770546336966">"Imbakan"</string>
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"Storage"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"i-access ang mga larawan, media at file sa iyong device"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Mikropono"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"mag-record ng audio"</string>
@@ -575,7 +585,7 @@
<string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Itakda ang pandaigdigang proxy ng device na gagamitin habang naka-enable ang patakaran. Ang may-ari ng device lang ang makakapagtakda sa pandaigdigang proxy."</string>
<string name="policylab_expirePassword" msgid="5610055012328825874">"Itakda screen lock password expiration"</string>
<string name="policydesc_expirePassword" msgid="5367525762204416046">"Baguhin kung gaano kadalas dapat palitan ang password, PIN o pattern sa screen lock."</string>
- <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Itakda pag-encrypt ng imbakan"</string>
+ <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Itakda pag-encrypt ng storage"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Hilinging naka-encrypt ang nakaimbak na data ng app."</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"Huwag paganahin mga camera"</string>
<string name="policydesc_disableCamera" msgid="2306349042834754597">"Pigilan ang paggamit sa lahat ng camera ng device."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 5cc96b6..e395435 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Uyarılar"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Mağaza demo"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB bağlantısı"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Kişisel Profile Geç"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0fb047a..09cec2a 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -271,6 +271,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Сповіщення"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Демо-режим для роздрібної торгівлі"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"З’єднання USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Перейти в особистий профіль"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 5c73b69..225faa6 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"الرٹس"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"ریٹیل ڈیمو"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB کنکشن"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"حفاظتی وضع"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android سسٹم"</string>
<string name="user_owner_label" msgid="1119010402169916617">"ذاتی پر سوئچ کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 1f23149..0e7d4ff 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo rejim"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB orqali ulanish"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Xavfsiz usul"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android tizimi"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Shaxsiy profilga o‘tish"</string>
@@ -722,7 +732,7 @@
<string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"Televizorda SIM karta yo‘q."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefoningizda SIM karta yo‘q."</string>
<string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"SIM kartani soling."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM karta solinmagan yoki uni o‘qib bo‘lmaydi. SIM kartani soling."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM karta solinmagan yoki u yaroqsiz. SIM kartani soling."</string>
<string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Foydalanib bo‘lmaydigan SIM karta."</string>
<string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"SIM kartangiz butunlay bloklab qo‘yilgan.\n Yangi SIM karta olish uchun aloqa operatoringiz bilan bog‘laning."</string>
<string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"Avvalgi musiqa"</string>
@@ -1174,7 +1184,7 @@
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB jihozga ulangan"</string>
<string name="usb_notification_message" msgid="3370903770828407960">"Boshqa parametrlarini ko‘rish uchun bosing."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB orqali nosozliklarni tuzatish"</string>
- <string name="adb_active_notification_message" msgid="4948470599328424059">"O‘chirib qo‘yish uchun bu yerga bosing."</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"Faolsizlantirish uchun bu yerga bosing."</string>
<!-- no translation found for adb_active_notification_message (8470296818270110396) -->
<skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Xatoliklar hisoboti olinmoqda…"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index fa103cc..f2ba671 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Giới thiệu bán lẻ"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Kết nối USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
<string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Chuyển sang Cá nhân"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index dc66d6f..6e35e3f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"提醒"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"零售演示模式"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB 连接"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
<string name="user_owner_label" msgid="1119010402169916617">"切换到“个人”"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 63cf0b1..74f4987 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -72,8 +72,8 @@
<string name="ClirMmi" msgid="7784673673446833091">"本機號碼"</string>
<string name="ColpMmi" msgid="3065121483740183974">"連接線識別功能"</string>
<string name="ColrMmi" msgid="4996540314421889589">"連接線識別限制"</string>
- <string name="CfMmi" msgid="5123218989141573515">"來電轉接"</string>
- <string name="CwMmi" msgid="9129678056795016867">"來電待接"</string>
+ <string name="CfMmi" msgid="5123218989141573515">"來電轉駁"</string>
+ <string name="CwMmi" msgid="9129678056795016867">"來電等候"</string>
<string name="BaMmi" msgid="455193067926770581">"通話限制"</string>
<string name="PwdMmi" msgid="7043715687905254199">"密碼更改"</string>
<string name="PinMmi" msgid="3113117780361190304">"更改 PIN"</string>
@@ -100,13 +100,13 @@
<string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"無法連接網絡"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="4164230263214915351">"如要改善接收品質,請前往 [系統] > [網絡與互聯網] > [流動網絡] > [偏好的網絡類型],然後變更所選的網絡類型。"</string>
<string name="notification_channel_network_alert" msgid="4427736684338074967">"通知"</string>
- <string name="notification_channel_call_forward" msgid="2419697808481833249">"來電轉接"</string>
+ <string name="notification_channel_call_forward" msgid="2419697808481833249">"來電轉駁"</string>
<string name="notification_channel_emergency_callback" msgid="6686166232265733921">"緊急回撥模式"</string>
<string name="notification_channel_mobile_data_alert" msgid="6130875231721406231">"流動數據通知"</string>
<string name="notification_channel_sms" msgid="3441746047346135073">"短訊"</string>
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"留言訊息"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi 通話"</string>
- <string name="peerTtyModeFull" msgid="6165351790010341421">"對方曾要求 TTY 模式 (FULL)"</string>
+ <string name="peerTtyModeFull" msgid="6165351790010341421">"對方曾要求 TTY 完整模式"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"對方曾要求 TTY 模式 (HCO)"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"對方曾要求 TTY 模式 (VCO)"</string>
<string name="peerTtyModeOff" msgid="3280819717850602205">"對方曾要求 TTY 模式 (OFF)"</string>
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"零售示範"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB 連線"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
<string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 97962cf..87e98dd 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"快訊"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"零售商示範模式"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"USB 連線"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
<string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index bcad869e..a656e6c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -265,6 +265,16 @@
<string name="notification_channel_alerts" msgid="4496839309318519037">"Izexwayiso"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"Idemo yokuthenga"</string>
<string name="notification_channel_usb" msgid="9006850475328924681">"Ukuxhumeka kwe-USB"</string>
+ <!-- no translation found for notification_channel_foreground_service (6665375982962336520) -->
+ <skip />
+ <!-- no translation found for foreground_service_app_in_background (6826789589341671842) -->
+ <skip />
+ <!-- no translation found for foreground_service_apps_in_background (7150914856893450380) -->
+ <skip />
+ <!-- no translation found for foreground_service_tap_for_details (372046743534354644) -->
+ <skip />
+ <!-- no translation found for foreground_service_multiple_separator (4021901567939866542) -->
+ <skip />
<string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
<string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
<string name="user_owner_label" msgid="1119010402169916617">"Shintshela komuntu siqu"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c421514..cfe25b3 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -63,6 +63,12 @@
<!-- Drawable to be drawn over the view to mark it as autofilled-->
<attr name="autofilledHighlight" format="reference" />
+ <!-- Max width of the autofill data set picker as a fraction of the screen width -->
+ <attr name="autofillDatasetPickerMaxWidth" format="reference" />
+
+ <!-- Max height of the autofill data set picker as a fraction of the screen height -->
+ <attr name="autofillDatasetPickerMaxHeight" format="reference" />
+
<!-- Default disabled alpha for widgets that set enabled/disabled alpha programmatically. -->
<attr name="disabledAlpha" format="float" />
<!-- The alpha applied to the foreground color to create the primary text color. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b7bc7b7..ced22cc 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -784,13 +784,13 @@
<enum name="locked" value="14" />
</attr>
- <!-- Specify the configuration changes that trigger the system to restart the
+ <!-- Specify the configuration changes that trigger the system to recreate the
current activity if any of these configuration changes happen in the system.
The valid configuration changes include mcc and mnc which are the same with
- those in configChanges. By default from Android O, we don't restart the activity
+ those in configChanges. By default from Android O, we don't recreate the activity
even the app doesn't specify mcc or mnc in configChanges. If the app wants to
- restart, specify them in restartOnConfigChanges. -->
- <attr name="restartOnConfigChanges">
+ be recreated, specify them in recreateOnConfigChanges. -->
+ <attr name="recreateOnConfigChanges">
<!-- The IMSI MCC has changed, that is a SIM has been detected and
updated the Mobile Country Code. -->
<flag name="mcc" value="0x0001" />
@@ -817,15 +817,15 @@
<attr name="configChanges">
<!-- The IMSI MCC has changed, that is a SIM has been detected and
updated the Mobile Country Code. By default from Android O, we
- don't restart the activity even the app doesn't specify mcc in
- configChanges. If the app wants to restart, specify mcc in
- restartOnConfigChanges. -->
+ don't recreate the activity even the app doesn't specify mcc in
+ configChanges. If the app wants to recreate the activity, specify
+ mcc in recreateOnConfigChanges. -->
<flag name="mcc" value="0x0001" />
<!-- The IMSI MNC has changed, that is a SIM has been detected and
updated the Mobile Network Code. By default from Android O, we
- don't restart the activity even the app doesn't specify mnc in
- configChanges. If the app wants to restart, specify mnc in
- restartOnConfigChanges. -->
+ don't recreate the activity even the app doesn't specify mnc in
+ configChanges. If the app wants to recreate the acvitity, specify
+ mnc in recreateOnConfigChanges. -->
<flag name="mnc" value="0x0002" />
<!-- The locale has changed, that is the user has selected a new
language that text should be displayed in. -->
@@ -2048,7 +2048,7 @@
<attr name="launchMode" />
<attr name="screenOrientation" />
<attr name="configChanges" />
- <attr name="restartOnConfigChanges" />
+ <attr name="recreateOnConfigChanges" />
<attr name="permission" />
<attr name="multiprocess" />
<attr name="process" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index eb25ab3..eca748c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1299,9 +1299,9 @@
* Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.
- This must be set to a valid network recommendation app.
+ This must be set to a valid network recommendation app or empty.
-->
- <string name="config_defaultNetworkRecommendationProviderPackage" translatable="false">com.android.networkrecommendation</string>
+ <string name="config_defaultNetworkRecommendationProviderPackage" translatable="false"></string>
<!-- Whether to enable Hardware FLP overlay which allows Hardware FLP to be
replaced by an app at run-time. When disabled, only the
@@ -2877,4 +2877,17 @@
<!-- The apps that need to be hidden when they are disabled -->
<string-array name="config_hideWhenDisabled_packageNames"></string-array>
+
+ <!-- Additional non-platform defined global settings exposed to Instant Apps -->
+ <string-array name="config_allowedGlobalInstantAppSettings"></string-array>
+
+ <!-- Additional non-platform defined system settings exposed to Instant Apps -->
+ <string-array name="config_allowedSystemInstantAppSettings"></string-array>
+
+ <!-- Additional non-platform defined secure settings exposed to Instant Apps -->
+ <string-array name="config_allowedSecureInstantAppSettings"></string-array>
+
+ <!-- Handle volume keys directly in Window Manager without passing them to the foreground app -->
+ <bool name="config_handleVolumeKeysInWindowManager">false</bool>
+
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 54225c7..880e0e1 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -559,4 +559,8 @@
<dimen name="item_touch_helper_max_drag_scroll_per_frame">20dp</dimen>
<dimen name="item_touch_helper_swipe_escape_velocity">120dp</dimen>
<dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen>
+
+ <!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
+ <dimen name="autofill_dataset_picker_max_size">90%</dimen>
+
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d8b7850..42d3f27 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2786,7 +2786,7 @@
<public name="appCategory" />
<public name="autoSizeMaxTextSize" />
<public name="__removed2" />
- <public name="restartOnConfigChanges" />
+ <public name="recreateOnConfigChanges" />
<public name="certDigest" />
<public name="splitName" />
<public name="colorMode" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e633d66..9848485 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3155,6 +3155,11 @@
<string name="usb_accessory_notification_title">Connected to a USB accessory</string>
<!-- See USB_PREFERENCES. This is the message. -->
<string name="usb_notification_message">Tap for more options.</string>
+ <!-- USB_PREFERENCES: Notification for when a type-c USB audio accessory is attached but not supported. This is the title -->
+ <string name="usb_unsupported_audio_accessory_title">Audio accessory not supported</string>
+ <!-- Message of notification shown when a type-c USB audio accessory is attached but not supported. -->
+ <string name="usb_unsupported_audio_accessory_message">Tap for more info</string>
+
<!-- Title of notification shown when ADB is actively connected to the phone. -->
<string name="adb_active_notification_title">USB debugging connected</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bd70ca8..f3bd8c6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -239,7 +239,8 @@
<java-symbol type="attr" name="accessibilityFocusedDrawable"/>
<java-symbol type="attr" name="isLightTheme"/>
<java-symbol type="attr" name="autofilledHighlight"/>
-
+ <java-symbol type="attr" name="autofillDatasetPickerMaxWidth"/>
+ <java-symbol type="attr" name="autofillDatasetPickerMaxHeight"/>
<java-symbol type="bool" name="action_bar_embed_tabs" />
<java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
<java-symbol type="bool" name="config_avoidGfxAccel" />
@@ -1958,6 +1959,8 @@
<java-symbol type="string" name="usb_ptp_notification_title" />
<java-symbol type="string" name="usb_midi_notification_title" />
<java-symbol type="string" name="usb_supplying_notification_title" />
+ <java-symbol type="string" name="usb_unsupported_audio_accessory_title" />
+ <java-symbol type="string" name="usb_unsupported_audio_accessory_message" />
<java-symbol type="string" name="config_UsbDeviceConnectionHandling_component" />
<java-symbol type="string" name="vpn_text" />
<java-symbol type="string" name="vpn_text_long" />
@@ -2915,6 +2918,7 @@
<java-symbol type="string" name="autofill_save_type_email_address" />
<java-symbol type="drawable" name="autofill_dataset_picker_background" />
<java-symbol type="style" name="AutofillDatasetPicker" />
+ <java-symbol type="dimen" name="autofill_dataset_picker_max_size"/>
<!-- Accessibility fingerprint gestures -->
<java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
@@ -3013,4 +3017,10 @@
<java-symbol type="string" name="config_feedbackIntentNameKey" />
<java-symbol type="array" name="config_hideWhenDisabled_packageNames" />
+
+ <java-symbol type="array" name="config_allowedGlobalInstantAppSettings" />
+ <java-symbol type="array" name="config_allowedSystemInstantAppSettings" />
+ <java-symbol type="array" name="config_allowedSecureInstantAppSettings" />
+
+ <java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index e8fbf34..383ae5d 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -449,6 +449,10 @@
<item name="tooltipFrameBackground">@drawable/tooltip_frame</item>
<item name="tooltipForegroundColor">@color/bright_foreground_light</item>
<item name="tooltipBackgroundColor">@color/tooltip_background_light</item>
+
+ <!-- Autofill: max width/height of the dataset picker as a fraction of screen size -->
+ <item name="autofillDatasetPickerMaxWidth">@dimen/autofill_dataset_picker_max_size</item>
+ <item name="autofillDatasetPickerMaxHeight">@dimen/autofill_dataset_picker_max_size</item>
</style>
<!-- Variant of {@link #Theme} with no title bar -->
diff --git a/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java b/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java
new file mode 100644
index 0000000..9bbcd3d
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link DistroFormatVersion}.
+ */
+// TODO(nfuller) Move to CTS once this class is part of the SystemApi. http://b/31008728
+public class DistroFormatVersionTest {
+
+ @Test
+ public void equalsAndHashCode() {
+ DistroFormatVersion one = new DistroFormatVersion(1, 2);
+ assertEqualsContract(one, one);
+
+ DistroFormatVersion two = new DistroFormatVersion(1, 2);
+ assertEqualsContract(one, two);
+
+ DistroFormatVersion three = new DistroFormatVersion(2, 1);
+ assertFalse(one.equals(three));
+ }
+
+ @Test
+ public void parcelable() {
+ DistroFormatVersion version = new DistroFormatVersion(2, 3);
+
+ Parcel parcel = Parcel.obtain();
+ version.writeToParcel(parcel, 0 /* flags */);
+ parcel.setDataPosition(0);
+
+ DistroFormatVersion newVersion = DistroFormatVersion.CREATOR.createFromParcel(parcel);
+
+ assertEquals(version, newVersion);
+ }
+
+ @Test
+ public void supportsVersion() {
+ DistroFormatVersion deviceVersion = new DistroFormatVersion(2, 2);
+ assertTrue(deviceVersion.supports(deviceVersion));
+
+ DistroFormatVersion sameVersion = new DistroFormatVersion(2, 2);
+ assertTrue(deviceVersion.supports(sameVersion));
+
+ // Minor versions are backwards compatible.
+ DistroFormatVersion sameMajorNewerMinor = new DistroFormatVersion(2, 3);
+ assertTrue(deviceVersion.supports(sameMajorNewerMinor));
+ DistroFormatVersion sameMajorOlderMinor = new DistroFormatVersion(2, 1);
+ assertFalse(deviceVersion.supports(sameMajorOlderMinor));
+
+ // Major versions are not backwards compatible.
+ DistroFormatVersion newerMajor = new DistroFormatVersion(1, 2);
+ assertFalse(deviceVersion.supports(newerMajor));
+ DistroFormatVersion olderMajor = new DistroFormatVersion(3, 2);
+ assertFalse(deviceVersion.supports(olderMajor));
+ }
+
+ private static void assertEqualsContract(DistroFormatVersion one, DistroFormatVersion two) {
+ assertEquals(one, two);
+ assertEquals(one.hashCode(), two.hashCode());
+ }
+}
diff --git a/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java b/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java
new file mode 100644
index 0000000..2fbc9a1
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link DistroRulesVersion}.
+ */
+// TODO(nfuller) Move to CTS once this class is part of the SystemApi. http://b/31008728
+public class DistroRulesVersionTest {
+
+ @Test
+ public void equalsAndHashCode() {
+ DistroRulesVersion one = new DistroRulesVersion("2016a", 2);
+ assertEqualsContract(one, one);
+
+ DistroRulesVersion two = new DistroRulesVersion("2016a", 2);
+ assertEqualsContract(one, two);
+
+ DistroRulesVersion three = new DistroRulesVersion("2016b", 1);
+ assertFalse(one.equals(three));
+ }
+
+ @Test
+ public void parcelable() {
+ DistroRulesVersion version = new DistroRulesVersion("2016a", 2);
+
+ Parcel parcel = Parcel.obtain();
+ version.writeToParcel(parcel, 0 /* flags */);
+ parcel.setDataPosition(0);
+
+ DistroRulesVersion newVersion = DistroRulesVersion.CREATOR.createFromParcel(parcel);
+
+ assertEquals(version, newVersion);
+ }
+
+ @Test
+ public void isOlderThan() {
+ DistroRulesVersion deviceVersion = new DistroRulesVersion("2016b", 2);
+ assertFalse(deviceVersion.isOlderThan(deviceVersion));
+
+ DistroRulesVersion sameVersion = new DistroRulesVersion("2016b", 2);
+ assertFalse(deviceVersion.isOlderThan(sameVersion));
+
+ DistroRulesVersion sameRulesNewerRevision = new DistroRulesVersion("2016b", 3);
+ assertTrue(deviceVersion.isOlderThan(sameRulesNewerRevision));
+
+ DistroRulesVersion sameRulesOlderRevision = new DistroRulesVersion("2016b", 1);
+ assertFalse(deviceVersion.isOlderThan(sameRulesOlderRevision));
+
+ DistroRulesVersion newerRules = new DistroRulesVersion("2016c", 2);
+ assertTrue(deviceVersion.isOlderThan(newerRules));
+
+ DistroRulesVersion olderRules = new DistroRulesVersion("2016a", 2);
+ assertFalse(deviceVersion.isOlderThan(olderRules));
+ }
+
+ private static void assertEqualsContract(DistroRulesVersion one, DistroRulesVersion two) {
+ assertEquals(one, two);
+ assertEquals(one.hashCode(), two.hashCode());
+ }
+}
diff --git a/core/tests/coretests/src/android/app/timezone/RulesStateTest.java b/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
new file mode 100644
index 0000000..a9357c9
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link RulesState}.
+ */
+// TODO(nfuller) Move to CTS once this class is part of the SystemApi. http://b/31008728
+public class RulesStateTest {
+
+ @Test
+ public void equalsAndHashCode() {
+ RulesState one = new RulesState(
+ "2016a", formatVersion(1, 2), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016a", 3),
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 2));
+ assertEqualsContract(one, one);
+
+ RulesState two = new RulesState(
+ "2016a", formatVersion(1, 2), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016a", 3),
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 2));
+ assertEqualsContract(one, two);
+
+ RulesState differentSystemRules = new RulesState(
+ "2016b", formatVersion(1, 2), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016a", 3),
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 2));
+ assertFalse(one.equals(differentSystemRules));
+
+ RulesState differentFormatVersion = new RulesState(
+ "2016a", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016a", 3),
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 2));
+ assertFalse(one.equals(differentFormatVersion));
+
+ RulesState differentOperationInProgress = new RulesState(
+ "2016a", formatVersion(1, 1), true /* operationInProgress */,
+ RulesState.STAGED_OPERATION_UNKNOWN, null /* stagedDistroRulesVersion */,
+ RulesState.DISTRO_STATUS_UNKNOWN, null /* installedDistroRulesVersion */);
+ assertFalse(one.equals(differentOperationInProgress));
+
+ RulesState differentStagedOperation = new RulesState(
+ "2016a", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_UNINSTALL, null /* stagedDistroRulesVersion */,
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 2));
+ assertFalse(one.equals(differentStagedOperation));
+
+ RulesState differentStagedInstallVersion = new RulesState(
+ "2016a", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016a", 4),
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 2));
+ assertFalse(one.equals(differentStagedInstallVersion));
+
+ RulesState differentInstalled = new RulesState(
+ "2016a", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016a", 3),
+ RulesState.DISTRO_STATUS_NONE, null /* installedDistroRulesVersion */);
+ assertFalse(one.equals(differentInstalled));
+
+ RulesState differentInstalledVersion = new RulesState(
+ "2016a", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016a", 3),
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 3));
+ assertFalse(one.equals(differentInstalledVersion));
+ }
+
+ @Test
+ public void parcelable() {
+ RulesState rulesState1 = new RulesState(
+ "2016a", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016b", 2),
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 3));
+ checkParcelableRoundTrip(rulesState1);
+
+ RulesState rulesStateWithNulls = new RulesState(
+ "2016a", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_NONE, null /* stagedDistroRulesVersion */,
+ RulesState.DISTRO_STATUS_NONE, null /* installedDistroRulesVersion */);
+ checkParcelableRoundTrip(rulesStateWithNulls);
+
+ RulesState rulesStateWithUnknowns = new RulesState(
+ "2016a", formatVersion(1, 1), true /* operationInProgress */,
+ RulesState.STAGED_OPERATION_UNKNOWN, null /* stagedDistroRulesVersion */,
+ RulesState.DISTRO_STATUS_UNKNOWN, null /* installedDistroRulesVersion */);
+ checkParcelableRoundTrip(rulesStateWithNulls);
+ }
+
+ private static void checkParcelableRoundTrip(RulesState rulesState) {
+ Parcel parcel = Parcel.obtain();
+ rulesState.writeToParcel(parcel, 0 /* flags */);
+ parcel.setDataPosition(0);
+
+ RulesState newVersion = RulesState.CREATOR.createFromParcel(parcel);
+
+ assertEquals(rulesState, newVersion);
+ }
+
+ @Test
+ public void isSystemVersionOlderThan() {
+ RulesState rulesState = new RulesState(
+ "2016b", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_NONE, null /* stagedDistroRulesVersion */,
+ RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 3));
+ assertFalse(rulesState.isSystemVersionOlderThan(rulesVersion("2016a", 1)));
+ assertFalse(rulesState.isSystemVersionOlderThan(rulesVersion("2016b", 1)));
+ assertTrue(rulesState.isSystemVersionOlderThan(rulesVersion("2016c", 1)));
+ }
+
+ @Test
+ public void isInstalledDistroOlderThan() {
+ RulesState operationInProgress = new RulesState(
+ "2016b", formatVersion(1, 1), true /* operationInProgress */,
+ RulesState.STAGED_OPERATION_UNKNOWN, null /* stagedDistroRulesVersion */,
+ RulesState.STAGED_OPERATION_UNKNOWN, null /* installedDistroRulesVersion */);
+ try {
+ operationInProgress.isInstalledDistroOlderThan(rulesVersion("2016b", 1));
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+
+ RulesState nothingInstalled = new RulesState(
+ "2016b", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_NONE, null /* stagedDistroRulesVersion */,
+ RulesState.DISTRO_STATUS_NONE, null /* installedDistroRulesVersion */);
+ try {
+ nothingInstalled.isInstalledDistroOlderThan(rulesVersion("2016b", 1));
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+
+ DistroRulesVersion installedVersion = rulesVersion("2016b", 3);
+ RulesState rulesStateWithInstalledVersion = new RulesState(
+ "2016b", formatVersion(1, 1), false /* operationInProgress */,
+ RulesState.STAGED_OPERATION_NONE, null /* stagedDistroRulesVersion */,
+ RulesState.DISTRO_STATUS_INSTALLED, installedVersion);
+
+ DistroRulesVersion olderRules = rulesVersion("2016a", 1);
+ assertEquals(installedVersion.isOlderThan(olderRules),
+ rulesStateWithInstalledVersion.isInstalledDistroOlderThan(olderRules));
+
+ DistroRulesVersion sameRules = rulesVersion("2016b", 1);
+ assertEquals(installedVersion.isOlderThan(sameRules),
+ rulesStateWithInstalledVersion.isInstalledDistroOlderThan(sameRules));
+
+ DistroRulesVersion newerRules = rulesVersion("2016c", 1);
+ assertEquals(installedVersion.isOlderThan(newerRules),
+ rulesStateWithInstalledVersion.isInstalledDistroOlderThan(newerRules));
+ }
+
+ private static void assertEqualsContract(RulesState one, RulesState two) {
+ assertEquals(one, two);
+ assertEquals(one.hashCode(), two.hashCode());
+ }
+
+ private static DistroRulesVersion rulesVersion(String rulesVersion, int revision) {
+ return new DistroRulesVersion(rulesVersion, revision);
+ }
+
+ private static DistroFormatVersion formatVersion(int majorVersion, int minorVersion) {
+ return new DistroFormatVersion(majorVersion, minorVersion);
+ }
+}
diff --git a/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java b/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java
new file mode 100644
index 0000000..e7a839c
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timezone;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.hamcrest.MockitoHamcrest.argThat;
+
+import android.content.Context;
+import android.content.Intent;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+/**
+ * Tests for {@link RulesUpdaterContract}.
+ */
+// TODO(nfuller) Move to CTS once this class is part of the SystemApi. http://b/31008728
+public class RulesUpdaterContractTest {
+
+ @Test
+ public void createUpdaterIntent() throws Exception {
+ String packageName = "foobar";
+ Intent intent = RulesUpdaterContract.createUpdaterIntent(packageName);
+
+ assertEquals(RulesUpdaterContract.ACTION_TRIGGER_RULES_UPDATE_CHECK, intent.getAction());
+ assertEquals(packageName, intent.getPackage());
+ assertEquals(Intent.FLAG_INCLUDE_STOPPED_PACKAGES, intent.getFlags());
+ }
+
+ @Test
+ public void sendBroadcast() throws Exception {
+ String packageName = "foobar";
+ byte[] tokenBytes = new byte[] { 1, 2, 3, 4, 5 };
+
+ Intent expectedIntent = RulesUpdaterContract.createUpdaterIntent(packageName);
+ expectedIntent.putExtra(RulesUpdaterContract.EXTRA_CHECK_TOKEN, tokenBytes);
+
+ Context mockContext = mock(Context.class);
+
+ RulesUpdaterContract.sendBroadcast(mockContext, packageName, tokenBytes);
+
+ verify(mockContext).sendBroadcast(
+ filterEquals(expectedIntent),
+ eq(RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION));
+ }
+
+ /**
+ * Registers a mockito parameter matcher that uses {@link Intent#filterEquals(Intent)}. to
+ * check the parameter against the intent supplied.
+ */
+ private static Intent filterEquals(final Intent expected) {
+ final Matcher<Intent> m = new BaseMatcher<Intent>() {
+ @Override
+ public boolean matches(Object actual) {
+ return actual != null && expected.filterEquals((Intent) actual);
+ }
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(expected.toString());
+ }
+ };
+ return argThat(m);
+ }
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 33a0493..698f2ec 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -36,6 +36,7 @@
import android.content.res.Resources.NotFoundException;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
@@ -64,9 +65,14 @@
import com.android.frameworks.coretests.R;
import com.android.internal.content.PackageHelper;
+import dalvik.system.VMRuntime;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -78,9 +84,9 @@
public static final String TAG = "PackageManagerTests";
- public final long MAX_WAIT_TIME = 25 * 1000;
+ public static final long MAX_WAIT_TIME = 25 * 1000;
- public final long WAIT_TIME_INCR = 5 * 1000;
+ public static final long WAIT_TIME_INCR = 5 * 1000;
private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec";
@@ -3861,6 +3867,117 @@
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
+ private static class TestDexModuleRegisterCallback
+ extends PackageManager.DexModuleRegisterCallback {
+ private String mDexModulePath = null;
+ private boolean mSuccess = false;
+ private String mMessage = null;
+ CountDownLatch doneSignal = new CountDownLatch(1);
+
+ @Override
+ public void onDexModuleRegistered(String dexModulePath, boolean success, String message) {
+ mDexModulePath = dexModulePath;
+ mSuccess = success;
+ mMessage = message;
+ doneSignal.countDown();
+ }
+
+ boolean waitTillDone() {
+ long startTime = System.currentTimeMillis();
+ while (System.currentTimeMillis() - startTime < MAX_WAIT_TIME) {
+ try {
+ return doneSignal.await(MAX_WAIT_TIME, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Interrupted during sleep", e);
+ }
+ }
+ return false;
+ }
+
+ }
+
+ // Verify that the base code path cannot be registered.
+ public void testRegisterDexModuleBaseCode() throws Exception {
+ PackageManager pm = getPm();
+ ApplicationInfo info = getContext().getApplicationInfo();
+ TestDexModuleRegisterCallback callback = new TestDexModuleRegisterCallback();
+ pm.registerDexModule(info.getBaseCodePath(), callback);
+ assertTrue(callback.waitTillDone());
+ assertEquals(info.getBaseCodePath(), callback.mDexModulePath);
+ assertFalse("BaseCodePath should not be registered", callback.mSuccess);
+ }
+
+ // Verify thatmodules which are not own by the calling package are not registered.
+ public void testRegisterDexModuleNotOwningModule() throws Exception {
+ TestDexModuleRegisterCallback callback = new TestDexModuleRegisterCallback();
+ String moduleBelongingToOtherPackage = "/data/user/0/com.google.android.gms/module.apk";
+ getPm().registerDexModule(moduleBelongingToOtherPackage, callback);
+ assertTrue(callback.waitTillDone());
+ assertEquals(moduleBelongingToOtherPackage, callback.mDexModulePath);
+ assertTrue(callback.waitTillDone());
+ assertFalse("Only modules belonging to the calling package can be registered",
+ callback.mSuccess);
+ }
+
+ // Verify that modules owned by the package are successfully registered.
+ public void testRegisterDexModuleSuccessfully() throws Exception {
+ ApplicationInfo info = getContext().getApplicationInfo();
+ // Copy the main apk into the data folder and use it as a "module".
+ File dexModuleDir = new File(info.dataDir, "module-dir");
+ File dexModule = new File(dexModuleDir, "module.apk");
+ try {
+ assertNotNull(FileUtils.createDir(
+ dexModuleDir.getParentFile(), dexModuleDir.getName()));
+ Files.copy(Paths.get(info.getBaseCodePath()), dexModule.toPath(),
+ StandardCopyOption.REPLACE_EXISTING);
+ TestDexModuleRegisterCallback callback = new TestDexModuleRegisterCallback();
+ getPm().registerDexModule(dexModule.toString(), callback);
+ assertTrue(callback.waitTillDone());
+ assertEquals(dexModule.toString(), callback.mDexModulePath);
+ assertTrue(callback.waitTillDone());
+ assertTrue(callback.mMessage, callback.mSuccess);
+
+ // NOTE:
+ // This actually verifies internal behaviour which might change. It's not
+ // ideal but it's the best we can do since there's no other place we can currently
+ // write a better test.
+ for(String isa : getAppDexInstructionSets(info)) {
+ Files.exists(Paths.get(dexModuleDir.toString(), "oat", isa, "module.odex"));
+ Files.exists(Paths.get(dexModuleDir.toString(), "oat", isa, "module.vdex"));
+ }
+ } finally {
+ FileUtils.deleteContentsAndDir(dexModuleDir);
+ }
+ }
+
+ // If the module does not exist on disk we should get a failure.
+ public void testRegisterDexModuleNotExists() throws Exception {
+ ApplicationInfo info = getContext().getApplicationInfo();
+ String nonExistentApk = Paths.get(info.dataDir, "non-existent.apk").toString();
+ TestDexModuleRegisterCallback callback = new TestDexModuleRegisterCallback();
+ getPm().registerDexModule(nonExistentApk, callback);
+ assertTrue(callback.waitTillDone());
+ assertEquals(nonExistentApk, callback.mDexModulePath);
+ assertTrue(callback.waitTillDone());
+ assertFalse("DexModule registration should fail", callback.mSuccess);
+ }
+
+ // Copied from com.android.server.pm.InstructionSets because we don't have access to it here.
+ private static String[] getAppDexInstructionSets(ApplicationInfo info) {
+ if (info.primaryCpuAbi != null) {
+ if (info.secondaryCpuAbi != null) {
+ return new String[] {
+ VMRuntime.getInstructionSet(info.primaryCpuAbi),
+ VMRuntime.getInstructionSet(info.secondaryCpuAbi) };
+ } else {
+ return new String[] {
+ VMRuntime.getInstructionSet(info.primaryCpuAbi) };
+ }
+ }
+
+ return new String[] { VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]) };
+ }
+
/*---------- Recommended install location tests ----*/
/*
* TODO's
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index ca4141a..b9bd193 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -220,41 +220,41 @@
* Unit test for PackageParser.getActivityConfigChanges().
* If the bit is 1 in the original configChanges, it is still 1 in the final configChanges.
* If the bit is 0 in the original configChanges and the bit is not set to 1 in
- * restartOnConfigChanges, the bit is changed to 1 in the final configChanges by default.
+ * recreateOnConfigChanges, the bit is changed to 1 in the final configChanges by default.
*/
@Test
public void testGetActivityConfigChanges() {
- // Not set in either configChanges or restartOnConfigChanges.
+ // Not set in either configChanges or recreateOnConfigChanges.
int configChanges = 0x0000; // 00000000.
- int restartOnConfigChanges = 0x0000; // 00000000.
+ int recreateOnConfigChanges = 0x0000; // 00000000.
int finalConfigChanges =
- PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+ PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
assertEquals(0x0003, finalConfigChanges); // Should be 00000011.
- // Not set in configChanges, but set in restartOnConfigChanges.
+ // Not set in configChanges, but set in recreateOnConfigChanges.
configChanges = 0x0000; // 00000000.
- restartOnConfigChanges = 0x0003; // 00000011.
+ recreateOnConfigChanges = 0x0003; // 00000011.
finalConfigChanges =
- PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+ PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
assertEquals(0x0000, finalConfigChanges); // Should be 00000000.
// Set in configChanges.
configChanges = 0x0003; // 00000011.
- restartOnConfigChanges = 0X0000; // 00000000.
+ recreateOnConfigChanges = 0X0000; // 00000000.
finalConfigChanges =
- PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+ PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
assertEquals(0x0003, finalConfigChanges); // Should be 00000011.
- restartOnConfigChanges = 0x0003; // 00000011.
+ recreateOnConfigChanges = 0x0003; // 00000011.
finalConfigChanges =
- PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+ PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
assertEquals(0x0003, finalConfigChanges); // Should still be 00000011.
// Other bit set in configChanges.
configChanges = 0x0080; // 10000000, orientation.
- restartOnConfigChanges = 0x0000; // 00000000.
+ recreateOnConfigChanges = 0x0000; // 00000000.
finalConfigChanges =
- PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+ PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
assertEquals(0x0083, finalConfigChanges); // Should be 10000011.
}
}
diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java
index aaaf55c..821ee80 100644
--- a/core/tests/coretests/src/android/os/VintfObjectTest.java
+++ b/core/tests/coretests/src/android/os/VintfObjectTest.java
@@ -26,5 +26,8 @@
// From /system/manifest.xml
assertTrue(String.join("", xmls).contains(
"<manifest version=\"1.0\" type=\"framework\">"));
+ // From /system/compatibility-matrix.xml
+ assertTrue(String.join("", xmls).contains(
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">"));
}
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 8d64aed..9289b6e 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -110,6 +110,8 @@
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE,
Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
+ Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX,
+ Settings.Global.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX,
Settings.Global.BLUETOOTH_DISABLED_PROFILES,
Settings.Global.BLUETOOTH_HEADSET_PRIORITY_PREFIX,
Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX,
@@ -394,6 +396,8 @@
Settings.Secure.ANR_SHOW_BACKGROUND,
Settings.Secure.ASSISTANT,
Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
+ Settings.Secure.ASSIST_GESTURE_ENABLED_KEYGUARD,
+ Settings.Secure.ASSIST_GESTURE_ENABLED_SLEEP,
Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
Settings.Secure.ASSIST_STRUCTURE_ENABLED,
Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
@@ -403,7 +407,6 @@
Settings.Secure.BACKUP_ENABLED,
Settings.Secure.BACKUP_PROVISIONED,
Settings.Secure.BACKUP_TRANSPORT,
- Settings.Secure.BLUETOOTH_HCI_LOG,
Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED, // Candidate for backup?
Settings.Secure.CARRIER_APPS_HANDLED,
Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG,
diff --git a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java
index 5ed6ce5..bc9f44d 100644
--- a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java
+++ b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java
@@ -16,17 +16,26 @@
package android.text;
-import junit.framework.TestCase;
-
import static android.text.Layout.Alignment.ALIGN_NORMAL;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
- * Tests DynamciLayout updateBlocks method.
+ * Tests DynamicLayout updateBlocks method.
*
* Requires disabling access checks in the vm since this calls package-private APIs.
*
*/
-public class DynamicLayoutBlocksTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DynamicLayoutBlocksTest {
private DynamicLayout dl = new DynamicLayout("", new TextPaint(), 0, ALIGN_NORMAL, 0, 0, false);
private static final int ___ = DynamicLayout.INVALID_BLOCK_INDEX;
@@ -88,6 +97,7 @@
assertState(sizes, ids);
}
+ @Test
public void testFrom0() {
defineInitialState( new int[] { 0 }, new int[] { 123 });
@@ -101,6 +111,7 @@
assertState( new int[] { 10 } );
}
+ @Test
public void testFrom1ReplaceByEmpty() {
defineInitialState( new int[] { 100 }, new int[] { 123 });
@@ -126,6 +137,7 @@
assertState( new int[] { 100 } );
}
+ @Test
public void testFrom1ReplaceFromFirstLine() {
defineInitialState( new int[] { 100 }, new int[] { 123 });
@@ -142,6 +154,7 @@
assertState( new int[] { 20 } );
}
+ @Test
public void testFrom1ReplaceFromCenter() {
defineInitialState( new int[] { 100 }, new int[] { 123 });
@@ -158,6 +171,7 @@
assertState( new int[] { 20, 50 } );
}
+ @Test
public void testFrom1ReplaceFromEnd() {
defineInitialState( new int[] { 100 }, new int[] { 123 });
@@ -171,6 +185,7 @@
assertState( new int[] { 100, 10 } );
}
+ @Test
public void testFrom2ReplaceFromFirstLine() {
defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
@@ -187,6 +202,7 @@
assertState( new int[] { 50 }, new int[] { ___ } );
}
+ @Test
public void testFrom2ReplaceFromFirstBlock() {
defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
@@ -203,6 +219,7 @@
assertState( new int[] { 3, 50 }, new int[] { ___, ___ } );
}
+ @Test
public void testFrom2ReplaceFromBottomBoundary() {
defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
@@ -216,6 +233,7 @@
assertState( new int[] { 10, 50 }, new int[] { ___, ___ } );
}
+ @Test
public void testFrom2ReplaceFromTopBoundary() {
defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
@@ -229,6 +247,7 @@
assertState( new int[] { 11, 50 }, new int[] { 123, ___ } );
}
+ @Test
public void testFrom2ReplaceFromSecondBlock() {
defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
@@ -242,6 +261,7 @@
assertState( new int[] { 11, 14-11, 50 }, new int[] { 123, ___, ___ } );
}
+ @Test
public void testFrom2RemoveFromFirst() {
defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
@@ -258,6 +278,7 @@
assertState( new int[] { 0 }, new int[] { ___ } );
}
+ @Test
public void testFrom2RemoveFromFirstBlock() {
defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
@@ -274,6 +295,7 @@
assertState( new int[] { 4 }, new int[] { ___ } );
}
+ @Test
public void testFrom2RemoveFromSecondBlock() {
defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
@@ -284,6 +306,7 @@
assertState( new int[] { 11, 14-11 }, new int[] { 123, ___ } );
}
+ @Test
public void testFrom3ReplaceFromFirstBlock() {
defineInitialState( new int[] { 10, 30, 60 }, new int[] { 123, 456, 789 });
@@ -306,6 +329,7 @@
assertState( new int[] { 3, 50 }, new int[] { ___, ___ } );
}
+ @Test
public void testFrom3ReplaceFromSecondBlock() {
defineInitialState( new int[] { 10, 30, 60 }, new int[] { 123, 456, 789 });
diff --git a/core/tests/coretests/src/android/text/DynamicLayoutTest.java b/core/tests/coretests/src/android/text/DynamicLayoutTest.java
index 9362ed9..da6dc7e 100644
--- a/core/tests/coretests/src/android/text/DynamicLayoutTest.java
+++ b/core/tests/coretests/src/android/text/DynamicLayoutTest.java
@@ -17,16 +17,28 @@
package android.text;
import static android.text.Layout.Alignment.ALIGN_NORMAL;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.FontMetricsInt;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.text.style.ReplacementSpan;
-import junit.framework.TestCase;
-public class DynamicLayoutTest extends TestCase {
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DynamicLayoutTest {
private static final int WIDTH = 10000;
+ @Test
public void testGetBlocksAlwaysNeedToBeRedrawn_en() {
final SpannableStringBuilder builder = new SpannableStringBuilder();
final DynamicLayout layout = new DynamicLayout(builder, new TextPaint(), WIDTH,
@@ -42,19 +54,7 @@
assertNull(layout.getBlocksAlwaysNeedToBeRedrawn());
}
-
- private static class MockReplacementSpan extends ReplacementSpan {
- @Override
- public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) {
- return 10;
- }
-
- @Override
- public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top,
- int y, int bottom, Paint paint) {
- }
- }
-
+ @Test
public void testGetBlocksAlwaysNeedToBeRedrawn_replacementSpan() {
final SpannableStringBuilder builder = new SpannableStringBuilder();
final DynamicLayout layout = new DynamicLayout(builder, new TextPaint(), WIDTH,
@@ -66,11 +66,17 @@
builder.append("hijk lmn\n");
assertNull(layout.getBlocksAlwaysNeedToBeRedrawn());
- builder.setSpan(new MockReplacementSpan(), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ReplacementSpan mockReplacementSpan = mock(ReplacementSpan.class);
+ when(mockReplacementSpan.getSize(any(), any(), any(), any(), any()))
+ .thenReturn(10);
+ doNothing().when(mockReplacementSpan)
+ .draw(any(), any(), any(), any(), any(), any(), any(), any(), any());
+
+ builder.setSpan(mockReplacementSpan, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
assertNotNull(layout.getBlocksAlwaysNeedToBeRedrawn());
assertTrue(layout.getBlocksAlwaysNeedToBeRedrawn().contains(0));
- builder.setSpan(new MockReplacementSpan(), 9, 13, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ builder.setSpan(mockReplacementSpan, 9, 13, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
assertTrue(layout.getBlocksAlwaysNeedToBeRedrawn().contains(0));
assertTrue(layout.getBlocksAlwaysNeedToBeRedrawn().contains(1));
@@ -83,6 +89,7 @@
assertTrue(layout.getBlocksAlwaysNeedToBeRedrawn().isEmpty());
}
+ @Test
public void testGetBlocksAlwaysNeedToBeRedrawn_thai() {
final SpannableStringBuilder builder = new SpannableStringBuilder();
final DynamicLayout layout = new DynamicLayout(builder, new TextPaint(), WIDTH,
diff --git a/core/tests/coretests/src/android/text/PackedIntVectorTest.java b/core/tests/coretests/src/android/text/PackedIntVectorTest.java
index 1aab8af..9df0f89 100644
--- a/core/tests/coretests/src/android/text/PackedIntVectorTest.java
+++ b/core/tests/coretests/src/android/text/PackedIntVectorTest.java
@@ -16,17 +16,23 @@
package android.text;
-import android.support.test.filters.SmallTest;
+import static org.junit.Assert.assertEquals;
-import junit.framework.TestCase;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* PackedIntVectorTest tests the features of android.util.PackedIntVector.
*/
-public class PackedIntVectorTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PackedIntVectorTest {
- @SmallTest
- public void testBasic() throws Exception {
+ @Test
+ public void testBasic() {
for (int width = 0; width < 10; width++) {
PackedIntVector p = new PackedIntVector(width);
int[] ins = new int[width];
diff --git a/core/tests/coretests/src/android/text/SpannableTest.java b/core/tests/coretests/src/android/text/SpannableTest.java
index d6f0244..5ed6250 100644
--- a/core/tests/coretests/src/android/text/SpannableTest.java
+++ b/core/tests/coretests/src/android/text/SpannableTest.java
@@ -16,15 +16,20 @@
package android.text;
-import android.test.InstrumentationTestCase;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.MediumTest;
-public abstract class SpannableTest extends InstrumentationTestCase {
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public abstract class SpannableTest {
protected abstract Spannable newSpannableWithText(String text);
- @MediumTest
+ @Test
public void testGetSpans() {
Spannable spannable = newSpannableWithText("abcdef");
Object emptySpan = new Object();
diff --git a/core/tests/coretests/src/android/text/SpannedTest.java b/core/tests/coretests/src/android/text/SpannedTest.java
index 911da4b..60cddb08 100644
--- a/core/tests/coretests/src/android/text/SpannedTest.java
+++ b/core/tests/coretests/src/android/text/SpannedTest.java
@@ -16,34 +16,40 @@
package android.text;
+import static org.junit.Assert.assertEquals;
+
import android.graphics.Typeface;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.text.style.CharacterStyle;
import android.text.style.StyleSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.TypefaceSpan;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* SpannedTest tests some features of Spanned
*/
-public class SpannedTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SpannedTest {
private int mExpect;
- @SmallTest
- public void testSpannableString() throws Exception {
+ @Test
+ public void testSpannableString() {
checkPriority(new SpannableString("the quick brown fox"));
}
- @SmallTest
- public void testSpannableStringBuilder() throws Exception {
+ @Test
+ public void testSpannableStringBuilder() {
checkPriority2(new SpannableStringBuilder("the quick brown fox"));
}
- @SmallTest
- public void testAppend() throws Exception {
+ @Test
+ public void testAppend() {
Object o = new Object();
SpannableString ss = new SpannableString("Test");
ss.setSpan(o, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -61,7 +67,7 @@
assertEquals(1, ssb.getSpans(4, 8, Object.class).length);
}
- @SmallTest
+ @Test
public void testWrapParcel() {
SpannableString s = new SpannableString("Hello there world");
CharacterStyle mark = new StyleSpan(Typeface.BOLD);
@@ -129,16 +135,16 @@
mExpect = 0;
- s.setSpan(new Watcher(2), 0, s.length(),
+ s.setSpan(new Watcher(2), 0, s.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE |
(2 << Spannable.SPAN_PRIORITY_SHIFT));
- s.setSpan(new Watcher(4), 0, s.length(),
+ s.setSpan(new Watcher(4), 0, s.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE |
(4 << Spannable.SPAN_PRIORITY_SHIFT));
- s.setSpan(new Watcher(1), 0, s.length(),
+ s.setSpan(new Watcher(1), 0, s.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE |
(1 << Spannable.SPAN_PRIORITY_SHIFT));
- s.setSpan(new Watcher(3), 0, s.length(),
+ s.setSpan(new Watcher(3), 0, s.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE |
(3 << Spannable.SPAN_PRIORITY_SHIFT));
@@ -162,10 +168,13 @@
mSequence = sequence;
}
- public void onSpanChanged(Spannable b, Object o, int s, int e,
- int st, int en) { }
+ @Override
+ public void onSpanChanged(Spannable b, Object o, int s, int e, int st, int en) { }
+
+ @Override
public void onSpanRemoved(Spannable b, Object o, int s, int e) { }
+ @Override
public void onSpanAdded(Spannable b, Object o, int s, int e) {
if (mExpect != 0) {
assertEquals(mSequence, mExpect);
@@ -173,16 +182,18 @@
}
}
- public void beforeTextChanged(CharSequence s, int start, int count,
- int after) { }
- public void onTextChanged(CharSequence s, int start, int before,
- int count) {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
if (mExpect != 0) {
assertEquals(mSequence, mExpect);
mExpect = mSequence - 1;
}
}
+ @Override
public void afterTextChanged(Editable s) { }
}
}
diff --git a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
index a9865f8..d16cce8 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
@@ -16,15 +16,21 @@
package android.text;
+import static org.junit.Assert.assertEquals;
+
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Quick check of native bidi implementation.
*/
-public class StaticLayoutBidiTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StaticLayoutBidiTest {
public static final int REQ_DL = 2; // Layout.DIR_REQUEST_DEFAULT_LTR;
public static final int REQ_DR = -2; // Layout.DIR_REQUEST_DEFAULT_RTL;
@@ -39,47 +45,47 @@
public static final String GIMEL = "\u05d2";
public static final String DALET = "\u05d3";
- @SmallTest
+ @Test
public void testAllLtr() {
expectNativeBidi(REQ_DL, "a test", "000000", L);
}
- @SmallTest
+ @Test
public void testLtrRtl() {
expectNativeBidi(REQ_DL, "abc " + ALEF + BET + GIMEL, "0000111", L);
}
- @SmallTest
+ @Test
public void testAllRtl() {
expectNativeBidi(REQ_DL, ALEF + SP + ALEF + BET + GIMEL + DALET, "111111", R);
}
- @SmallTest
+ @Test
public void testRtlLtr() {
expectNativeBidi(REQ_DL, ALEF + BET + GIMEL + " abc", "1111222", R);
}
- @SmallTest
+ @Test
public void testRAllLtr() {
expectNativeBidi(REQ_R, "a test", "222222", R);
}
- @SmallTest
+ @Test
public void testRLtrRtl() {
expectNativeBidi(REQ_R, "abc " + ALEF + BET + GIMEL, "2221111", R);
}
- @SmallTest
+ @Test
public void testLAllRtl() {
expectNativeBidi(REQ_L, ALEF + SP + ALEF + BET + GIMEL + DALET, "111111", L);
}
- @SmallTest
+ @Test
public void testLRtlLtr() {
expectNativeBidi(REQ_DL, ALEF + BET + GIMEL + " abc", "1111222", R);
}
- @SmallTest
+ @Test
public void testNativeBidi() {
expectNativeBidi(REQ_L, ALEF + BET + GIMEL + " abc", "1110000", L);
}
diff --git a/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java b/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java
index 2300c63..e0b4776 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java
@@ -16,16 +16,21 @@
package android.text;
+import static org.junit.Assert.fail;
+
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.text.Layout.Directions;
import android.text.StaticLayoutTest.LayoutBuilder;
-import junit.framework.TestCase;
-
import java.util.Arrays;
import java.util.Formatter;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class StaticLayoutDirectionsTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StaticLayoutDirectionsTest {
private static final char ALEF = '\u05d0';
private static Directions dirs(int ... dirs) {
@@ -107,7 +112,7 @@
return new String(chars, 0, chars.length);
}
- @SmallTest
+ @Test
public void testDirections() {
StringBuilder buf = new StringBuilder("\n");
Formatter f = new Formatter(buf);
@@ -122,7 +127,7 @@
}
}
- @SmallTest
+ @Test
public void testTrailingWhitespace() {
LayoutBuilder b = StaticLayoutTest.builder();
b.setText(pseudoBidiToReal("Ab c"));
@@ -137,7 +142,7 @@
expectDirections("split line", expected, result);
}
- @SmallTest
+ @Test
public void testNextToRightOf() {
LayoutBuilder b = StaticLayoutTest.builder();
b.setText(pseudoBidiToReal("aA1B2"));
@@ -161,7 +166,7 @@
}
}
- @SmallTest
+ @Test
public void testNextToLeftOf() {
LayoutBuilder b = StaticLayoutTest.builder();
b.setText(pseudoBidiToReal("aA1B2"));
@@ -178,40 +183,6 @@
}
}
- // utility, not really a test
- /*
- public void testMeasureText1() {
- LayoutBuilder b = StaticLayoutTest.builder();
- String text = "ABC"; // "abAB"
- b.setText(pseudoBidiToReal(text));
- Layout l = b.build();
- Directions directions = l.getLineDirections(0);
-
- TextPaint workPaint = new TextPaint();
-
- int dir = -1; // LEFT_TO_RIGHT
- boolean trailing = true;
- boolean alt = true;
- do {
- dir = -dir;
- do {
- trailing = !trailing;
- for (int offset = 0, end = b.text.length(); offset <= end; ++offset) {
- float width = Layout.measureText(b.paint,
- workPaint,
- b.text,
- 0, offset, end,
- dir, directions,
- trailing, false,
- null);
- Log.i("BIDI", "dir: " + dir + " trail: " + trailing +
- " offset: " + offset + " width: " + width);
- }
- } while (!trailing);
- } while (dir > 0);
- }
- */
-
// utility for displaying arrays in hex
private static String hexArray(int[] array) {
StringBuilder sb = new StringBuilder();
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index 436840c..b7ca219 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -16,25 +16,30 @@
package android.text;
+import static android.text.Layout.Alignment.ALIGN_NORMAL;
+import static org.junit.Assert.assertEquals;
+
import android.graphics.Paint.FontMetricsInt;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.text.Layout.Alignment;
import android.text.method.EditorState;
import android.util.Log;
-import junit.framework.TestCase;
-
-import static android.text.Layout.Alignment.ALIGN_NORMAL;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests StaticLayout vertical metrics behavior.
*/
-public class StaticLayoutTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StaticLayoutTest {
/**
* Basic test showing expected behavior and relationship between font
* metrics and line metrics.
*/
- @SmallTest
+ @Test
public void testGetters1() {
LayoutBuilder b = builder();
FontMetricsInt fmi = b.paint.getFontMetricsInt();
@@ -60,7 +65,7 @@
* Basic test showing effect of includePad = true with 1 line.
* Top and bottom padding are affected, as is the line descent and height.
*/
- @SmallTest
+ @Test
public void testGetters2() {
LayoutBuilder b = builder()
.setIncludePad(true);
@@ -75,7 +80,7 @@
* Basic test showing effect of includePad = true wrapping to 2 lines.
* Ascent of top line and descent of bottom line are affected.
*/
- @SmallTest
+ @Test
public void testGetters3() {
LayoutBuilder b = builder()
.setIncludePad(true)
@@ -92,7 +97,7 @@
* Basic test showing effect of includePad = true wrapping to 3 lines.
* First line ascent is top, bottom line descent is bottom.
*/
- @SmallTest
+ @Test
public void testGetters4() {
LayoutBuilder b = builder()
.setText("This is a longer test")
@@ -112,7 +117,7 @@
* large text. See effect of leading. Currently, we don't expect there to
* even be non-zero leading.
*/
- @SmallTest
+ @Test
public void testGetters5() {
LayoutBuilder b = builder()
.setText("This is a longer test")
@@ -139,7 +144,7 @@
* Basic test showing effect of includePad = true, spacingAdd = 2, wrapping
* to 3 lines.
*/
- @SmallTest
+ @Test
public void testGetters6() {
int spacingAdd = 2; // int so expressions return int
LayoutBuilder b = builder()
@@ -160,7 +165,7 @@
* Basic test showing effect of includePad = true, spacingAdd = 2,
* spacingMult = 1.5, wrapping to 3 lines.
*/
- @SmallTest
+ @Test
public void testGetters7() {
LayoutBuilder b = builder()
.setText("This is a longer test")
@@ -182,7 +187,7 @@
* Basic test showing effect of includePad = true, spacingAdd = 0,
* spacingMult = 0.8 when wrapping to 3 lines.
*/
- @SmallTest
+ @Test
public void testGetters8() {
LayoutBuilder b = builder()
.setText("This is a longer test")
@@ -336,6 +341,7 @@
* Tests for keycap, variation selectors, flags are in CTS.
* See {@link android.text.cts.StaticLayoutTest}.
*/
+ @Test
public void testEmojiOffset() {
EditorState state = new EditorState();
TextPaint paint = new TextPaint();
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java b/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java
index 7e07acb..f6888e3 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java
@@ -16,15 +16,23 @@
package android.text;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.text.Layout.Alignment;
-import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for text measuring methods of StaticLayout.
*/
-public class StaticLayoutTextMeasuringTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StaticLayoutTextMeasuringTest {
private static final float SPACE_MULTI = 1.0f;
private static final float SPACE_ADD = 0.0f;
private static final int DEFAULT_OUTER_WIDTH = 150;
@@ -32,37 +40,36 @@
private TextPaint mDefaultPaint;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setup() {
if (mDefaultPaint == null) {
mDefaultPaint = new TextPaint();
}
}
- @SmallTest
+ @Test
public void testGetPrimaryHorizontal_zwnbsp() {
// a, ZERO WIDTH NO-BREAK SPACE
String testString = "a\uFEFF";
StaticLayout layout = new StaticLayout(testString, mDefaultPaint,
DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
- assertEquals(0.0f, layout.getPrimaryHorizontal(0));
- assertEquals(layout.getPrimaryHorizontal(2), layout.getPrimaryHorizontal(1));
+ assertEquals(0.0f, layout.getPrimaryHorizontal(0), 0f);
+ assertEquals(layout.getPrimaryHorizontal(2), layout.getPrimaryHorizontal(1), 0f);
}
- @SmallTest
+ @Test
public void testGetPrimaryHorizontal_devanagari() {
// DEVANAGARI LETTER KA, DEVANAGARI VOWEL SIGN AA
String testString = "\u0915\u093E";
StaticLayout layout = new StaticLayout(testString, mDefaultPaint,
DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
- assertEquals(0.0f, layout.getPrimaryHorizontal(0));
- assertEquals(layout.getPrimaryHorizontal(2), layout.getPrimaryHorizontal(1));
+ assertEquals(0.0f, layout.getPrimaryHorizontal(0), 0f);
+ assertEquals(layout.getPrimaryHorizontal(2), layout.getPrimaryHorizontal(1), 0f);
}
- @SmallTest
+ @Test
public void testGetPrimaryHorizontal_flagEmoji() {
// REGIONAL INDICATOR SYMBOL LETTER U, REGIONAL INDICATOR SYMBOL LETTER S, REGIONAL
// INDICATOR SYMBOL LETTER Z
@@ -71,12 +78,12 @@
StaticLayout layout = new StaticLayout(testString, mDefaultPaint,
DEFAULT_OUTER_WIDTH, DEFAULT_ALIGN, SPACE_MULTI, SPACE_ADD, true);
- assertEquals(0.0f, layout.getPrimaryHorizontal(0));
- assertEquals(layout.getPrimaryHorizontal(4), layout.getPrimaryHorizontal(1));
- assertEquals(layout.getPrimaryHorizontal(4), layout.getPrimaryHorizontal(2));
- assertEquals(layout.getPrimaryHorizontal(4), layout.getPrimaryHorizontal(3));
+ assertEquals(0.0f, layout.getPrimaryHorizontal(0), 0f);
+ assertEquals(layout.getPrimaryHorizontal(4), layout.getPrimaryHorizontal(1), 0f);
+ assertEquals(layout.getPrimaryHorizontal(4), layout.getPrimaryHorizontal(2), 0f);
+ assertEquals(layout.getPrimaryHorizontal(4), layout.getPrimaryHorizontal(3), 0f);
assertTrue(layout.getPrimaryHorizontal(6) > layout.getPrimaryHorizontal(4));
- assertEquals(layout.getPrimaryHorizontal(6), layout.getPrimaryHorizontal(5));
+ assertEquals(layout.getPrimaryHorizontal(6), layout.getPrimaryHorizontal(5), 0f);
}
}
diff --git a/core/tests/coretests/src/android/text/TextLayoutTest.java b/core/tests/coretests/src/android/text/TextLayoutTest.java
index f3a28b4..8963189 100644
--- a/core/tests/coretests/src/android/text/TextLayoutTest.java
+++ b/core/tests/coretests/src/android/text/TextLayoutTest.java
@@ -17,31 +17,34 @@
package android.text;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
-import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TextLayoutTest {
+ private String mString;
+ private TextPaint mPaint;
-public class TextLayoutTest extends TestCase {
-
- protected String mString;
- protected TextPaint mPaint;
-
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setup() {
mString = "The quick brown fox";
mPaint = new TextPaint();
}
- @SmallTest
- public void testStaticLayout() throws Exception {
- Layout l = new StaticLayout(mString, mPaint, 200,
+ @Test
+ public void testStaticLayout() {
+ new StaticLayout(mString, mPaint, 200,
Layout.Alignment.ALIGN_NORMAL, 1, 0,
true);
}
- @SmallTest
- public void testDynamicLayoutTest() throws Exception {
- Layout l = new DynamicLayout(mString, mPaint, 200,
+ @Test
+ public void testDynamicLayoutTest() {
+ new DynamicLayout(mString, mPaint, 200,
Layout.Alignment.ALIGN_NORMAL, 1, 0,
true);
}
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index 26aabdb..312c4fb 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -16,6 +16,14 @@
package android.text;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.support.test.runner.AndroidJUnit4;
import com.google.android.collect.Lists;
import android.os.Parcel;
@@ -27,19 +35,21 @@
import android.text.util.Rfc822Tokenizer;
import android.view.View;
-import junit.framework.TestCase;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* TextUtilsTest tests {@link TextUtils}.
*/
-public class TextUtilsTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TextUtilsTest {
- @SmallTest
- public void testBasic() throws Exception {
+ @Test
+ public void testBasic() {
assertEquals("", TextUtils.concat());
assertEquals("foo", TextUtils.concat("foo"));
assertEquals("foobar", TextUtils.concat("foo", "bar"));
@@ -71,8 +81,8 @@
assertTrue(TextUtils.concat(foo, bar) instanceof SpannedString);
}
- @SmallTest
- public void testTemplateString() throws Exception {
+ @Test
+ public void testTemplateString() {
CharSequence result;
result = TextUtils.expandTemplate("This is a ^1 of the ^2 broadcast ^3.",
@@ -136,7 +146,7 @@
/** Fail unless text+spans contains a span 'spanName' with the given start and end. */
private void checkContains(Spanned text, String[] spans, String spanName,
- int start, int end) throws Exception {
+ int start, int end) {
for (String i: spans) {
if (i.equals(spanName)) {
assertEquals(start, text.getSpanStart(i));
@@ -147,8 +157,8 @@
fail();
}
- @SmallTest
- public void testTemplateSpan() throws Exception {
+ @Test
+ public void testTemplateSpan() {
SpannableString template;
Spanned result;
String[] spans;
@@ -186,27 +196,27 @@
checkContains(result, spans, "during+after", 1, 2);
}
- @SmallTest
+ @Test
public void testStringSplitterSimple() {
stringSplitterTestHelper("a,b,cde", new String[] {"a", "b", "cde"});
}
- @SmallTest
+ @Test
public void testStringSplitterEmpty() {
stringSplitterTestHelper("", new String[] {});
}
- @SmallTest
+ @Test
public void testStringSplitterWithLeadingEmptyString() {
stringSplitterTestHelper(",a,b,cde", new String[] {"", "a", "b", "cde"});
}
- @SmallTest
+ @Test
public void testStringSplitterWithInternalEmptyString() {
stringSplitterTestHelper("a,b,,cde", new String[] {"a", "b", "", "cde"});
}
- @SmallTest
+ @Test
public void testStringSplitterWithTrailingEmptyString() {
// A single trailing emtpy string should be ignored.
stringSplitterTestHelper("a,b,cde,", new String[] {"a", "b", "cde"});
@@ -222,7 +232,7 @@
MoreAsserts.assertEquals(expectedStrings, strings.toArray(new String[]{}));
}
- @SmallTest
+ @Test
public void testTrim() {
String[] strings = { "abc", " abc", " abc", "abc ", "abc ",
" abc ", " abc ", "\nabc\n", "\nabc", "abc\n" };
@@ -232,7 +242,7 @@
}
}
- @SmallTest
+ @Test
public void testRfc822TokenizerFullAddress() {
Rfc822Token[] tokens = Rfc822Tokenizer.tokenize("Foo Bar (something) <foo@google.com>");
assertNotNull(tokens);
@@ -242,7 +252,7 @@
assertEquals("something",tokens[0].getComment());
}
- @SmallTest
+ @Test
public void testRfc822TokenizeItemWithError() {
Rfc822Token[] tokens = Rfc822Tokenizer.tokenize("\"Foo Bar\\");
assertNotNull(tokens);
@@ -250,7 +260,7 @@
assertEquals("Foo Bar", tokens[0].getAddress());
}
- @SmallTest
+ @Test
public void testRfc822FindToken() {
Rfc822Tokenizer tokenizer = new Rfc822Tokenizer();
// 0 1 2 3 4
@@ -262,12 +272,13 @@
assertEquals(46, tokenizer.findTokenEnd(address, 25));
}
- @SmallTest
+ @Test
public void testRfc822FindTokenWithError() {
assertEquals(9, new Rfc822Tokenizer().findTokenEnd("\"Foo Bar\\", 0));
}
@LargeTest
+ @Test
public void testEllipsize() {
CharSequence s1 = "The quick brown fox jumps over \u00FEhe lazy dog.";
CharSequence s2 = new Wrapper(s1);
@@ -327,7 +338,7 @@
}
}
- @SmallTest
+ @Test
public void testDelimitedStringContains() {
assertFalse(TextUtils.delimitedStringContains("", ',', null));
assertFalse(TextUtils.delimitedStringContains(null, ',', ""));
@@ -347,7 +358,7 @@
assertFalse(TextUtils.delimitedStringContains("network,mock,gpsx", ',', "gps"));
}
- @SmallTest
+ @Test
public void testCharSequenceCreator() {
Parcel p = Parcel.obtain();
TextUtils.writeToParcel(null, p, 0);
@@ -360,7 +371,7 @@
assertEquals("conversion to/from parcel failed", "test", text);
}
- @SmallTest
+ @Test
public void testCharSequenceCreatorNull() {
Parcel p;
CharSequence text;
@@ -371,7 +382,7 @@
assertNull("null CharSequence should generate null from parcel", text);
}
- @SmallTest
+ @Test
public void testCharSequenceCreatorSpannable() {
Parcel p;
CharSequence text;
@@ -382,7 +393,7 @@
assertEquals("conversion to/from parcel failed", "test", text.toString());
}
- @SmallTest
+ @Test
public void testCharSequenceCreatorString() {
Parcel p;
CharSequence text;
@@ -404,10 +415,12 @@
mString = s;
}
+ @Override
public int length() {
return mString.length();
}
+ @Override
public char charAt(int off) {
return mString.charAt(off);
}
@@ -417,12 +430,13 @@
return mString.toString();
}
+ @Override
public CharSequence subSequence(int start, int end) {
return new Wrapper(mString.subSequence(start, end));
}
}
- @LargeTest
+ @Test
public void testRemoveEmptySpans() {
MockSpanned spanned = new MockSpanned();
@@ -484,14 +498,17 @@
}
}
+ @Override
public char charAt(int arg0) {
return 0;
}
+ @Override
public int length() {
return 0;
}
+ @Override
public CharSequence subSequence(int arg0, int arg1) {
return null;
}
@@ -522,7 +539,7 @@
}
}
- @SmallTest
+ @Test
public void testGetLayoutDirectionFromLocale() {
assertEquals(View.LAYOUT_DIRECTION_LTR, TextUtils.getLayoutDirectionFromLocale(null));
assertEquals(View.LAYOUT_DIRECTION_LTR,
diff --git a/core/tests/coretests/src/android/text/VariationParserTest.java b/core/tests/coretests/src/android/text/VariationParserTest.java
index b0f55d6..ec2c96c 100644
--- a/core/tests/coretests/src/android/text/VariationParserTest.java
+++ b/core/tests/coretests/src/android/text/VariationParserTest.java
@@ -16,17 +16,24 @@
package android.text;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
import android.graphics.fonts.FontVariationAxis;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class VariationParserTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class VariationParserTest {
private static final String[] INVALID_STYLE_VALUES = {
"", "x", "\t", "\n"
};
- @SmallTest
+ @Test
public void testFromFontVariationSetting_InvalidStyleValue() {
// Test with invalid styleValue
for (String invalidStyle : INVALID_STYLE_VALUES) {
@@ -39,7 +46,8 @@
}
for (String invalidStyle : INVALID_STYLE_VALUES) {
try {
- FontVariationAxis.fromFontVariationSettings("'wght' 1, 'wdth' " + invalidStyle);
+ FontVariationAxis.fromFontVariationSettings("'wght' 1, 'wdth' "
+ + invalidStyle);
fail();
} catch (IllegalArgumentException e) {
// pass
@@ -47,10 +55,13 @@
}
}
- @SmallTest
+ @Test
public void testOpenTypeTagValue() {
- assertEquals(0x77647468, (new FontVariationAxis("wdth", 0).getOpenTypeTagValue()));
- assertEquals(0x41582020, (new FontVariationAxis("AX ", 0).getOpenTypeTagValue()));
- assertEquals(0x20202020, (new FontVariationAxis(" ", 0).getOpenTypeTagValue()));
+ assertEquals(0x77647468,
+ new FontVariationAxis("wdth", 0).getOpenTypeTagValue());
+ assertEquals(0x41582020,
+ new FontVariationAxis("AX ", 0).getOpenTypeTagValue());
+ assertEquals(0x20202020,
+ new FontVariationAxis(" ", 0).getOpenTypeTagValue());
}
}
diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java
index 93bc911..15c86f0 100644
--- a/core/tests/coretests/src/android/text/format/DateFormatTest.java
+++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java
@@ -16,14 +16,21 @@
package android.text.format;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class DateFormatTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DateFormatTest {
- @SmallTest
- public void testHasDesignator() throws Exception {
+ @Test
+ public void testHasDesignator() {
assertTrue(DateFormat.hasDesignator("hh:mm:ss", DateFormat.MINUTE));
assertTrue(DateFormat.hasDesignator("myyyy", DateFormat.MINUTE));
assertTrue(DateFormat.hasDesignator("mmm", DateFormat.MINUTE));
@@ -31,8 +38,8 @@
assertFalse(DateFormat.hasDesignator("hh:MM:ss", DateFormat.MINUTE));
}
- @SmallTest
- public void testHasDesignatorEscaped() throws Exception {
+ @Test
+ public void testHasDesignatorEscaped() {
assertTrue(DateFormat.hasDesignator("hh:mm 'LOL'", DateFormat.MINUTE));
assertFalse(DateFormat.hasDesignator("hh:mm 'yyyy'", DateFormat.YEAR));
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
index de43fc6..9271cb4 100644
--- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -16,45 +16,40 @@
package android.text.format;
+import static org.junit.Assert.assertEquals;
+
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.LocaleList;
import android.support.test.filters.SmallTest;
-
-import junit.framework.TestCase;
+import android.support.test.runner.AndroidJUnit4;
import java.util.Locale;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class DateUtilsTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DateUtilsTest {
private static final LocaleList LOCALE_LIST_US = new LocaleList(Locale.US);
private LocaleList mOriginalLocales;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setup() {
mOriginalLocales = Resources.getSystem().getConfiguration().getLocales();
setLocales(LOCALE_LIST_US);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void teardown() {
setLocales(mOriginalLocales);
- super.tearDown();
}
- private void setLocales(LocaleList locales) {
- final Resources systemResources = Resources.getSystem();
- final Configuration config = new Configuration(systemResources.getConfiguration());
- config.setLocales(locales);
- // This is not very safe to call, but since DateUtils.formatDuration() is a static method
- // (it gets its format strings from the system resources), we can't pass a modified Context
- // to it.
- systemResources.updateConfiguration(config, null);
- }
-
- @SmallTest
- public void test_formatDuration_seconds() throws Exception {
+ @Test
+ public void test_formatDuration_seconds() {
assertEquals("0 seconds", DateUtils.formatDuration(0));
assertEquals("0 seconds", DateUtils.formatDuration(1));
assertEquals("0 seconds", DateUtils.formatDuration(499));
@@ -75,8 +70,8 @@
assertEquals("2s", DateUtils.formatDuration(1500, DateUtils.LENGTH_SHORTEST));
}
- @SmallTest
- public void test_formatDuration_Minutes() throws Exception {
+ @Test
+ public void test_formatDuration_Minutes() {
assertEquals("59 seconds", DateUtils.formatDuration(59000));
assertEquals("60 seconds", DateUtils.formatDuration(59500));
assertEquals("1 minute", DateUtils.formatDuration(60000));
@@ -92,8 +87,8 @@
assertEquals("2m", DateUtils.formatDuration(120000, DateUtils.LENGTH_SHORTEST));
}
- @SmallTest
- public void test_formatDuration_Hours() throws Exception {
+ @Test
+ public void test_formatDuration_Hours() {
assertEquals("59 minutes", DateUtils.formatDuration(3540000));
assertEquals("1 hour", DateUtils.formatDuration(3600000));
assertEquals("48 hours", DateUtils.formatDuration(172800000));
@@ -107,4 +102,15 @@
assertEquals("1h", DateUtils.formatDuration(3600000, DateUtils.LENGTH_SHORTEST));
assertEquals("48h", DateUtils.formatDuration(172800000, DateUtils.LENGTH_SHORTEST));
}
+
+ private void setLocales(LocaleList locales) {
+ final Resources systemResources = Resources.getSystem();
+ final Configuration config = new Configuration(systemResources.getConfiguration());
+ config.setLocales(locales);
+ // This is not very safe to call, but since DateUtils.formatDuration() is a static method
+ // (it gets its format strings from the system resources), we can't pass a modified Context
+ // to it.
+ systemResources.updateConfiguration(config, null);
+ }
+
}
diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java
index 2293094..a4ce911 100644
--- a/core/tests/coretests/src/android/text/format/FormatterTest.java
+++ b/core/tests/coretests/src/android/text/format/FormatterTest.java
@@ -16,43 +16,43 @@
package android.text.format;
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
+import android.support.test.runner.AndroidJUnit4;
import android.text.format.Formatter.BytesResult;
import java.util.Locale;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class FormatterTest extends AndroidTestCase {
-
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class FormatterTest {
private Locale mOriginalLocale;
+ private Context mContext;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mOriginalLocale = mContext.getResources().getConfiguration().locale;
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getContext();
+ mOriginalLocale = mContext.getResources()
+ .getConfiguration().locale;
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() {
if (mOriginalLocale != null) {
setLocale(mOriginalLocale);
}
- super.tearDown();
}
- private void setLocale(Locale locale) {
- Resources res = getContext().getResources();
- Configuration config = res.getConfiguration();
- config.locale = locale;
- res.updateConfiguration(config, res.getDisplayMetrics());
-
- Locale.setDefault(locale);
- }
-
- @SmallTest
+ @Test
public void testFormatBytes() {
setLocale(Locale.ENGLISH);
@@ -90,7 +90,7 @@
checkFormatBytes(-914, false, "-0.91", -910);
// Missing FLAG_CALCULATE_ROUNDED case.
- BytesResult r = Formatter.formatBytes(getContext().getResources(), 1, 0);
+ BytesResult r = Formatter.formatBytes(mContext.getResources(), 1, 0);
assertEquals("1", r.value);
assertEquals(0, r.roundedBytes); // Didn't pass FLAG_CALCULATE_ROUNDED
@@ -101,9 +101,18 @@
private void checkFormatBytes(long bytes, boolean useShort,
String expectedString, long expectedRounded) {
- BytesResult r = Formatter.formatBytes(getContext().getResources(), bytes,
+ BytesResult r = Formatter.formatBytes(mContext.getResources(), bytes,
Formatter.FLAG_CALCULATE_ROUNDED | (useShort ? Formatter.FLAG_SHORTER : 0));
assertEquals(expectedString, r.value);
assertEquals(expectedRounded, r.roundedBytes);
}
+
+ private void setLocale(Locale locale) {
+ Resources res = mContext.getResources();
+ Configuration config = res.getConfiguration();
+ config.locale = locale;
+ res.updateConfiguration(config, res.getDisplayMetrics());
+
+ Locale.setDefault(locale);
+ }
}
diff --git a/core/tests/coretests/src/android/text/format/TimeTest.java b/core/tests/coretests/src/android/text/format/TimeTest.java
index f6dd0d4..8983d15 100644
--- a/core/tests/coretests/src/android/text/format/TimeTest.java
+++ b/core/tests/coretests/src/android/text/format/TimeTest.java
@@ -16,17 +16,25 @@
package android.text.format;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import android.support.test.filters.SmallTest;
import android.support.test.filters.Suppress;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import android.util.TimeFormatException;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class TimeTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TimeTest {
- @SmallTest
- public void testNormalize0() throws Exception {
+ @Test
+ public void testNormalize0() {
Time t = new Time(Time.TIMEZONE_UTC);
t.parse("20060432T010203");
t.normalize(false /* use isDst */);
@@ -174,8 +182,8 @@
new DateTest(2007, 10, 5, 2, 0, 60, 2007, 10, 5, 3, 0),
};
- @SmallTest
- public void testNormalize1() throws Exception {
+ @Test
+ public void testNormalize1() {
Time local = new Time("America/Los_Angeles");
int len = dayTests.length;
@@ -265,70 +273,70 @@
}
}
- @SmallTest
- public void testSwitchTimezone0() throws Exception {
+ @Test
+ public void testSwitchTimezone0() {
Time t = new Time(Time.TIMEZONE_UTC);
t.parse("20061005T120000");
t.switchTimezone("America/Los_Angeles");
// System.out.println("got: " + t);
}
- @SmallTest
- public void testCtor0() throws Exception {
+ @Test
+ public void testCtor0() {
Time t = new Time(Time.TIMEZONE_UTC);
assertEquals(Time.TIMEZONE_UTC, t.timezone);
}
- @SmallTest
- public void testGetActualMaximum0() throws Exception {
+ @Test
+ public void testGetActualMaximum0() {
Time t = new Time(Time.TIMEZONE_UTC);
- int r = t.getActualMaximum(Time.SECOND);
+ t.getActualMaximum(Time.SECOND);
// System.out.println("r=" + r);
}
- @SmallTest
- public void testClear0() throws Exception {
+ @Test
+ public void testClear0() {
Time t = new Time(Time.TIMEZONE_UTC);
t.clear(Time.TIMEZONE_UTC);
}
- @SmallTest
- public void testCompare0() throws Exception {
+ @Test
+ public void testCompare0() {
Time a = new Time(Time.TIMEZONE_UTC);
Time b = new Time("America/Los_Angeles");
int r = Time.compare(a, b);
// System.out.println("r=" + r);
}
- @SmallTest
- public void testFormat0() throws Exception {
+ @Test
+ public void testFormat0() {
Time t = new Time(Time.TIMEZONE_UTC);
String r = t.format("%Y%m%dT%H%M%S");
// System.out.println("r='" + r + "'");
}
- @SmallTest
- public void testToString0() throws Exception {
+ @Test
+ public void testToString0() {
Time t = new Time(Time.TIMEZONE_UTC);
String r = t.toString();
// System.out.println("r='" + r + "'");
}
- @SmallTest
- public void testGetCurrentTimezone0() throws Exception {
+ @Test
+ public void testGetCurrentTimezone0() {
String r = Time.getCurrentTimezone();
// System.out.println("r='" + r + "'");
}
- @SmallTest
- public void testSetToNow0() throws Exception {
+ @Test
+ public void testSetToNow0() {
Time t = new Time(Time.TIMEZONE_UTC);
t.setToNow();
// System.out.println("t=" + t);
}
- @SmallTest
- public void testMillis0() throws Exception {
+ @Test
+ public void testMillis0() {
Time t = new Time(Time.TIMEZONE_UTC);
t.set(0, 0, 0, 1, 1, 2006);
long r = t.toMillis(true /* ignore isDst */);
@@ -338,23 +346,23 @@
// System.out.println("r=" + r);
}
- @SmallTest
- public void testMillis1() throws Exception {
+ @Test
+ public void testMillis1() {
Time t = new Time(Time.TIMEZONE_UTC);
t.set(1, 0, 0, 1, 0, 1970);
long r = t.toMillis(true /* ignore isDst */);
// System.out.println("r=" + r);
}
- @SmallTest
- public void testParse0() throws Exception {
+ @Test
+ public void testParse0() {
Time t = new Time(Time.TIMEZONE_UTC);
t.parse("12345678T901234");
// System.out.println("t=" + t);
}
- @SmallTest
- public void testParse33390() throws Exception {
+ @Test
+ public void testParse33390() {
Time t = new Time(Time.TIMEZONE_UTC);
t.parse3339("1980-05-23");
@@ -435,8 +443,8 @@
}
}
- @SmallTest
- public void testSet0() throws Exception {
+ @Test
+ public void testSet0() {
Time t = new Time(Time.TIMEZONE_UTC);
t.set(1000L);
// System.out.println("t.year=" + t.year);
@@ -449,13 +457,13 @@
// System.out.println("t=" + t);
}
- @SmallTest
- public void testSet1() throws Exception {
+ @Test
+ public void testSet1() {
Time t = new Time(Time.TIMEZONE_UTC);
t.set(1, 2, 3, 4, 5, 6);
// System.out.println("t=" + t);
}
-
+
// Timezones that cover the world. Some GMT offsets occur more than
// once in case some cities decide to change their GMT offset.
private static final String[] mTimeZones = {
@@ -518,9 +526,9 @@
"Pacific/Honolulu",
"Pacific/Midway",
};
-
+
@Suppress
- public void disableTestGetJulianDay() throws Exception {
+ public void disableTestGetJulianDay() {
Time time = new Time();
// For each day of the year, and for each timezone, get the Julian
@@ -560,11 +568,11 @@
}
}
}
-
+
@Suppress
- public void disableTestSetJulianDay() throws Exception {
+ public void disableTestSetJulianDay() {
Time time = new Time();
-
+
// For each day of the year in 2008, and for each timezone,
// test that we can set the Julian day correctly.
for (int monthDay = 1; monthDay <= 366; monthDay++) {
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index 864b48a..6e41831 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -17,9 +17,13 @@
package android.text.method;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.text.InputType;
import android.view.KeyEvent;
import android.widget.TextView.BufferType;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Test backspace key handling of {@link android.text.method.BaseKeyListener}.
@@ -27,6 +31,8 @@
* Only contains edge cases. For normal cases, see {@see android.text.method.cts.BackspaceTest}.
* TODO: introduce test cases for surrogate pairs and replacement span.
*/
+@SmallTest
+@RunWith(AndroidJUnit4.class)
public class BackspaceTest extends KeyListenerTestCase {
private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
public int getInputType() {
@@ -49,7 +55,7 @@
state.mSelectionEnd = mTextView.getSelectionEnd();
}
- @SmallTest
+ @Test
public void testCombiningEnclosingKeycaps() {
EditorState state = new EditorState();
@@ -77,7 +83,7 @@
state.assertEquals("|");
}
- @SmallTest
+ @Test
public void testVariationSelector() {
EditorState state = new EditorState();
@@ -141,7 +147,7 @@
state.assertEquals("|");
}
- @SmallTest
+ @Test
public void testEmojiZWJSequence() {
EditorState state = new EditorState();
@@ -221,7 +227,7 @@
state.assertEquals("|");
}
- @SmallTest
+ @Test
public void testFlags() {
EditorState state = new EditorState();
@@ -283,7 +289,7 @@
state.assertEquals("'a' |");
}
- @SmallTest
+ @Test
public void testEmojiModifier() {
EditorState state = new EditorState();
@@ -312,7 +318,7 @@
state.assertEquals("|");
}
- @SmallTest
+ @Test
public void testMixedEdgeCases() {
EditorState state = new EditorState();
diff --git a/core/tests/coretests/src/android/text/method/EditorState.java b/core/tests/coretests/src/android/text/method/EditorState.java
index bbbbd6d..12bb8c8 100644
--- a/core/tests/coretests/src/android/text/method/EditorState.java
+++ b/core/tests/coretests/src/android/text/method/EditorState.java
@@ -16,6 +16,11 @@
package android.text.method;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Editable;
@@ -59,19 +64,6 @@
public EditorState() {
}
- /**
- * A mocked {@link android.text.style.ReplacementSpan} for testing purpose.
- */
- private static class MockReplacementSpan extends ReplacementSpan {
- public int getSize(Paint paint, CharSequence text, int start, int end,
- Paint.FontMetricsInt fm) {
- return 0;
- }
- public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top,
- int y, int bottom, Paint paint) {
- }
- }
-
// Returns true if the code point is ASCII and graph.
private boolean isGraphicAscii(int codePoint) {
return 0x20 < codePoint && codePoint < 0x7F;
@@ -169,7 +161,14 @@
throw new IllegalArgumentException(
"ReplacementSpan start position appears after end position.");
}
- spannable.setSpan(new MockReplacementSpan(), replacementSpanStart, replacementSpanEnd,
+
+ ReplacementSpan mockReplacementSpan = mock(ReplacementSpan.class);
+ when(mockReplacementSpan.getSize(any(), any(), any(), any(), any()))
+ .thenReturn(0);
+ doNothing().when(mockReplacementSpan)
+ .draw(any(), any(), any(), any(), any(), any(), any(), any(), any());
+
+ spannable.setSpan(mockReplacementSpan, replacementSpanStart, replacementSpanEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mText = Editable.Factory.getInstance().newEditable(spannable);
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 839d380..6914e21 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -17,16 +17,23 @@
package android.text.method;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.text.InputType;
import android.view.KeyEvent;
import android.widget.TextView.BufferType;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* Test forward delete key handling of {@link android.text.method.BaseKeyListener}.
*
* Only contains edge cases. For normal cases, see {@see android.text.method.cts.ForwardDeleteTest}.
* TODO: introduce test cases for surrogate pairs and replacement span.
*/
+@SmallTest
+@RunWith(AndroidJUnit4.class)
public class ForwardDeleteTest extends KeyListenerTestCase {
private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
public int getInputType() {
@@ -49,7 +56,7 @@
state.mSelectionEnd = mTextView.getSelectionEnd();
}
- @SmallTest
+ @Test
public void testCombiningEnclosingKeycaps() {
EditorState state = new EditorState();
@@ -69,7 +76,7 @@
state.assertEquals("|");
}
- @SmallTest
+ @Test
public void testVariationSelector() {
EditorState state = new EditorState();
@@ -117,7 +124,7 @@
state.assertEquals("|");
}
- @SmallTest
+ @Test
public void testEmojiZeroWidthJoinerSequence() {
EditorState state = new EditorState();
@@ -160,7 +167,7 @@
state.assertEquals("|");
}
- @SmallTest
+ @Test
public void testFlags() {
EditorState state = new EditorState();
@@ -217,7 +224,7 @@
state.assertEquals("| 'b'");
}
- @SmallTest
+ @Test
public void testEmojiModifier() {
EditorState state = new EditorState();
@@ -246,7 +253,7 @@
state.assertEquals("|");
}
- @SmallTest
+ @Test
public void testMixedEdgeCases() {
EditorState state = new EditorState();
@@ -354,6 +361,8 @@
// ZERO WIDTH JOINER + regional indicator symbol
state.setByString("| U+1F469 U+200D U+1F1FA");
forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
state.assertEquals("|");
// Regional indicator symbol + end with ZERO WIDTH JOINER
@@ -364,6 +373,8 @@
// Regional indicator symbol + ZERO WIDTH JOINER
state.setByString("| U+1F1FA U+200D U+1F469");
forwardDelete(state, 0);
+ state.assertEquals("| U+1F469");
+ forwardDelete(state, 0);
state.assertEquals("|");
// Start with ZERO WIDTH JOINER + emoji modifier
@@ -384,6 +395,8 @@
// Emoji modifier + ZERO WIDTH JOINER
state.setByString("| U+1F466 U+1F3FB U+200D U+1F469");
forwardDelete(state, 0);
+ state.assertEquals("| U+1F469");
+ forwardDelete(state, 0);
state.assertEquals("|");
// Regional indicator symbol + emoji modifier
diff --git a/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java b/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
index f005d7b..99a0091 100644
--- a/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
+++ b/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
@@ -17,25 +17,19 @@
package android.text.method;
import android.app.Instrumentation;
-import android.test.InstrumentationTestCase;
+import android.support.test.InstrumentationRegistry;
import android.view.KeyEvent;
import android.widget.EditText;
-import com.android.frameworks.coretests.R;
-
-public abstract class KeyListenerTestCase extends InstrumentationTestCase {
-
+public abstract class KeyListenerTestCase {
protected Instrumentation mInstrumentation;
protected EditText mTextView;
public KeyListenerTestCase() {
}
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mInstrumentation = getInstrumentation();
+ protected void setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
mTextView = new EditText(mInstrumentation.getContext());
}
diff --git a/core/tests/coretests/src/android/text/method/WordIteratorTest.java b/core/tests/coretests/src/android/text/method/WordIteratorTest.java
index 66cf65f..3499a74 100644
--- a/core/tests/coretests/src/android/text/method/WordIteratorTest.java
+++ b/core/tests/coretests/src/android/text/method/WordIteratorTest.java
@@ -16,16 +16,25 @@
package android.text.method;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import java.text.BreakIterator;
import java.util.Locale;
+import org.junit.Test;
+import org.junit.runner.RunWith;
// TODO(Bug: 24062099): Add more tests for non-ascii text.
-public class WordIteratorTest extends AndroidTestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WordIteratorTest {
- @SmallTest
+ @Test
public void testSetCharSequence() {
final String text = "text";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -48,7 +57,7 @@
wordIterator.setCharSequence(text, text.length(), text.length());
}
- @SmallTest
+ @Test
public void testWindowWidth() {
final String text = "aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -65,7 +74,7 @@
assertEquals(BreakIterator.DONE, wordIterator.following(expectedWindowEnd));
}
- @SmallTest
+ @Test
public void testPreceding() {
final String text = "abc def-ghi. jkl";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -105,7 +114,7 @@
assertEquals(text.indexOf('j'), wordIterator.preceding(text.indexOf('l')));
}
- @SmallTest
+ @Test
public void testFollowing() {
final String text = "abc def-ghi. jkl";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -145,7 +154,7 @@
assertEquals(BreakIterator.DONE, wordIterator.following(text.length()));
}
- @SmallTest
+ @Test
public void testIsBoundary() {
final String text = "abc def-ghi. jkl";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -173,7 +182,7 @@
assertTrue(wordIterator.isBoundary(text.length()));
}
- @SmallTest
+ @Test
public void testNextBoundary() {
final String text = "abc def-ghi. jkl";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -220,7 +229,7 @@
assertEquals(BreakIterator.DONE, currentOffset);
}
- @SmallTest
+ @Test
public void testPrevBoundary() {
final String text = "abc def-ghi. jkl";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -266,7 +275,7 @@
assertEquals(BreakIterator.DONE, currentOffset);
}
- @SmallTest
+ @Test
public void testGetBeginning() {
{
final String text = "abc def-ghi. jkl";
@@ -340,7 +349,7 @@
}
}
- @SmallTest
+ @Test
public void testGetEnd() {
{
final String text = "abc def-ghi. jkl";
@@ -415,7 +424,7 @@
}
}
- @SmallTest
+ @Test
public void testGetPunctuationBeginning() {
final String text = "abc!? (^^;) def";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -450,7 +459,7 @@
assertEquals(text.indexOf(';'), wordIterator.getPunctuationBeginning(text.length()));
}
- @SmallTest
+ @Test
public void testGetPunctuationEnd() {
final String text = "abc!? (^^;) def";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -482,7 +491,7 @@
assertEquals(BreakIterator.DONE, wordIterator.getPunctuationEnd(text.length()));
}
- @SmallTest
+ @Test
public void testIsAfterPunctuation() {
final String text = "abc!? (^^;) def";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -498,7 +507,7 @@
assertFalse(wordIterator.isAfterPunctuation(text.length() + 1));
}
- @SmallTest
+ @Test
public void testIsOnPunctuation() {
final String text = "abc!? (^^;) def";
WordIterator wordIterator = new WordIterator(Locale.ENGLISH);
@@ -517,7 +526,7 @@
assertFalse(wordIterator.isOnPunctuation(text.length() + 1));
}
- @SmallTest
+ @Test
public void testApostropheMiddleOfWord() {
// These tests confirm that the word "isn't" is treated like one word.
final String text = "isn't he";
diff --git a/core/tests/coretests/src/android/text/util/LinkifyTest.java b/core/tests/coretests/src/android/text/util/LinkifyTest.java
index 487f4e9..23c34085 100644
--- a/core/tests/coretests/src/android/text/util/LinkifyTest.java
+++ b/core/tests/coretests/src/android/text/util/LinkifyTest.java
@@ -16,45 +16,49 @@
package android.text.util;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import android.content.Context;
import android.content.res.Configuration;
import android.os.LocaleList;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
+import android.support.test.runner.AndroidJUnit4;
import android.text.method.LinkMovementMethod;
import android.widget.TextView;
import java.util.Locale;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* LinkifyTest tests {@link Linkify}.
*/
-public class LinkifyTest extends AndroidTestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LinkifyTest {
private static final LocaleList LOCALE_LIST_US = new LocaleList(Locale.US);
private LocaleList mOriginalLocales;
+ private Context mContext;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getContext();
mOriginalLocales = LocaleList.getDefault();
LocaleList.setDefault(LOCALE_LIST_US);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void teardown() {
LocaleList.setDefault(mOriginalLocales);
- super.tearDown();
}
- private Context createUsEnglishContext() {
- final Configuration overrideConfig = new Configuration();
- overrideConfig.setLocales(LOCALE_LIST_US);
- return getContext().createConfigurationContext(overrideConfig);
- }
-
- @SmallTest
- public void testNothing() throws Exception {
+ @Test
+ public void testNothing() {
TextView tv;
tv = new TextView(createUsEnglishContext());
@@ -64,8 +68,8 @@
assertTrue(tv.getUrls().length == 0);
}
- @SmallTest
- public void testNormal() throws Exception {
+ @Test
+ public void testNormal() {
TextView tv;
tv = new TextView(createUsEnglishContext());
@@ -76,8 +80,8 @@
assertTrue(tv.getUrls().length == 2);
}
- @SmallTest
- public void testUnclickable() throws Exception {
+ @Test
+ public void testUnclickable() {
TextView tv;
tv = new TextView(createUsEnglishContext());
@@ -88,4 +92,10 @@
assertFalse(tv.getMovementMethod() instanceof LinkMovementMethod);
assertTrue(tv.getUrls().length == 2);
}
+
+ private Context createUsEnglishContext() {
+ final Configuration overrideConfig = new Configuration();
+ overrideConfig.setLocales(LOCALE_LIST_US);
+ return mContext.createConfigurationContext(overrideConfig);
+ }
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index f59e4fc..742fd60 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -118,7 +118,7 @@
if (isTextClassifierDisabled()) return;
String text = "Visit http://www.android.com for more information";
- String classifiedText = "http://www.android.com";
+ String classifiedText = "www.android.com";
int startIndex = text.indexOf(classifiedText);
int endIndex = startIndex + classifiedText.length();
assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES),
@@ -193,7 +193,19 @@
public boolean matches(Object o) {
if (o instanceof TextClassification) {
TextClassification result = (TextClassification) o;
- return text.equals(result.getText())
+ final boolean typeRequirementSatisfied;
+ switch (type) {
+ case TextClassifier.TYPE_URL:
+ String scheme = result.getIntent().getData().getScheme();
+ typeRequirementSatisfied = "http".equalsIgnoreCase(scheme)
+ || "https".equalsIgnoreCase(scheme);
+ break;
+ default:
+ typeRequirementSatisfied = true;
+ }
+
+ return typeRequirementSatisfied
+ && text.equals(result.getText())
&& result.getEntityCount() > 0
&& type.equals(result.getEntity(0));
// TODO: Include other properties.
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 2203b6a..ebab129 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -28,6 +28,7 @@
import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
import static android.widget.espresso.TextViewAssertions.hasSelection;
+import static android.widget.espresso.TextViewAssertions.doesNotHaveStyledText;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarItemIndex;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed;
@@ -47,9 +48,16 @@
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.is;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.text.TextUtils;
+import android.text.Spanned;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.ViewAssertion;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.View;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider;
@@ -64,6 +72,8 @@
import com.android.frameworks.coretests.R;
+import junit.framework.AssertionFailedError;
+
/**
* Tests the TextView widget from an Activity
*/
@@ -708,7 +718,8 @@
}
@Override
- public void onDestroyActionMode(ActionMode actionMode) {}
+ public void onDestroyActionMode(ActionMode actionMode) {
+ }
}));
final String text = "droid@android.com";
@@ -717,4 +728,50 @@
sleepForFloatingToolbarPopup();
assertFloatingToolbarItemIndex(android.R.id.textAssist, 0);
}
+
+ public void testPastePlainText_menuAction() throws Exception {
+ initializeClipboardWithText(TextStyle.STYLED);
+
+ onView(withId(R.id.textview)).perform(replaceText(""));
+ onView(withId(R.id.textview)).perform(longClick());
+ sleepForFloatingToolbarPopup();
+ clickFloatingToolbarItem(
+ getActivity().getString(com.android.internal.R.string.paste_as_plain_text));
+ getInstrumentation().waitForIdleSync();
+
+ onView(withId(R.id.textview)).check(matches(withText("styledtext")));
+ onView(withId(R.id.textview)).check(doesNotHaveStyledText());
+ }
+
+ public void testPastePlainText_noMenuItemForPlainText() {
+ initializeClipboardWithText(TextStyle.PLAIN);
+
+ onView(withId(R.id.textview)).perform(replaceText(""));
+ onView(withId(R.id.textview)).perform(longClick());
+ sleepForFloatingToolbarPopup();
+
+ assertFloatingToolbarDoesNotContainItem(
+ getActivity().getString(com.android.internal.R.string.paste_as_plain_text));
+ }
+
+ private void initializeClipboardWithText(TextStyle textStyle) {
+ final ClipData clip;
+ switch (textStyle) {
+ case STYLED:
+ clip = ClipData.newHtmlText("html", "styledtext", "<b>styledtext</b>");
+ break;
+ case PLAIN:
+ clip = ClipData.newPlainText("plain", "plaintext");
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid text style");
+ }
+ getActivity().getWindow().getDecorView().post(() ->
+ getActivity().getSystemService(ClipboardManager.class).setPrimaryClip( clip));
+ getInstrumentation().waitForIdleSync();
+ }
+
+ private enum TextStyle {
+ PLAIN, STYLED
+ }
}
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
index 6e44cd8..2532731 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
@@ -26,6 +26,8 @@
import android.graphics.drawable.Drawable;
import android.support.test.espresso.NoMatchingViewException;
import android.support.test.espresso.ViewAssertion;
+import android.text.Spanned;
+import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
@@ -100,22 +102,19 @@
* @param index A matcher representing the expected index.
*/
public static ViewAssertion hasInsertionPointerAtIndex(final Matcher<Integer> index) {
- return new ViewAssertion() {
- @Override
- public void check(View view, NoMatchingViewException exception) {
- if (view instanceof TextView) {
- TextView textView = (TextView) view;
- int selectionStart = textView.getSelectionStart();
- int selectionEnd = textView.getSelectionEnd();
- try {
- assertThat(selectionStart, index);
- assertThat(selectionEnd, index);
- } catch (IndexOutOfBoundsException e) {
- throw new AssertionFailedError(e.getMessage());
- }
- } else {
- throw new AssertionFailedError("TextView not found");
+ return (view, exception) -> {
+ if (view instanceof TextView) {
+ TextView textView = (TextView) view;
+ int selectionStart = textView.getSelectionStart();
+ int selectionEnd = textView.getSelectionEnd();
+ try {
+ assertThat(selectionStart, index);
+ assertThat(selectionEnd, index);
+ } catch (IndexOutOfBoundsException e) {
+ throw new AssertionFailedError(e.getMessage());
}
+ } else {
+ throw new AssertionFailedError("TextView not found");
}
};
}
@@ -137,6 +136,19 @@
}
/**
+ * Returns a {@link ViewAssertion} that asserts that the TextView does not contain styled text.
+ */
+ public static ViewAssertion doesNotHaveStyledText() {
+ return (view, exception) -> {
+ final CharSequence text = ((TextView) view).getText();
+ if (text instanceof Spanned && !TextUtils.hasStyleSpan((Spanned) text)) {
+ return;
+ }
+ throw new AssertionFailedError("TextView has styled text");
+ };
+ }
+
+ /**
* A {@link ViewAssertion} to check the selected text in a {@link TextView}.
*/
private static final class TextSelectionAssertion implements ViewAssertion {
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 344f3c8..86ab3dc 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -181,6 +181,9 @@
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
+ <!-- STOPSHIP(b/36856786): Revert this once it is fixed properly -->
+ <allow-in-power-save package="com.google.android.apps.enterprise.dmagent" />
+
<!-- These are the packages that are white-listed to be able to run as system user -->
<system-user-whitelisted-app package="com.android.settings" />
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index ad6ea2b..f38d8d2 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -230,6 +230,7 @@
FontFamily fontFamily = new FontFamily();
for (final FontFileResourceEntry fontFile : filesEntry.getEntries()) {
+ // TODO: Add ttc and variation font support. (b/37853920)
if (!fontFamily.addFontFromAssetManager(mgr, fontFile.getFileName(),
0 /* resourceCookie */, false /* isAsset */, 0 /* ttcIndex */,
fontFile.getWeight(), fontFile.isItalic() ? STYLE_ITALIC : STYLE_NORMAL,
@@ -237,11 +238,9 @@
return null;
}
}
- // Due to backward compatibility, even if the font is not supported by our font stack,
- // we need to place the empty font at the first place. The typeface with empty font
- // behaves different from default typeface especially in fallback font selection.
- fontFamily.allowUnsupportedFont();
- fontFamily.freeze();
+ if (!fontFamily.freeze()) {
+ return null;
+ }
FontFamily[] familyChain = { fontFamily };
typeface = createFromFamiliesWithDefault(familyChain,
RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index ffadad9..ab10e97 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -78,6 +78,7 @@
* Mask path is defined inside device configuration in following dimension: [100 x 100]
* @hide
*/
+ @TestApi
public static final float MASK_SIZE = 100f;
/**
@@ -179,7 +180,6 @@
*
* @param backgroundDrawable drawable that should be rendered in the background
* @param foregroundDrawable drawable that should be rendered in the foreground
- * @hide
*/
public AdaptiveIconDrawable(Drawable backgroundDrawable,
Drawable foregroundDrawable) {
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
new file mode 100644
index 0000000..9f2d129
--- /dev/null
+++ b/libs/hwui/Android.bp
@@ -0,0 +1,386 @@
+cc_defaults {
+ name: "hwui_defaults",
+ defaults: [
+ "hwui_static_deps",
+
+ //"hwui_bugreport_font_cache_usage",
+ //"hwui_compile_for_perf",
+
+ // Enables fine-grained GLES error checking
+ // If enabled, every GLES call is wrapped & error checked
+ // Has moderate overhead
+ //"hwui_enable_opengl-validation",
+ ],
+
+ cflags: [
+ "-DEGL_EGLEXT_PROTOTYPES",
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DATRACE_TAG=ATRACE_TAG_VIEW",
+ "-DLOG_TAG=\"OpenGLRenderer\"",
+ "-Wall",
+ "-Wno-unused-parameter",
+ "-Wunreachable-code",
+ "-Werror",
+ "-fvisibility=hidden",
+
+ // GCC false-positives on this warning, and since we -Werror that's
+ // a problem
+ "-Wno-free-nonheap-object",
+
+ // clang's warning is broken, see: https://llvm.org/bugs/show_bug.cgi?id=21629
+ "-Wno-missing-braces",
+
+ // TODO: Linear blending should be enabled by default, but we are
+ // TODO: making it an opt-in while it's a work in progress
+ //"-DANDROID_ENABLE_LINEAR_BLENDING",
+ ],
+
+ include_dirs: [
+ "external/skia/include/private",
+ "external/skia/src/core",
+ "external/skia/src/effects",
+ "external/skia/src/image",
+ "external/skia/src/utils",
+ ],
+
+ product_variables: {
+ device_uses_hwc2: {
+ cflags: ["-DUSE_HWC2"],
+ },
+ },
+}
+
+cc_defaults {
+ name: "hwui_static_deps",
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libutils",
+ "libEGL",
+ "libGLESv2",
+ "libvulkan",
+ "libskia",
+ "libui",
+ "libgui",
+ "libprotobuf-cpp-full",
+ "libharfbuzz_ng",
+ "libft2",
+ "libminikin",
+ "libandroidfw",
+ "libRScpp",
+ ],
+ static_libs: [
+ "libplatformprotos",
+ ],
+}
+
+cc_defaults {
+ name: "hwui_bugreport_font_cache_usage",
+ srcs: ["font/FontCacheHistoryTracker.cpp"],
+ cflags: ["-DBUGREPORT_FONT_CACHE_USAGE"],
+}
+
+cc_defaults {
+ name: "hwui_compile_for_perf",
+ // TODO: Non-arm?
+ cflags: [
+ "-fno-omit-frame-pointer",
+ "-marm",
+ "-mapcs",
+ ],
+}
+
+cc_defaults {
+ name: "hwui_debug",
+ cflags: ["-include debug/wrap_gles.h"],
+ srcs: [
+ "debug/wrap_gles.cpp",
+ "debug/DefaultGlesDriver.cpp",
+ "debug/GlesErrorCheckWrapper.cpp",
+ "debug/GlesDriver.cpp",
+ "debug/FatalBaseDriver.cpp",
+ "debug/NullGlesDriver.cpp",
+ ],
+ include_dirs: ["frameworks/native/opengl/libs/GLES2"],
+}
+
+cc_defaults {
+ name: "hwui_enable_opengl_validation",
+ defaults: ["hwui_debug"],
+ cflags: ["-DDEBUG_OPENGL=3"],
+ srcs: ["debug/wrap_gles.cpp"],
+ include_dirs: ["frameworks/native/opengl/libs/GLES2"],
+}
+
+// ------------------------
+// library
+// ------------------------
+
+cc_defaults {
+ name: "libhwui_defaults",
+ defaults: ["hwui_defaults"],
+ srcs: [
+ "hwui/Bitmap.cpp",
+ "font/CacheTexture.cpp",
+ "font/Font.cpp",
+ "hwui/Canvas.cpp",
+ "hwui/MinikinSkia.cpp",
+ "hwui/MinikinUtils.cpp",
+ "hwui/PaintImpl.cpp",
+ "hwui/Typeface.cpp",
+ "pipeline/skia/GLFunctorDrawable.cpp",
+ "pipeline/skia/LayerDrawable.cpp",
+ "pipeline/skia/RenderNodeDrawable.cpp",
+ "pipeline/skia/ReorderBarrierDrawables.cpp",
+ "pipeline/skia/SkiaDisplayList.cpp",
+ "pipeline/skia/SkiaOpenGLPipeline.cpp",
+ "pipeline/skia/SkiaOpenGLReadback.cpp",
+ "pipeline/skia/SkiaPipeline.cpp",
+ "pipeline/skia/SkiaProfileRenderer.cpp",
+ "pipeline/skia/SkiaRecordingCanvas.cpp",
+ "pipeline/skia/SkiaVulkanPipeline.cpp",
+ "renderstate/Blend.cpp",
+ "renderstate/MeshState.cpp",
+ "renderstate/OffscreenBufferPool.cpp",
+ "renderstate/PixelBufferState.cpp",
+ "renderstate/RenderState.cpp",
+ "renderstate/Scissor.cpp",
+ "renderstate/Stencil.cpp",
+ "renderstate/TextureState.cpp",
+ "renderthread/CanvasContext.cpp",
+ "renderthread/OpenGLPipeline.cpp",
+ "renderthread/DrawFrameTask.cpp",
+ "renderthread/EglManager.cpp",
+ "renderthread/VulkanManager.cpp",
+ "renderthread/RenderProxy.cpp",
+ "renderthread/RenderTask.cpp",
+ "renderthread/RenderThread.cpp",
+ "renderthread/TimeLord.cpp",
+ "renderthread/Frame.cpp",
+ "service/GraphicsStatsService.cpp",
+ "thread/TaskManager.cpp",
+ "utils/Blur.cpp",
+ "utils/Color.cpp",
+ "utils/GLUtils.cpp",
+ "utils/LinearAllocator.cpp",
+ "utils/StringUtils.cpp",
+ "utils/TestWindowContext.cpp",
+ "utils/VectorDrawableUtils.cpp",
+ "AmbientShadow.cpp",
+ "AnimationContext.cpp",
+ "Animator.cpp",
+ "AnimatorManager.cpp",
+ "BakedOpDispatcher.cpp",
+ "BakedOpRenderer.cpp",
+ "BakedOpState.cpp",
+ "Caches.cpp",
+ "CanvasState.cpp",
+ "ClipArea.cpp",
+ "DamageAccumulator.cpp",
+ "DeferredLayerUpdater.cpp",
+ "DeviceInfo.cpp",
+ "DisplayList.cpp",
+ "Extensions.cpp",
+ "FboCache.cpp",
+ "FontRenderer.cpp",
+ "FrameBuilder.cpp",
+ "FrameInfo.cpp",
+ "FrameInfoVisualizer.cpp",
+ "GammaFontRenderer.cpp",
+ "GlLayer.cpp",
+ "GlopBuilder.cpp",
+ "GpuMemoryTracker.cpp",
+ "GradientCache.cpp",
+ "Image.cpp",
+ "Interpolator.cpp",
+ "JankTracker.cpp",
+ "Layer.cpp",
+ "LayerBuilder.cpp",
+ "LayerUpdateQueue.cpp",
+ "Matrix.cpp",
+ "OpDumper.cpp",
+ "OpenGLReadback.cpp",
+ "Patch.cpp",
+ "PatchCache.cpp",
+ "PathCache.cpp",
+ "PathParser.cpp",
+ "PathTessellator.cpp",
+ "PixelBuffer.cpp",
+ "ProfileRenderer.cpp",
+ "Program.cpp",
+ "ProgramCache.cpp",
+ "Properties.cpp",
+ "PropertyValuesAnimatorSet.cpp",
+ "PropertyValuesHolder.cpp",
+ "RecordingCanvas.cpp",
+ "RenderBufferCache.cpp",
+ "RenderNode.cpp",
+ "RenderProperties.cpp",
+ "ResourceCache.cpp",
+ "ShadowTessellator.cpp",
+ "SkiaCanvas.cpp",
+ "SkiaCanvasProxy.cpp",
+ "SkiaShader.cpp",
+ "Snapshot.cpp",
+ "SpotShadow.cpp",
+ "TessellationCache.cpp",
+ "TextDropShadowCache.cpp",
+ "Texture.cpp",
+ "TextureCache.cpp",
+ "VectorDrawable.cpp",
+ "VkLayer.cpp",
+ "protos/hwui.proto",
+ ],
+
+ proto: {
+ export_proto_headers: true,
+ },
+
+ export_include_dirs: ["."],
+}
+
+cc_library {
+ name: "libhwui",
+ defaults: ["libhwui_defaults"],
+}
+
+// ------------------------
+// static library null gpu
+// ------------------------
+
+cc_library_static {
+ name: "libhwui_static_debug",
+ defaults: [
+ "libhwui_defaults",
+ "hwui_debug",
+ ],
+ cflags: ["-DHWUI_NULL_GPU"],
+ srcs: [
+ "debug/nullegl.cpp",
+ ],
+ export_include_dirs: ["."],
+}
+
+cc_defaults {
+ name: "hwui_test_defaults",
+ defaults: ["hwui_defaults"],
+ test_suites: ["device-tests"],
+ srcs: [
+ "tests/common/scenes/*.cpp",
+ "tests/common/LeakChecker.cpp",
+ "tests/common/TestListViewSceneBase.cpp",
+ "tests/common/TestContext.cpp",
+ "tests/common/TestScene.cpp",
+ "tests/common/TestUtils.cpp",
+ ],
+}
+
+// ------------------------
+// unit tests
+// ------------------------
+
+cc_test {
+ name: "hwui_unit_tests",
+ defaults: ["hwui_test_defaults"],
+
+ static_libs: [
+ "libgmock",
+ "libhwui_static_debug",
+ ],
+ shared_libs: ["libmemunreachable"],
+ cflags: [
+ "-include debug/wrap_gles.h",
+ "-DHWUI_NULL_GPU",
+ ],
+
+ srcs: [
+ "tests/unit/main.cpp",
+ "tests/unit/BakedOpDispatcherTests.cpp",
+ "tests/unit/BakedOpRendererTests.cpp",
+ "tests/unit/BakedOpStateTests.cpp",
+ "tests/unit/BitmapTests.cpp",
+ "tests/unit/CanvasContextTests.cpp",
+ "tests/unit/CanvasStateTests.cpp",
+ "tests/unit/ClipAreaTests.cpp",
+ "tests/unit/DamageAccumulatorTests.cpp",
+ "tests/unit/DeferredLayerUpdaterTests.cpp",
+ "tests/unit/DeviceInfoTests.cpp",
+ "tests/unit/FatVectorTests.cpp",
+ "tests/unit/FontRendererTests.cpp",
+ "tests/unit/FrameBuilderTests.cpp",
+ "tests/unit/GlopBuilderTests.cpp",
+ "tests/unit/GpuMemoryTrackerTests.cpp",
+ "tests/unit/GradientCacheTests.cpp",
+ "tests/unit/GraphicsStatsServiceTests.cpp",
+ "tests/unit/LayerUpdateQueueTests.cpp",
+ "tests/unit/LeakCheckTests.cpp",
+ "tests/unit/LinearAllocatorTests.cpp",
+ "tests/unit/MatrixTests.cpp",
+ "tests/unit/MeshStateTests.cpp",
+ "tests/unit/OffscreenBufferPoolTests.cpp",
+ "tests/unit/OpDumperTests.cpp",
+ "tests/unit/PathInterpolatorTests.cpp",
+ "tests/unit/RenderNodeDrawableTests.cpp",
+ "tests/unit/RecordingCanvasTests.cpp",
+ "tests/unit/RenderNodeTests.cpp",
+ "tests/unit/RenderPropertiesTests.cpp",
+ "tests/unit/SkiaBehaviorTests.cpp",
+ "tests/unit/SkiaDisplayListTests.cpp",
+ "tests/unit/SkiaPipelineTests.cpp",
+ "tests/unit/SkiaRenderPropertiesTests.cpp",
+ "tests/unit/SkiaCanvasTests.cpp",
+ "tests/unit/SnapshotTests.cpp",
+ "tests/unit/StringUtilsTests.cpp",
+ "tests/unit/TestUtilsTests.cpp",
+ "tests/unit/TextDropShadowCacheTests.cpp",
+ "tests/unit/TextureCacheTests.cpp",
+ "tests/unit/VectorDrawableTests.cpp",
+ ],
+}
+
+// ------------------------
+// Macro-bench app
+// ------------------------
+
+cc_benchmark {
+ name: "hwuimacro",
+ defaults: ["hwui_test_defaults"],
+
+ // set to libhwui_static_debug to skip actual GL commands
+ whole_static_libs: ["libhwui"],
+ shared_libs: ["libmemunreachable"],
+
+ srcs: [
+ "tests/macrobench/TestSceneRunner.cpp",
+ "tests/macrobench/main.cpp",
+ ],
+}
+
+// ------------------------
+// Micro-bench app
+// ---------------------
+
+cc_benchmark {
+ name: "hwuimicro",
+ defaults: ["hwui_test_defaults"],
+
+ cflags: [
+ "-include debug/wrap_gles.h",
+ "-DHWUI_NULL_GPU",
+ ],
+
+ whole_static_libs: ["libhwui_static_debug"],
+ shared_libs: ["libmemunreachable"],
+
+ srcs: [
+ "tests/microbench/main.cpp",
+ "tests/microbench/DisplayListCanvasBench.cpp",
+ "tests/microbench/FontBench.cpp",
+ "tests/microbench/FrameBuilderBench.cpp",
+ "tests/microbench/LinearAllocatorBench.cpp",
+ "tests/microbench/PathParserBench.cpp",
+ "tests/microbench/RenderNodeBench.cpp",
+ "tests/microbench/ShadowBench.cpp",
+ "tests/microbench/TaskManagerBench.cpp",
+ ],
+}
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
deleted file mode 100644
index 1e0eeb1..0000000
--- a/libs/hwui/Android.mk
+++ /dev/null
@@ -1,386 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-BUGREPORT_FONT_CACHE_USAGE := false
-
-# Enables fine-grained GLES error checking
-# If set to true, every GLES call is wrapped & error checked
-# Has moderate overhead
-HWUI_ENABLE_OPENGL_VALIDATION := false
-
-hwui_src_files := \
- hwui/Bitmap.cpp \
- font/CacheTexture.cpp \
- font/Font.cpp \
- hwui/Canvas.cpp \
- hwui/MinikinSkia.cpp \
- hwui/MinikinUtils.cpp \
- hwui/PaintImpl.cpp \
- hwui/Typeface.cpp \
- pipeline/skia/GLFunctorDrawable.cpp \
- pipeline/skia/LayerDrawable.cpp \
- pipeline/skia/RenderNodeDrawable.cpp \
- pipeline/skia/ReorderBarrierDrawables.cpp \
- pipeline/skia/SkiaDisplayList.cpp \
- pipeline/skia/SkiaOpenGLPipeline.cpp \
- pipeline/skia/SkiaOpenGLReadback.cpp \
- pipeline/skia/SkiaPipeline.cpp \
- pipeline/skia/SkiaProfileRenderer.cpp \
- pipeline/skia/SkiaRecordingCanvas.cpp \
- pipeline/skia/SkiaVulkanPipeline.cpp \
- renderstate/Blend.cpp \
- renderstate/MeshState.cpp \
- renderstate/OffscreenBufferPool.cpp \
- renderstate/PixelBufferState.cpp \
- renderstate/RenderState.cpp \
- renderstate/Scissor.cpp \
- renderstate/Stencil.cpp \
- renderstate/TextureState.cpp \
- renderthread/CanvasContext.cpp \
- renderthread/OpenGLPipeline.cpp \
- renderthread/DrawFrameTask.cpp \
- renderthread/EglManager.cpp \
- renderthread/VulkanManager.cpp \
- renderthread/RenderProxy.cpp \
- renderthread/RenderTask.cpp \
- renderthread/RenderThread.cpp \
- renderthread/TimeLord.cpp \
- renderthread/Frame.cpp \
- service/GraphicsStatsService.cpp \
- thread/TaskManager.cpp \
- utils/Blur.cpp \
- utils/Color.cpp \
- utils/GLUtils.cpp \
- utils/LinearAllocator.cpp \
- utils/StringUtils.cpp \
- utils/TestWindowContext.cpp \
- utils/VectorDrawableUtils.cpp \
- AmbientShadow.cpp \
- AnimationContext.cpp \
- Animator.cpp \
- AnimatorManager.cpp \
- BakedOpDispatcher.cpp \
- BakedOpRenderer.cpp \
- BakedOpState.cpp \
- Caches.cpp \
- CanvasState.cpp \
- ClipArea.cpp \
- DamageAccumulator.cpp \
- DeferredLayerUpdater.cpp \
- DeviceInfo.cpp \
- DisplayList.cpp \
- Extensions.cpp \
- FboCache.cpp \
- FontRenderer.cpp \
- FrameBuilder.cpp \
- FrameInfo.cpp \
- FrameInfoVisualizer.cpp \
- GammaFontRenderer.cpp \
- GlLayer.cpp \
- GlopBuilder.cpp \
- GpuMemoryTracker.cpp \
- GradientCache.cpp \
- Image.cpp \
- Interpolator.cpp \
- JankTracker.cpp \
- Layer.cpp \
- LayerBuilder.cpp \
- LayerUpdateQueue.cpp \
- Matrix.cpp \
- OpDumper.cpp \
- OpenGLReadback.cpp \
- Patch.cpp \
- PatchCache.cpp \
- PathCache.cpp \
- PathParser.cpp \
- PathTessellator.cpp \
- PixelBuffer.cpp \
- ProfileRenderer.cpp \
- Program.cpp \
- ProgramCache.cpp \
- Properties.cpp \
- PropertyValuesAnimatorSet.cpp \
- PropertyValuesHolder.cpp \
- RecordingCanvas.cpp \
- RenderBufferCache.cpp \
- RenderNode.cpp \
- RenderProperties.cpp \
- ResourceCache.cpp \
- ShadowTessellator.cpp \
- SkiaCanvas.cpp \
- SkiaCanvasProxy.cpp \
- SkiaShader.cpp \
- Snapshot.cpp \
- SpotShadow.cpp \
- TessellationCache.cpp \
- TextDropShadowCache.cpp \
- Texture.cpp \
- TextureCache.cpp \
- VectorDrawable.cpp \
- VkLayer.cpp \
- protos/hwui.proto
-
-hwui_test_common_src_files := \
- $(call all-cpp-files-under, tests/common/scenes) \
- tests/common/LeakChecker.cpp \
- tests/common/TestListViewSceneBase.cpp \
- tests/common/TestContext.cpp \
- tests/common/TestScene.cpp \
- tests/common/TestUtils.cpp
-
-hwui_debug_common_src_files := \
- debug/wrap_gles.cpp \
- debug/DefaultGlesDriver.cpp \
- debug/GlesErrorCheckWrapper.cpp \
- debug/GlesDriver.cpp \
- debug/FatalBaseDriver.cpp \
- debug/NullGlesDriver.cpp
-
-hwui_cflags := \
- -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES \
- -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \
- -Wall -Wno-unused-parameter -Wunreachable-code -Werror
-
-ifeq ($(TARGET_USES_HWC2),true)
- hwui_cflags += -DUSE_HWC2
-endif
-
-# TODO: Linear blending should be enabled by default, but we are
-# TODO: making it an opt-in while it's a work in progress
-# TODO: The final test should be:
-# TODO: ifneq ($(TARGET_ENABLE_LINEAR_BLENDING),false)
-ifeq ($(TARGET_ENABLE_LINEAR_BLENDING),true)
- hwui_cflags += -DANDROID_ENABLE_LINEAR_BLENDING
-endif
-
-# GCC false-positives on this warning, and since we -Werror that's
-# a problem
-hwui_cflags += -Wno-free-nonheap-object
-
-# clang's warning is broken, see: https://llvm.org/bugs/show_bug.cgi?id=21629
-hwui_cflags += -Wno-missing-braces
-
-ifeq (true, $(BUGREPORT_FONT_CACHE_USAGE))
- hwui_src_files += \
- font/FontCacheHistoryTracker.cpp
- hwui_cflags += -DBUGREPORT_FONT_CACHE_USAGE
-endif
-
-ifndef HWUI_COMPILE_SYMBOLS
- hwui_cflags += -fvisibility=hidden
-endif
-
-ifdef HWUI_COMPILE_FOR_PERF
- # TODO: Non-arm?
- hwui_cflags += -fno-omit-frame-pointer -marm -mapcs
-endif
-
-# This has to be lazy-resolved because it depends on the LOCAL_MODULE_CLASS
-# which varies depending on what is being built
-define hwui_proto_include
-$(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
-endef
-
-hwui_c_includes += \
- external/skia/include/private \
- external/skia/src/core \
- external/skia/src/effects \
- external/skia/src/image \
- external/skia/src/utils \
- external/icu/icu4c/source/common \
- external/harfbuzz_ng/src \
- external/freetype/include
-
-# enable RENDERSCRIPT
-hwui_c_includes += \
- $(call intermediates-dir-for,STATIC_LIBRARIES,TARGET,) \
- frameworks/rs/cpp \
- frameworks/rs
-
-# ------------------------
-# static library
-# ------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := libhwui_static
-LOCAL_CFLAGS := $(hwui_cflags)
-LOCAL_SRC_FILES := $(hwui_src_files)
-
-ifeq (true, $(HWUI_ENABLE_OPENGL_VALIDATION))
- LOCAL_CFLAGS += -include debug/wrap_gles.h
- LOCAL_CFLAGS += -DDEBUG_OPENGL=3
- LOCAL_SRC_FILES += $(hwui_debug_common_src_files)
-endif
-
-LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(LOCAL_PATH) \
- $(call hwui_proto_include)
-
-include $(LOCAL_PATH)/hwui_static_deps.mk
-include $(BUILD_STATIC_LIBRARY)
-
-# ------------------------
-# static library null gpu
-# ------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := libhwui_static_debug
-LOCAL_CFLAGS := \
- $(hwui_cflags) \
- -include debug/wrap_gles.h \
- -DHWUI_NULL_GPU
-LOCAL_SRC_FILES := \
- $(hwui_src_files) \
- $(hwui_debug_common_src_files) \
- debug/nullegl.cpp
-LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(LOCAL_PATH) \
- $(call hwui_proto_include)
-
-include $(LOCAL_PATH)/hwui_static_deps.mk
-include $(BUILD_STATIC_LIBRARY)
-
-# ------------------------
-# shared library
-# ------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE := libhwui
-LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-include $(LOCAL_PATH)/hwui_static_deps.mk
-include $(BUILD_SHARED_LIBRARY)
-
-# ------------------------
-# unit tests
-# ------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := hwui_unit_tests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_LIBRARIES := libgmock libhwui_static_debug
-LOCAL_SHARED_LIBRARIES := libmemunreachable
-LOCAL_CFLAGS := \
- $(hwui_cflags) \
- -include debug/wrap_gles.h \
- -DHWUI_NULL_GPU
-LOCAL_C_INCLUDES := $(hwui_c_includes)
-
-LOCAL_SRC_FILES += \
- $(hwui_test_common_src_files) \
- tests/unit/main.cpp \
- tests/unit/BakedOpDispatcherTests.cpp \
- tests/unit/BakedOpRendererTests.cpp \
- tests/unit/BakedOpStateTests.cpp \
- tests/unit/BitmapTests.cpp \
- tests/unit/CanvasContextTests.cpp \
- tests/unit/CanvasStateTests.cpp \
- tests/unit/ClipAreaTests.cpp \
- tests/unit/DamageAccumulatorTests.cpp \
- tests/unit/DeferredLayerUpdaterTests.cpp \
- tests/unit/DeviceInfoTests.cpp \
- tests/unit/FatVectorTests.cpp \
- tests/unit/FontRendererTests.cpp \
- tests/unit/FrameBuilderTests.cpp \
- tests/unit/GlopBuilderTests.cpp \
- tests/unit/GpuMemoryTrackerTests.cpp \
- tests/unit/GradientCacheTests.cpp \
- tests/unit/GraphicsStatsServiceTests.cpp \
- tests/unit/LayerUpdateQueueTests.cpp \
- tests/unit/LeakCheckTests.cpp \
- tests/unit/LinearAllocatorTests.cpp \
- tests/unit/MatrixTests.cpp \
- tests/unit/MeshStateTests.cpp \
- tests/unit/OffscreenBufferPoolTests.cpp \
- tests/unit/OpDumperTests.cpp \
- tests/unit/PathInterpolatorTests.cpp \
- tests/unit/RenderNodeDrawableTests.cpp \
- tests/unit/RecordingCanvasTests.cpp \
- tests/unit/RenderNodeTests.cpp \
- tests/unit/RenderPropertiesTests.cpp \
- tests/unit/SkiaBehaviorTests.cpp \
- tests/unit/SkiaDisplayListTests.cpp \
- tests/unit/SkiaPipelineTests.cpp \
- tests/unit/SkiaRenderPropertiesTests.cpp \
- tests/unit/SkiaCanvasTests.cpp \
- tests/unit/SnapshotTests.cpp \
- tests/unit/StringUtilsTests.cpp \
- tests/unit/TestUtilsTests.cpp \
- tests/unit/TextDropShadowCacheTests.cpp \
- tests/unit/TextureCacheTests.cpp \
- tests/unit/VectorDrawableTests.cpp \
-
-include $(LOCAL_PATH)/hwui_static_deps.mk
-include $(BUILD_NATIVE_TEST)
-
-# ------------------------
-# Macro-bench app
-# ------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp
-LOCAL_MODULE:= hwuimacro
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-LOCAL_MULTILIB := both
-LOCAL_CFLAGS := $(hwui_cflags)
-LOCAL_C_INCLUDES := $(hwui_c_includes)
-
-# set to libhwui_static_debug to skip actual GL commands
-LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
-LOCAL_SHARED_LIBRARIES := libmemunreachable
-
-LOCAL_SRC_FILES += \
- $(hwui_test_common_src_files) \
- tests/macrobench/TestSceneRunner.cpp \
- tests/macrobench/main.cpp
-
-include $(LOCAL_PATH)/hwui_static_deps.mk
-include $(BUILD_NATIVE_BENCHMARK)
-
-# ------------------------
-# Micro-bench app
-# ---------------------
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= hwuimicro
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := \
- $(hwui_cflags) \
- -include debug/wrap_gles.h \
- -DHWUI_NULL_GPU
-
-LOCAL_C_INCLUDES := $(hwui_c_includes)
-
-LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static_debug
-LOCAL_SHARED_LIBRARIES := libmemunreachable
-
-LOCAL_SRC_FILES += \
- $(hwui_test_common_src_files) \
- tests/microbench/main.cpp \
- tests/microbench/DisplayListCanvasBench.cpp \
- tests/microbench/FontBench.cpp \
- tests/microbench/FrameBuilderBench.cpp \
- tests/microbench/LinearAllocatorBench.cpp \
- tests/microbench/PathParserBench.cpp \
- tests/microbench/RenderNodeBench.cpp \
- tests/microbench/ShadowBench.cpp \
- tests/microbench/TaskManagerBench.cpp
-
-
-include $(LOCAL_PATH)/hwui_static_deps.mk
-include $(BUILD_NATIVE_BENCHMARK)
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 8126d57..028d9f7 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -291,7 +291,6 @@
/ kSlowFrameBucketIntervalMs;
framebucket = std::min(framebucket,
static_cast<uint32_t>(mData->slowFrameCounts.size() - 1));
- framebucket = std::max(framebucket, 0u);
mData->slowFrameCounts[framebucket]++;
}
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 929d1606..b113626 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -317,7 +317,17 @@
}
void Bitmap::setColorSpace(sk_sp<SkColorSpace> colorSpace) {
- reconfigure(info().makeColorSpace(std::move(colorSpace)), rowBytes(), sk_ref_sp(colorTable()));
+ mInfo = mInfo.makeColorSpace(std::move(colorSpace));
+}
+
+static SkImageInfo validateAlpha(const SkImageInfo& info) {
+ // Need to validate the alpha type to filter against the color type
+ // to prevent things like a non-opaque RGB565 bitmap
+ SkAlphaType alphaType;
+ LOG_ALWAYS_FATAL_IF(!SkColorTypeValidateAlphaType(
+ info.colorType(), info.alphaType(), &alphaType),
+ "Failed to validate alpha type!");
+ return info.makeAlphaType(alphaType);
}
void Bitmap::reconfigure(const SkImageInfo& newInfo, size_t rowBytes, sk_sp<SkColorTable> ctable) {
@@ -325,19 +335,14 @@
ctable = nullptr;
}
- // Need to validate the alpha type to filter against the color type
- // to prevent things like a non-opaque RGB565 bitmap
- SkAlphaType alphaType;
- LOG_ALWAYS_FATAL_IF(!SkColorTypeValidateAlphaType(
- newInfo.colorType(), newInfo.alphaType(), &alphaType),
- "Failed to validate alpha type!");
+ mInfo = validateAlpha(newInfo);
// Dirty hack is dirty
// TODO: Figure something out here, Skia's current design makes this
// really hard to work with. Skia really, really wants immutable objects,
// but with the nested-ref-count hackery going on that's just not
// feasible without going insane trying to figure it out
- this->android_only_reset(newInfo.makeAlphaType(alphaType), rowBytes, std::move(ctable));
+ this->android_only_reset(mInfo.width(), mInfo.height(), rowBytes, std::move(ctable));
}
static sk_sp<SkColorTable> sanitize(const SkImageInfo& info, sk_sp<SkColorTable> ctable) {
@@ -347,8 +352,11 @@
}
return nullptr; // drop the ctable if we're not indexed
}
-Bitmap::Bitmap(void* address, size_t size, const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable)
- : SkPixelRef(info, address, rowBytes, sanitize(info, std::move(ctable)))
+Bitmap::Bitmap(void* address, size_t size, const SkImageInfo& info, size_t rowBytes,
+ sk_sp<SkColorTable> ctable)
+ : SkPixelRef(info.width(), info.height(), address, rowBytes,
+ sanitize(info, std::move(ctable)))
+ , mInfo(validateAlpha(info))
, mPixelStorageType(PixelStorageType::Heap) {
mPixelStorage.heap.address = address;
mPixelStorage.heap.size = size;
@@ -356,7 +364,9 @@
Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc,
const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable)
- : SkPixelRef(info, address, rowBytes, sanitize(info, std::move(ctable)))
+ : SkPixelRef(info.width(), info.height(), address, rowBytes,
+ sanitize(info, std::move(ctable)))
+ , mInfo(validateAlpha(info))
, mPixelStorageType(PixelStorageType::External) {
mPixelStorage.external.address = address;
mPixelStorage.external.context = context;
@@ -365,7 +375,9 @@
Bitmap::Bitmap(void* address, int fd, size_t mappedSize,
const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable)
- : SkPixelRef(info, address, rowBytes, sanitize(info, std::move(ctable)))
+ : SkPixelRef(info.width(), info.height(), address, rowBytes,
+ sanitize(info, std::move(ctable)))
+ , mInfo(validateAlpha(info))
, mPixelStorageType(PixelStorageType::Ashmem) {
mPixelStorage.ashmem.address = address;
mPixelStorage.ashmem.fd = fd;
@@ -373,9 +385,10 @@
}
Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info)
- : SkPixelRef(info, nullptr,
+ : SkPixelRef(info.width(), info.height(), nullptr,
bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride(),
nullptr)
+ , mInfo(validateAlpha(info))
, mPixelStorageType(PixelStorageType::Hardware) {
mPixelStorage.hardware.buffer = buffer;
buffer->incStrong(buffer);
@@ -428,10 +441,6 @@
}
}
-size_t Bitmap::getAllocatedSizeInBytes() const {
- return info().getSafeSize(this->rowBytes());
-}
-
int Bitmap::getAshmemFd() const {
switch (mPixelStorageType) {
case PixelStorageType::Ashmem:
@@ -459,7 +468,7 @@
return;
}
- changeAlphaType(alphaType);
+ mInfo = mInfo.makeAlphaType(alphaType);
}
void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
@@ -470,19 +479,19 @@
uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap);
return;
}
- outBitmap->setInfo(info(), rowBytes());
+ outBitmap->setInfo(mInfo, rowBytes());
outBitmap->setPixelRef(sk_ref_sp(this), 0, 0);
}
void Bitmap::getSkBitmapForShaders(SkBitmap* outBitmap) {
- outBitmap->setInfo(info(), rowBytes());
+ outBitmap->setInfo(mInfo, rowBytes());
outBitmap->setPixelRef(sk_ref_sp(this), 0, 0);
outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
}
void Bitmap::getBounds(SkRect* bounds) const {
SkASSERT(bounds);
- bounds->set(0, 0, SkIntToScalar(info().width()), SkIntToScalar(info().height()));
+ bounds->set(0, 0, SkIntToScalar(width()), SkIntToScalar(height()));
}
GraphicBuffer* Bitmap::graphicBuffer() {
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 701b9db..9a76715 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -67,11 +67,8 @@
Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
size_t rowBytes, sk_sp<SkColorTable> ctable);
- int width() const { return info().width(); }
- int height() const { return info().height(); }
-
int rowBytesAsPixels() const {
- return rowBytes() >> info().shiftPerPixel();
+ return rowBytes() >> SkColorTypeShiftPerPixel(mInfo.colorType());
}
void reconfigure(const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable);
@@ -91,8 +88,12 @@
void setHasHardwareMipMap(bool hasMipMap);
bool hasHardwareMipMap() const;
- bool isOpaque() const {return info().isOpaque(); }
- SkColorType colorType() const { return info().colorType(); }
+ bool isOpaque() const { return mInfo.isOpaque(); }
+ SkColorType colorType() const { return mInfo.colorType(); }
+ const SkImageInfo& info() const {
+ return mInfo;
+ }
+
void getBounds(SkRect* bounds) const;
bool readyToDraw() const {
@@ -104,13 +105,13 @@
}
GraphicBuffer* graphicBuffer();
-protected:
- virtual size_t getAllocatedSizeInBytes() const override;
private:
Bitmap(GraphicBuffer* buffer, const SkImageInfo& info);
virtual ~Bitmap();
void* getStorage() const;
+ SkImageInfo mInfo;
+
const PixelStorageType mPixelStorageType;
bool mHasHardwareMipMap = false;
@@ -136,4 +137,4 @@
} mPixelStorage;
};
-} //namespace android
\ No newline at end of file
+} //namespace android
diff --git a/libs/hwui/hwui_static_deps.mk b/libs/hwui/hwui_static_deps.mk
deleted file mode 100644
index 8826cfc..0000000
--- a/libs/hwui/hwui_static_deps.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-###############################################################################
-#
-#
-# This file contains the shared and static dependencies needed by any target
-# that attempts to statically link HWUI (i.e. libhwui_static build target). This
-# file should be included by any target that lists libhwui_static as a
-# dependency.
-#
-# This is a workaround for the fact that the build system does not add these
-# transitive dependencies when it attempts to link libhwui_static into another
-# library.
-#
-###############################################################################
-
-LOCAL_SHARED_LIBRARIES += \
- liblog \
- libcutils \
- libutils \
- libEGL \
- libGLESv2 \
- libvulkan \
- libskia \
- libui \
- libgui \
- libprotobuf-cpp-full \
- libharfbuzz_ng \
- libft2 \
- libminikin \
- libandroidfw \
- libRScpp
-
-LOCAL_STATIC_LIBRARIES += \
- libplatformprotos
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index bd798e8..fcdd814 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -819,7 +819,7 @@
EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected";
}
-OPENGL_PIPELINE_TEST(FrameBuilder, renderNode) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderNode) {
class RenderNodeTestRenderer : public TestRendererBase {
public:
void onRectOp(const RectOp& op, const BakedOpState& state) override {
@@ -2321,7 +2321,7 @@
EXPECT_EQ(1, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) {
/* R is backward projected on B
A
/ \
@@ -2351,7 +2351,7 @@
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) {
/* R is backward projected on E
A
/ | \
@@ -2383,7 +2383,7 @@
EXPECT_EQ(4, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) {
/* R is backward projected without receiver
A
/ \
@@ -2412,7 +2412,7 @@
EXPECT_EQ(2, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) {
/* R is backward projected on C
A
/ \
@@ -2441,7 +2441,7 @@
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
[](RenderProperties& props, RecordingCanvas& canvas) {
drawOrderedNode(&canvas, 0, nullptr); //nodeB
@@ -2464,7 +2464,7 @@
EXPECT_EQ(2, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) {
//TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a
//bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical
//tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling
@@ -2497,7 +2497,7 @@
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) {
/* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed.
A
|
@@ -2530,7 +2530,7 @@
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) {
/* R is backward projected on B
A
|
@@ -2562,7 +2562,7 @@
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) {
/* B and G are receivables, R is backward projected
A
/ \
@@ -2595,7 +2595,7 @@
EXPECT_EQ(4, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) {
/* B and G are receivables, G is backward projected
A
/ \
@@ -2628,7 +2628,7 @@
EXPECT_EQ(4, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) {
/* B and G are receivables, R is backward projected
A
/ \
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 6bc5e91..9bd5994 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -36,6 +36,7 @@
import android.os.SystemProperties;
import android.util.Log;
+import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.R;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.TelephonyProperties;
@@ -364,7 +365,8 @@
// Construct Notification
if (mNiNotificationBuilder == null) {
- mNiNotificationBuilder = new Notification.Builder(mContext)
+ mNiNotificationBuilder = new Notification.Builder(mContext,
+ SystemNotificationChannels.NETWORK_ALERTS)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_gps_on)
.setWhen(0)
.setOngoing(true)
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index 29d1986..b1dc3ad 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -357,6 +357,20 @@
}
/**
+ * @hide
+ * Internal listener setter, no null checks on listener nor handler
+ * @param listener
+ * @param handler
+ * @return this {@code Builder} instance.
+ */
+ @NonNull Builder setOnAudioFocusChangeListenerInt(
+ OnAudioFocusChangeListener listener, Handler handler) {
+ mFocusListener = listener;
+ mListenerHandler = handler;
+ return this;
+ }
+
+ /**
* Sets the listener called when audio focus changes after being requested with
* {@link AudioManager#requestAudioFocus(AudioFocusRequest)}, and until being abandoned
* with {@link AudioManager#abandonAudioFocusRequest(AudioFocusRequest)}.
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index ce07c99..0b5dff2 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2445,7 +2445,7 @@
}
final AudioFocusRequest afr = new AudioFocusRequest.Builder(durationHint)
- .setOnAudioFocusChangeListener(l, null /* no Handler for this legacy API */)
+ .setOnAudioFocusChangeListenerInt(l, null /* no Handler for this legacy API */)
.setAudioAttributes(requestAttributes)
.setAcceptsDelayedFocusGain((flags & AUDIOFOCUS_FLAG_DELAY_OK)
== AUDIOFOCUS_FLAG_DELAY_OK)
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index e634dc2..dd66649 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -536,9 +536,9 @@
throw new IllegalArgumentException("Use of STREAM_ACCESSIBILITY is reserved for "
+ "volume control");
}
- Log.e(className, "Use of stream types is deprecated for operations other than " +
- "volume control.");
- Log.e(className, "See the documentation of " + opName + " for what to use instead with " +
+ Log.w(className, "Use of stream types is deprecated for operations other than " +
+ "volume control");
+ Log.w(className, "See the documentation of " + opName + " for what to use instead with " +
"android.media.AudioAttributes to qualify your playback use case");
}
}
diff --git a/media/java/android/media/midi/IMidiDeviceServer.aidl b/media/java/android/media/midi/IMidiDeviceServer.aidl
index f17e19d..59f0f23 100644
--- a/media/java/android/media/midi/IMidiDeviceServer.aidl
+++ b/media/java/android/media/midi/IMidiDeviceServer.aidl
@@ -31,5 +31,7 @@
int connectPorts(IBinder token, in FileDescriptor fd, int outputPortNumber);
MidiDeviceInfo getDeviceInfo();
- void setDeviceInfo(in MidiDeviceInfo deviceInfo);
+
+ // For use by MidiService.
+ oneway void setDeviceInfo(in MidiDeviceInfo deviceInfo);
}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 6f4118e..4496a82 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -437,7 +437,7 @@
public static final String PARAM_BROWSABLE_ONLY = "browsable_only";
/**
- * A optional query, update or delete URI parameter that allows the caller to specify canonical
+ * An optional query, update or delete URI parameter that allows the caller to specify canonical
* genre to filter programs.
* @hide
*/
@@ -452,6 +452,13 @@
public static final String PARAM_PREVIEW = "preview";
/**
+ * An optional query, update or delete URI parameter that allows the caller to specify package
+ * name to filter channels.
+ * @hide
+ */
+ public static final String PARAM_PACKAGE = "package";
+
+ /**
* Builds an ID that uniquely identifies a TV input service.
*
* @param name The {@link ComponentName} of the TV input service to build ID for.
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index a292b8e..74085d3 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -949,9 +949,6 @@
com.android.internal.R.styleable.TvInputService);
mSetupActivity = sa.getString(
com.android.internal.R.styleable.TvInputService_setupActivity);
- if (inputType == TYPE_TUNER && TextUtils.isEmpty(mSetupActivity)) {
- throw new IllegalStateException("Setup activity not found for " + si.name);
- }
if (mCanRecord == null) {
mCanRecord = sa.getBoolean(
com.android.internal.R.styleable.TvInputService_canRecord, false);
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index e51025f..7b5f778 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -745,7 +745,7 @@
* Called when the application sets the surface.
*
* <p>The TV input service should render video onto the given surface. When called with
- * {@code null}, the input service should immediately release any references to the
+ * {@code null}, the input service should immediately free any references to the
* currently set surface and stop using it.
*
* @param surface The surface to be used for video rendering. Can be {@code null}.
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
index 3831cf7..dbfeefd 100644
--- a/obex/javax/obex/ServerSession.java
+++ b/obex/javax/obex/ServerSession.java
@@ -104,7 +104,6 @@
case ObexHelper.OBEX_OPCODE_DISCONNECT:
handleDisconnectRequest();
- done = true;
break;
case ObexHelper.OBEX_OPCODE_GET:
diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
index 7a3ed24..21c350be 100644
--- a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
@@ -20,14 +20,11 @@
public class EGLSurfaceImpl extends EGLSurface {
long mEGLSurface;
- private long mNativePixelRef;
public EGLSurfaceImpl() {
mEGLSurface = 0;
- mNativePixelRef = 0;
}
public EGLSurfaceImpl(long surface) {
mEGLSurface = surface;
- mNativePixelRef = 0;
}
@Override
diff --git a/packages/BackupRestoreConfirmation/res/values-gl/strings.xml b/packages/BackupRestoreConfirmation/res/values-gl/strings.xml
index c973a31..0a12aa7 100644
--- a/packages/BackupRestoreConfirmation/res/values-gl/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-gl/strings.xml
@@ -24,10 +24,10 @@
<string name="restore_confirm_text" msgid="7499866728030461776">"Solicitouse unha restauración de todos os datos desde un ordenador de escritorio conectado. Queres permitir esta operación?\n\nSe non o solicitaches ti, non permitas que se realice. Substituiranse todos os datos que conteña o dispositivo."</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Restaurar os meus datos"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Non restaurar"</string>
- <string name="current_password_text" msgid="8268189555578298067">"Insire o contrasinal de copia de seguranza actual a continuación:"</string>
+ <string name="current_password_text" msgid="8268189555578298067">"Insire o contrasinal da copia de seguranza actual a continuación:"</string>
<string name="device_encryption_restore_text" msgid="1570864916855208992">"Insire o contrasinal de encriptación do teu dispositivo a continuación."</string>
<string name="device_encryption_backup_text" msgid="5866590762672844664">"Insire o contrasinal de encriptación do dispositivo a continuación. Tamén se usará para encriptar o arquivo de copia de seguranza."</string>
- <string name="backup_enc_password_text" msgid="4981585714795233099">"Insire un contrasinal para encriptar os datos da copia de seguranza completa. Se queda en branco este campo, usarase o contrasinal de copia de seguranza actual."</string>
+ <string name="backup_enc_password_text" msgid="4981585714795233099">"Insire un contrasinal para encriptar os datos da copia de seguranza completa. Se queda en branco este campo, usarase o contrasinal da copia de seguranza actual."</string>
<string name="backup_enc_password_optional" msgid="1350137345907579306">"Se queres encriptar os datos da copia de seguranza completa, insire un contrasinal a continuación:"</string>
<string name="backup_enc_password_required" msgid="7889652203371654149">"Como o teu dispositivo está cifrado, debes cifrar a túa copia de seguranza. Introduce un contrasinal a continuación:"</string>
<string name="restore_enc_password_text" msgid="6140898525580710823">"Se os datos de restauración están encriptados, insire o contrasinal a continuación:"</string>
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 2ef1cf5..c309133 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -34,6 +34,7 @@
<intent-filter>
<action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
<action android:name="com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
+ <action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
<service android:name="com.android.carrierdefaultapp.ProvisionObserver"
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 7fd1601..0213306 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -112,8 +112,6 @@
private static void onShowCaptivePortalNotification(Intent intent, Context context) {
logd("onShowCaptivePortalNotification");
- final NotificationManager notificationMgr = context.getSystemService(
- NotificationManager.class);
Intent portalIntent = new Intent(context, CaptivePortalLoginActivity.class);
portalIntent.putExtras(intent);
portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
@@ -123,7 +121,8 @@
Notification notification = getNotification(context, R.string.portal_notification_id,
R.string.portal_notification_detail, pendingIntent);
try {
- notificationMgr.notify(PORTAL_NOTIFICATION_TAG, PORTAL_NOTIFICATION_ID, notification);
+ context.getSystemService(NotificationManager.class)
+ .notify(PORTAL_NOTIFICATION_TAG, PORTAL_NOTIFICATION_ID, notification);
} catch (NullPointerException npe) {
loge("setNotificationVisible: " + npe);
}
@@ -131,12 +130,11 @@
private static void onShowNoDataServiceNotification(Context context) {
logd("onShowNoDataServiceNotification");
- final NotificationManager notificationMgr = context.getSystemService(
- NotificationManager.class);
Notification notification = getNotification(context, R.string.no_data_notification_id,
R.string.no_data_notification_detail, null);
try {
- notificationMgr.notify(NO_DATA_NOTIFICATION_TAG, NO_DATA_NOTIFICATION_ID, notification);
+ context.getSystemService(NotificationManager.class)
+ .notify(NO_DATA_NOTIFICATION_TAG, NO_DATA_NOTIFICATION_ID, notification);
} catch (NullPointerException npe) {
loge("setNotificationVisible: " + npe);
}
@@ -144,26 +142,16 @@
private static void onCancelAllNotifications(Context context) {
logd("onCancelAllNotifications");
- final NotificationManager notificationMgr = context.getSystemService(
- NotificationManager.class);
- notificationMgr.cancelAll();
+ context.getSystemService(NotificationManager.class).cancelAll();
}
private static Notification getNotification(Context context, int titleId, int textId,
PendingIntent pendingIntent) {
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
- final NotificationManager notificationManager = context.getSystemService(
- NotificationManager.class);
final Resources resources = context.getResources();
final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
resources.getString(R.string.android_system_label));
- /* Creates the notification channel and registers it with NotificationManager. If a channel
- * with the same ID is already registered, NotificationManager will ignore this call.
- */
- notificationManager.createNotificationChannel(new NotificationChannel(
- NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
- resources.getString(R.string.mobile_data_status_notification_channel_name),
- NotificationManager.IMPORTANCE_DEFAULT));
+ createNotificationChannels(context);
Notification.Builder builder = new Notification.Builder(context)
.setContentTitle(resources.getString(titleId))
.setContentText(String.format(resources.getString(textId),
@@ -187,6 +175,19 @@
return builder.build();
}
+ /**
+ * Creates the notification channel and registers it with NotificationManager. Also used to
+ * update an existing channel's name.
+ */
+ static void createNotificationChannels(Context context) {
+ context.getSystemService(NotificationManager.class)
+ .createNotificationChannel(new NotificationChannel(
+ NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
+ context.getResources().getString(
+ R.string.mobile_data_status_notification_channel_name),
+ NotificationManager.IMPORTANCE_DEFAULT));
+ }
+
private static void logd(String s) {
Log.d(TAG, s);
}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
index 3fd89d9..3f55ff5 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
@@ -32,6 +32,10 @@
Log.d(TAG, "skip carrier actions during provisioning");
return;
}
+ if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+ CarrierActionUtils.createNotificationChannels(context);
+ return;
+ }
List<Integer> actionList = CustomConfigLoader.loadCarrierActionList(context, intent);
for (int actionIdx : actionList) {
Log.d(TAG, "apply carrier action idx: " + actionIdx);
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 7448079..6000500 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -87,7 +87,7 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"מבטל את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"שגיאת מדפסת ב-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"המדפסת חסמה את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <string name="cancel" msgid="4373674107267141885">"בטל"</string>
+ <string name="cancel" msgid="4373674107267141885">"ביטול"</string>
<string name="restart" msgid="2472034227037808749">"הפעל מחדש"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"אין חיבור למדפסת"</string>
<string name="reason_unknown" msgid="5507940196503246139">"לא ידוע"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 1eeed3c..0bfda36 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -198,7 +198,7 @@
<item msgid="1069584980746680398">"Razmera animacije 10x"</item>
</string-array>
<string-array name="overlay_display_devices_entries">
- <item msgid="1606809880904982133">"Nijedno"</item>
+ <item msgid="1606809880904982133">"Ništa"</item>
<item msgid="9033194758688161545">"480 piksela"</item>
<item msgid="1025306206556583600">"480 piksela (bezbedno)"</item>
<item msgid="1853913333042744661">"720 piksela"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 35473b3..fcbb89d 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -316,7 +316,7 @@
<string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Protanomalija (crveno-zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"Tritanomalija (plavo-žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boja"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na performanse."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na kvalitet rada."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="845431008899029842">"Još oko <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do potpunog punjenja"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 61388c0..f8eec7f 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -95,7 +95,7 @@
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Партатыўная кропка доступу"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-мадэм"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Мадэм"</string>
- <string name="tether_settings_title_all" msgid="8356136101061143841">"Мадэм і партатыўны хотспот"</string>
+ <string name="tether_settings_title_all" msgid="8356136101061143841">"Рэжым мадэма"</string>
<string name="managed_user_title" msgid="8109605045406748842">"Усе працоўныя праграмы"</string>
<string name="user_guest" msgid="8475274842845401871">"Госць"</string>
<string name="unknown" msgid="1592123443519355854">"Невядома"</string>
@@ -306,7 +306,7 @@
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Пераход..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Шыфраванне файлаў ужо дзейнічае"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Пераход на шыфраванне файлаў"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Перайдзіце з шыфравання раздзелаў даных на шыфраванне файлаў.\n !!Увага!! Гэта прывядзе да выдалення ўсіх даных.\n Гэта функцыя ў альфа-версіі, яна можа працаваць няправільна.\n Каб працягнуць, націсніце «Сцерці і перайсці...»."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Перайдзіце з шыфравання раздзелаў даных на шыфраванне файлаў.\n !!Увага!! Гэта прывядзе да выдалення ўсіх даных.\n Гэта функцыя ў альфа-версіі, яна можа працаваць няправільна.\n Каб працягнуць, націсніце \"Сцерці і перайсці...\"."</string>
<string name="button_convert_fbe" msgid="5152671181309826405">"Сцерці і перайсці..."</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Каляровы рэжым выявы"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Выкарыстоўваць sRGB"</string>
@@ -316,7 +316,7 @@
<string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Пратанамалія (чырвоны-зялёны)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"Трытанамалія (сіні-жоўты)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Карэкцыя колеру"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Гэтая функцыя з\'яўляецца эксперыментальнай і можа паўплываць на прадукцыйнасць."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Гэта функцыя з\'яўляецца эксперыментальнай і можа паўплываць на прадукцыйнасць."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="845431008899029842">"Засталося каля <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index aeea676..53c50b9 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -216,7 +216,7 @@
<string name="enable_terminal_title" msgid="95572094356054120">"Локален терминал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Актив. на прил. за терминал с достъп до локалния команден ред"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Проверка с HDCP"</string>
- <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Повед. за проверка с HDCP"</string>
+ <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Проверка с HDCP"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"Отстраняване на грешки"</string>
<string name="debug_app" msgid="8349591734751384446">"Избор на прил. за отстран. на грешки"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"Няма зададено приложение за отстраняване на грешки"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 886d635..6d755ea 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -103,13 +103,13 @@
<string name="launch_defaults_some" msgid="313159469856372621">"Neke zadane vrijednosti su postavljene"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nema postavljenih zadanih vrijednosti"</string>
<string name="tts_settings" msgid="8186971894801348327">"Postavke za pretvaranje teksta u govor"</string>
- <string name="tts_settings_title" msgid="1237820681016639683">"Izlaz za pretvaranje teksta u govor"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Pretvaranje teksta u govor"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina"</string>
<string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utječe na ton sintetiziranog govora"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
- <string name="tts_lang_use_system" msgid="2679252467416513208">"Koristi sistemski jezik"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Korištenje sistemskog jezika"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije izabran"</string>
<string name="tts_default_lang_summary" msgid="5219362163902707785">"Postavlja glas za dati jezik za izgovoreni tekst"</string>
<string name="tts_play_example_title" msgid="7094780383253097230">"Poslušajte primjer"</string>
@@ -117,7 +117,7 @@
<string name="tts_install_data_title" msgid="4264378440508149986">"Instaliraj glasovne podatke"</string>
<string name="tts_install_data_summary" msgid="5742135732511822589">"Instalirajte glasovne podatke potrebne za sintetiziranje govora"</string>
<string name="tts_engine_security_warning" msgid="8786238102020223650">"Ovaj program za sintetiziranje govora u mogućnosti je da prikuplja sav tekst koji se izgovara, uključujući lične podatke kao što su lozinke i brojevi kreditnih kartica. Program omogućava aplikacija <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Da li želite koristiti ovaj program za sintetiziranje govora?"</string>
- <string name="tts_engine_network_required" msgid="1190837151485314743">"Ovaj jezik zahtijeva mrežnu vezu radi za izlaz tekst-u-govor."</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Ovaj jezik zahtijeva aktivnu mrežnu vezu za pretvaranje teksta u govor."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"Ovo je primjer sinteze govora"</string>
<string name="tts_status_title" msgid="7268566550242584413">"Zadani status jezika"</string>
<string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> je u potpunosti podržan"</string>
@@ -126,7 +126,7 @@
<string name="tts_status_checking" msgid="5339150797940483592">"Provjerava se…"</string>
<string name="tts_engine_settings_title" msgid="3499112142425680334">"Postavke za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
<string name="tts_engine_settings_button" msgid="1030512042040722285">"Pokreni postavke programa"</string>
- <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Željeni program"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Željeni alat"</string>
<string name="tts_general_section_title" msgid="4402572014604490502">"Opće postavke"</string>
<string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Postavite visinu glasa"</string>
<string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Visinu glasa koji izgovara tekst postavite na podrazumjevanu."</string>
@@ -216,7 +216,7 @@
<string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Omogući terminalnu aplik. koja nudi pristup lok. kom. okruženju"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP provjeravanje"</string>
- <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Pos. ponaš. kod HDCP pr."</string>
+ <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Postavke HDCP provjere"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"Otklanjanje grešaka"</string>
<string name="debug_app" msgid="8349591734751384446">"Odaberi aplikaciju za otklanjanje grešaka"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"Nema postavljenih aplikac. za otklanjanje grešaka"</string>
@@ -278,12 +278,12 @@
<string name="force_resizable_activities_summary" msgid="6667493494706124459">"Neka sve aktivnosti budu takve da mogu mijenjati veličinu za prikaz sa više prozora, bez obzira na prikazane vrijednosti."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore nepravilnih oblika"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogućiti podršku za eksperimentalne prozore nepravilnih oblika."</string>
- <string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka za rezervnu kopiju radne površine"</string>
+ <string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka za sigurnosnu kopiju radne površine"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije sa radne površine"</string>
- <string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova lozinka za rezervnu kopiju postavljena"</string>
+ <string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova lozinka za sigurnosnu kopiju postavljena"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Nova lozinka i potvrda se ne podudaraju"</string>
- <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Nije uspjelo postavljanje lozinke za rezervnu kopiju"</string>
+ <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Nije uspjelo postavljanje lozinke za sigurnosnu kopiju"</string>
<string-array name="color_mode_names">
<item msgid="2425514299220523812">"Živopisan (zadano)"</item>
<item msgid="8446070607501413455">"Prirodan"</item>
@@ -302,11 +302,11 @@
<string name="select_webview_provider_title" msgid="4628592979751918907">"Postavljanje WebViewa"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesi WebView"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Ovaj izbor više ne vrijedi. Pokušajte ponovo."</string>
- <string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvori u šifrirani fajl"</string>
+ <string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvaranje u šifrirani fajl"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvaranje…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fajl je već šifriran"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Pretvaranje u šifrirane fajlove"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Pretvori particiju sa podacima u particiju šifriranu sistemom fajlova.\n !! Upozorenje!! Ovo će izbrisati sve vaše podatke.\n Ova funkcija je u alfa fazi razvoja i možda neće ispravno raditi.\n Pritisnite \'Obriši i pretvori…\" da nastavite."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Pretvorite particiju sa podacima u particiju šifriranu sistemom fajlova.\n !! Upozorenje!! Ovo će izbrisati sve vaše podatke.\n Ova funkcija je u alfa fazi razvoja i možda neće ispravno raditi.\n Pritisnite \"Obriši i pretvori…\" da nastavite."</string>
<string name="button_convert_fbe" msgid="5152671181309826405">"Obriši i pretvori…"</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Režim boja Slika"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Koristi sRGB"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 1c7ce0c..2a4db1d 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -302,7 +302,7 @@
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementació de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configura la implementació de WebView"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Aquesta opció ja no és vàlida. Torna-ho a provar."</string>
- <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteix en l\'encriptació de fitxers"</string>
+ <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteix en encriptació de fitxers"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converteix…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"El fitxer ja està encriptat"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"S\'està convertint en l\'encriptació basada en fitxers"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index c433c0f..8b57734 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -91,11 +91,11 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicacións eliminadas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicacións e usuarios eliminados"</string>
- <string name="tether_settings_title_usb" msgid="6688416425801386511">"Ancoraxe de USB"</string>
- <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Zona interactiva portátil"</string>
- <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Ancoraxe de Bluetooth"</string>
- <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Ancoraxe á rede"</string>
- <string name="tether_settings_title_all" msgid="8356136101061143841">"Ancoraxe á rede e zona wifi"</string>
+ <string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión compart. por USB"</string>
+ <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Zona wifi portátil"</string>
+ <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Conexión por Bluetooth"</string>
+ <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Conexión compartida"</string>
+ <string name="tether_settings_title_all" msgid="8356136101061143841">"Conexión comp./zona wifi"</string>
<string name="managed_user_title" msgid="8109605045406748842">"Aplicacións de traballo"</string>
<string name="user_guest" msgid="8475274842845401871">"Convidado"</string>
<string name="unknown" msgid="1592123443519355854">"Descoñecida"</string>
@@ -149,7 +149,7 @@
<string name="development_settings_summary" msgid="1815795401632854041">"Definir as opcións de desenvolvemento de aplicacións"</string>
<string name="development_settings_not_available" msgid="4308569041701535607">"As opcións de programador non están dispoñibles para este usuario"</string>
<string name="vpn_settings_not_available" msgid="956841430176985598">"A configuración da VPN non está dispoñible para este usuario"</string>
- <string name="tethering_settings_not_available" msgid="6765770438438291012">"A configuración da ancoraxe non está dispoñible para este usuario"</string>
+ <string name="tethering_settings_not_available" msgid="6765770438438291012">"A configuración da conexión compartida non está dispoñible para este usuario"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"A configuración do nome do punto de acceso non está dispoñible para este usuario"</string>
<string name="enable_adb" msgid="7982306934419797485">"Depuración de USB"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"Modo de depuración de erros cando o USB está conectado"</string>
@@ -281,9 +281,9 @@
<string name="local_backup_password_title" msgid="3860471654439418822">"Contrasinal para copias"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"As copias de seguridade de ordenador completas non están protexidas"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca para cambiar ou eliminar o contrasinal para as copias de seguranza completas do escritorio"</string>
- <string name="local_backup_password_toast_success" msgid="582016086228434290">"Novo contrasinal de copia de seguranza definido"</string>
+ <string name="local_backup_password_toast_success" msgid="582016086228434290">"Novo contrasinal da copia de seguranza definido"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"O contrasinal novo e a confirmación non coinciden"</string>
- <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Erro ao definir un contrasinal de copia de seguranza"</string>
+ <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Erro ao definir un contrasinal da copia de seguranza"</string>
<string-array name="color_mode_names">
<item msgid="2425514299220523812">"Brillante (predeterminado)"</item>
<item msgid="8446070607501413455">"Natural"</item>
@@ -297,17 +297,17 @@
<string name="inactive_apps_title" msgid="1317817863508274533">"Aplicacións inactivas"</string>
<string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Aplicación inactiva. Toca para alternar a configuración."</string>
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aplicación activa. Toca para alternar a configuración."</string>
- <string name="runningservices_settings_title" msgid="8097287939865165213">"Servizos en execución"</string>
+ <string name="runningservices_settings_title" msgid="8097287939865165213">"En execución"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Ver e controlar servizos actualmente en execución"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementación de WebView"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Esta opción xa non é válida. Téntao de novo."</string>
- <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter no encriptado baseado en ficheiros"</string>
+ <string name="convert_to_file_encryption" msgid="3060156730651061223">"Cambiar a cifraxe de ficheiros"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Xa se encriptou o ficheiro"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Convertendo no encriptado baseado en ficheiros"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Converte a partición de datos nun encriptado baseado en ficheiros.\n Advertencia: Esta acción borrará todos os datos.\n Esta función é alfa e quizais non funcione correctamente.\n Toca Borrar e converter... para continuar."</string>
- <string name="button_convert_fbe" msgid="5152671181309826405">"Borrar e converter..."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Converte a partición de datos nunha encriptación baseada en ficheiros.\n Advertencia: Esta acción borrará todos os datos.\n Esta función é alfa e quizais non funcione correctamente.\n Para continuar, toca Limpar e converter..."</string>
+ <string name="button_convert_fbe" msgid="5152671181309826405">"Limpar e converter..."</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Modo de cor da imaxe"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Utiliza sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Desactivado"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 0ec7637..14ba223 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -299,15 +299,15 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Ակտիվ է: Հպեք՝ փոխելու համար:"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Աշխատեցվող ծառայություններ"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Դիտել և վերահսկել ընթացիկ աշխատեցվող ծառայությունները"</string>
- <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-ի իրականացում"</string>
+ <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ծառայություն"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ընտրեք WebView-ի իրականացումը"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Այս ընտրանքն այլևս վավեր չէ: Փորձեք նորից:"</string>
- <string name="convert_to_file_encryption" msgid="3060156730651061223">"Վերածել ֆայլային գաղտնագրման"</string>
+ <string name="convert_to_file_encryption" msgid="3060156730651061223">"Անցում ֆայլերի գաղտնագրման"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Փոխարկել…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ֆայլային գաղտնագրումն արդեն կատարվել է"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Վերածում ֆայլային գաղտնագրման"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Ստեղծեք ֆայլային գաղտնագրում՝ փոխարկելով տվյալների բաժինը:\n !!Ուշադրություն!! Ձեր բոլոր տվյալները կջնջվեն:\n Այս գործառույթը դեռ գտնվում է փորձարկման փուլում և հնարավոր է ճիշտ չաշխատի:\n Շարունակելու համար սեղմեք «Սրբել և փոխարկել...» կոճակը:"</string>
- <string name="button_convert_fbe" msgid="5152671181309826405">"Սրբել և փոխարկել…"</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Անցնել առանձին ֆայլերի գաղտնագրման։\n Ուշադրությո՛ւն։ Ձեր բոլոր տվյալները կջնջվեն:\n Այս գործառույթը դեռ գտնվում է փորձարկման փուլում և, հնարավոր է, ճիշտ չաշխատի:\n Շարունակելու համար սեղմեք «Սրբել և անցնել...» կոճակը:"</string>
+ <string name="button_convert_fbe" msgid="5152671181309826405">"Սրբել և անցնել…"</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Նկարի գունային ռեժիմ"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Օգտագործել sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Կասեցված է"</string>
@@ -315,8 +315,8 @@
<string name="daltonizer_mode_deuteranomaly" msgid="5475532989673586329">"Դեյտերանոմալիա (կարմիր-կանաչ)"</string>
<string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Պրոտանոմալիա (կարմիր-կանաչ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"Տրիտանոմալիա (կապույտ-դեղին)"</string>
- <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Գունային կարգաբերում"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Սա փորձնական գործառույթ է և կարող է ազդել աշխատանքի վրա:"</string>
+ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Գունաշտկում"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Սա փորձնական գործառույթ է և կարող է ազդել սարքի աշխատանքի վրա:"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string>
<string name="power_remaining_duration_only" msgid="845431008899029842">"Մնացել է մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Մինչև լրիվ լիցքավորումը մնացել է <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 213aaf3..e64e007 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -267,7 +267,7 @@
<string name="animator_duration_scale_title" msgid="3406722410819934083">"קנה מידה למשך זמן אנימציה"</string>
<string name="overlay_display_devices_title" msgid="5364176287998398539">"צור הדמיית תצוגות משניות"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"אפליקציות"</string>
- <string name="immediately_destroy_activities" msgid="1579659389568133959">"אל תשמור פעילויות"</string>
+ <string name="immediately_destroy_activities" msgid="1579659389568133959">"ללא שמירת פעילויות"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"השמד כל פעילות ברגע שהמשתמש עוזב אותה"</string>
<string name="app_process_limit_title" msgid="4280600650253107163">"מגבלה של תהליכים ברקע"</string>
<string name="show_all_anrs" msgid="28462979638729082">"הצג את כל פריטי ה-ANR"</string>
@@ -302,12 +302,12 @@
<string name="select_webview_provider_title" msgid="4628592979751918907">"יישום WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"הגדרת יישום WebView"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"אפשרות זו כבר אינה תקפה. נסה שוב."</string>
- <string name="convert_to_file_encryption" msgid="3060156730651061223">"המר להצפנת קבצים"</string>
+ <string name="convert_to_file_encryption" msgid="3060156730651061223">"המרה לצורך הצפנת קבצים"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"המר..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"הצפנת קבצים כבר מוגדרת"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"המרה להצפנה מבוססת קבצים"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"המר את מחיצת הנתונים להצפנה מבוססת-קבצים.\n אזהרה!! פעולה זו תמחק את כל הנתונים.\n תכונה זו זמינה בגרסת אלפא וייתכן שלא תפעל כראוי.\n הקש על \'מחק והמר...\' כדי להמשיך."</string>
- <string name="button_convert_fbe" msgid="5152671181309826405">"מחק והמר..."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"המר את מחיצת הנתונים להצפנה מבוססת-קבצים.\n אזהרה!! פעולה זו תמחק את כל הנתונים.\n תכונה זו זמינה בגרסת אלפא וייתכן שלא תפעל כראוי.\n הקש על \'מחיקה והמרה…\' כדי להמשיך."</string>
+ <string name="button_convert_fbe" msgid="5152671181309826405">"מחיקה והמרה…"</string>
<string name="picture_color_mode" msgid="4560755008730283695">"מצב צבע התמונה"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"שימוש ב-sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="7482661936053801862">"מושבת"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 088d295..08e6449 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -316,7 +316,7 @@
<string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"პროტოანომალია (წითელი-მწვანე)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"ტრიტანომალია (ლურჯი-ყვითელი)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ფერის კორექცია"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს შესრულებაზე."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს ფუნქციონალობაზე."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string>
<string name="power_remaining_duration_only" msgid="845431008899029842">"დარჩა დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 1d7a9a4..9c8e28a 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -50,8 +50,8 @@
</string-array>
<string-array name="hdcp_checking_titles">
<item msgid="441827799230089869">"Эч качан текшерилбесин"</item>
- <item msgid="6042769699089883931">"DRM мазмунун гана текшерүү"</item>
- <item msgid="9174900380056846820">"Ар дайым текшерүү"</item>
+ <item msgid="6042769699089883931">"DRM мазмуну гана текшерилсин"</item>
+ <item msgid="9174900380056846820">"Ар дайым текшерилсин"</item>
</string-array>
<string-array name="hdcp_checking_summaries">
<item msgid="505558545611516707">"Эч качан HDCP текшерүү колдонулбасын"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 410f80b..97830f0 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -216,7 +216,7 @@
<string name="enable_terminal_title" msgid="95572094356054120">"Жергиликтүү терминал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Жергиликтүү буйрук кабыгын сунуштаган терминалга уруксат берүү"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP текшерүү"</string>
- <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCP текшерүү арактн коюу"</string>
+ <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCP текшерүү тартиби"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"Жөндөө"</string>
<string name="debug_app" msgid="8349591734751384446">"Жөндөөчү колдонмону тандоо"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"Эч бир жөндөөчү колдонмо орнотулган жок."</string>
@@ -299,15 +299,15 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Иштеп турат. Которуштуруу үчүн таптап коюңуз."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Иштеп жаткан кызматтар"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Учурда иштеп жаткан кызматтарды көрүү жана көзөмөлдөө"</string>
- <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView аткарылышы"</string>
+ <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView кызматы"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView аткарылышын коюу"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Тандалган нерсе жараксыз болуп калган. Кайра аракет кылыңыз."</string>
- <string name="convert_to_file_encryption" msgid="3060156730651061223">"Файл шифрлөөсүнө айландыруу"</string>
+ <string name="convert_to_file_encryption" msgid="3060156730651061223">"Файлдарды шифрлөөгө өтүү"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Айландыруу…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Файл мурунтан эле шифрленген"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Файл негизиндеги шифрлөөгө айландырылууда"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Дайындардын бөлүнүшүн файл негизиндеги шифрлөөгө айландыруу.\n !!Эскертүү!! Бул бардык дайындарыңызды тазалайт.\n Бул функция - альфа жана туура иштебеши мүмкүн.\n Улантуу үчүн \'Сүрүп салуу жана айландыруу…\' дегенди басыңыз."</string>
- <string name="button_convert_fbe" msgid="5152671181309826405">"Сүрүп салуу жана айландыруу…"</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Айрым файлдарды шифрлөөгө өтөсүз.\n !!Эскертүү!! Ушуну менен бардык дайындар өчөт.\n Бул альфа версия болгондуктан, функция талаптагыдай иштебеши мүмкүн.\n Улантуу үчүн \'Өчүрүп туруп, кийинкиге өтүү…\' дегенди басыңыз."</string>
+ <string name="button_convert_fbe" msgid="5152671181309826405">"Өчүрүп туруп, кийинкиге өтүү…"</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Сүрөт түсү режими"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"sRGB колдонуңуз"</string>
<string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Токтотулган"</string>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index f57989b..ef1c9de 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -198,7 +198,7 @@
<item msgid="1069584980746680398">"Размера анимације 10x"</item>
</string-array>
<string-array name="overlay_display_devices_entries">
- <item msgid="1606809880904982133">"Ниједно"</item>
+ <item msgid="1606809880904982133">"Ништа"</item>
<item msgid="9033194758688161545">"480 пиксела"</item>
<item msgid="1025306206556583600">"480 пиксела (безбедно)"</item>
<item msgid="1853913333042744661">"720 пиксела"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 9c08f97..3992dbe 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -316,7 +316,7 @@
<string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Протаномалија (црвено-зелено)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"Тританомалија (плаво-жуто)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекција боја"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ова функција је експериментална и може да утиче на перформансе."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ова функција је експериментална и може да утиче на квалитет рада."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="845431008899029842">"Још око <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> до потпуног пуњења"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index a217708..d3f137f 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -103,10 +103,10 @@
<string name="launch_defaults_some" msgid="313159469856372621">"Налаштовано деякі значення за умовчанням"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Немає значень за умовчанням"</string>
<string name="tts_settings" msgid="8186971894801348327">"Налашт. синтезу мовлення"</string>
- <string name="tts_settings_title" msgid="1237820681016639683">"Вивід синтезу мовлення з тексту"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Синтез мовлення"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Темп мовлення"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Швидкість відтворення тексту"</string>
- <string name="tts_default_pitch_title" msgid="6135942113172488671">"Вис. зв."</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Тон"</string>
<string name="tts_default_pitch_summary" msgid="1944885882882650009">"Впливає на тон синтезованого мовлення"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Мова"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Використовувати мову системи"</string>
@@ -302,7 +302,7 @@
<string name="select_webview_provider_title" msgid="4628592979751918907">"Застосування WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Налаштувати застосування WebView"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Ця опція більше не дійсна. Повторіть спробу."</string>
- <string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертувати в зашифрований файл"</string>
+ <string name="convert_to_file_encryption" msgid="3060156730651061223">"Перехід до шифрування файлів"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертація…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Уже конвертовано в зашифрований файл"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Конвертація в зашифрований файл"</string>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 76be771..cc7ef9b 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -223,7 +223,7 @@
<item msgid="1064373276095698656">"Chizmaning sinov buyruqlarini yashil bilan"</item>
</string-array>
<string-array name="track_frame_time_entries">
- <item msgid="2193584639058893150">"O‘chirib qo‘yish"</item>
+ <item msgid="2193584639058893150">"Faolsizlantirish"</item>
<item msgid="2751513398307949636">"Ekranda bo‘laklar tarzida"</item>
<item msgid="2355151170975410323">"“<xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>” buyrug‘ida"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 4e92c46..ad9dc3a 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -28,7 +28,7 @@
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Sifatsiz tarmoq sababli ulanib bo‘lmadi"</string>
<string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi ulanishini o‘rnatib bo‘lmadi"</string>
<string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Tasdiqdan o‘tishda muammo"</string>
- <string name="wifi_not_in_range" msgid="1136191511238508967">"Aloqada emas"</string>
+ <string name="wifi_not_in_range" msgid="1136191511238508967">"Xizmat doirasidan tashqarida"</string>
<string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Avtomatik ravishda ulanilmaydi"</string>
<string name="wifi_no_internet" msgid="3880396223819116454">"Internet aloqasi yo‘q"</string>
<string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> tomonidan saqlangan"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java
index 972ea34..d5725e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java
@@ -18,7 +18,6 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
-import android.content.res.Resources;
import android.provider.Settings;
import android.view.accessibility.AccessibilityManager;
@@ -55,8 +54,4 @@
public static boolean isRequested(Context ctx) {
return isRequestedByMagnification(ctx) || isRequestedByAccessibilityService(ctx);
}
-
- public static boolean isDeviceSupported(Resources res) {
- return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
- }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 66dfecd..443f1ee 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -1040,6 +1040,11 @@
final IPackageStatsObserver.Stub mStatsObserver = new IPackageStatsObserver.Stub() {
public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
+ if (!succeeded) {
+ // There is no meaningful information in stats if the call failed.
+ return;
+ }
+
boolean sizeChanged = false;
synchronized (mEntriesMap) {
if (DEBUG_LOCKING) Log.v(TAG, "onGetStatsCompleted acquired lock");
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
index ccf7a0b..39dfe0e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -33,7 +33,7 @@
public final long freeBytes;
public final long totalBytes;
- private PrivateStorageInfo(long freeBytes, long totalBytes) {
+ public PrivateStorageInfo(long freeBytes, long totalBytes) {
this.freeBytes = freeBytes;
this.totalBytes = totalBytes;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index e5cdc85..988060e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -16,6 +16,7 @@
package com.android.settingslib.dream;
+import android.annotation.IntDef;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -35,6 +36,8 @@
import android.util.Log;
import android.util.Xml;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -68,6 +71,15 @@
}
}
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({WHILE_CHARGING, WHILE_DOCKED, EITHER, NEVER})
+ public @interface WhenToDream{}
+
+ public static final int WHILE_CHARGING = 0;
+ public static final int WHILE_DOCKED = 1;
+ public static final int EITHER = 2;
+ public static final int NEVER = 3;
+
private final Context mContext;
private final IDreamManager mDreamManager;
private final DreamInfoComparator mComparator;
@@ -75,6 +87,15 @@
private final boolean mDreamsActivatedOnSleepByDefault;
private final boolean mDreamsActivatedOnDockByDefault;
+ private static DreamBackend sInstance;
+
+ public static DreamBackend getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new DreamBackend(context);
+ }
+ return sInstance;
+ }
+
public DreamBackend(Context context) {
mContext = context;
mDreamManager = IDreamManager.Stub.asInterface(
@@ -138,6 +159,42 @@
return null;
}
+ public @WhenToDream int getWhenToDreamSetting() {
+ if (!isEnabled()) {
+ return NEVER;
+ }
+ return isActivatedOnDock() && isActivatedOnSleep() ? EITHER
+ : isActivatedOnDock() ? WHILE_DOCKED
+ : isActivatedOnSleep() ? WHILE_CHARGING
+ : NEVER;
+ }
+
+ public void setWhenToDream(@WhenToDream int whenToDream) {
+ setEnabled(whenToDream != NEVER);
+
+ switch (whenToDream) {
+ case WHILE_CHARGING:
+ setActivatedOnDock(false);
+ setActivatedOnSleep(true);
+ break;
+
+ case WHILE_DOCKED:
+ setActivatedOnDock(true);
+ setActivatedOnSleep(false);
+ break;
+
+ case EITHER:
+ setActivatedOnDock(true);
+ setActivatedOnSleep(true);
+ break;
+
+ case NEVER:
+ default:
+ break;
+ }
+
+ }
+
public boolean isEnabled() {
return getBoolean(Settings.Secure.SCREENSAVER_ENABLED, mDreamsEnabledByDefault);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 24d8187..eb513e1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -998,9 +998,11 @@
if (mRssi != info.getRssi()) {
mRssi = info.getRssi();
updated = true;
+ } else if (mNetworkInfo != null && networkInfo != null
+ && mNetworkInfo.getDetailedState() != networkInfo.getDetailedState()) {
+ updated = true;
}
mInfo = info;
- // TODO(b/37289220): compare NetworkInfo states and set updated = true if necessary
mNetworkInfo = networkInfo;
} else if (mInfo != null) {
updated = true;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 646b6ba..be15e65 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -124,7 +124,8 @@
*/
private final Object mLock = new Object();
- //visible to both worker and main thread. Guarded by #mInternalAccessPoints
+ //visible to both worker and main thread.
+ @GuardedBy("mLock")
private final AccessPointListenerAdapter mAccessPointListenerAdapter
= new AccessPointListenerAdapter();
@@ -1005,12 +1006,13 @@
if (DBG) {
Log.d(TAG, "Starting to copy AP items on the MainHandler");
}
- if (notifyListeners) {
- notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
- }
-
- mAccessPointListenerAdapter.mPendingNotifications.clear();
synchronized (mLock) {
+ if (notifyListeners) {
+ notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
+ }
+
+ mAccessPointListenerAdapter.mPendingNotifications.clear();
+
for (AccessPoint internalAccessPoint : mInternalAccessPoints) {
AccessPoint accessPoint = oldAccessPoints.get(internalAccessPoint.mId);
if (accessPoint == null) {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 154fde2..56cb0a3 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -404,4 +404,55 @@
assertThat(ap.getPasspointFqdn()).isEqualTo(fqdn);
assertThat(ap.getConfigName()).isEqualTo(providerFriendlyName);
}
+
+ @Test
+ public void testUpdateNetworkInfo_returnsTrue() {
+ int networkId = 123;
+ int rssi = -55;
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = networkId;
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(networkId);
+ wifiInfo.setRssi(rssi);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(networkId)
+ .setRssi(rssi)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ NetworkInfo newInfo = new NetworkInfo(networkInfo);
+ newInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+ assertThat(ap.update(config, wifiInfo, newInfo)).isTrue();
+ }
+
+ @Test
+ public void testUpdateNetworkInfoWithSameInfo_returnsFalse() {
+ int networkId = 123;
+ int rssi = -55;
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = networkId;
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(networkId);
+ wifiInfo.setRssi(rssi);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(networkId)
+ .setRssi(rssi)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
+ assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
+ }
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
index a347203..2213ae6 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -20,6 +20,7 @@
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.os.Bundle;
/**
@@ -36,11 +37,13 @@
// set some sensible defaults
private int mRssi = AccessPoint.UNREACHABLE_RSSI;
- private int networkId = WifiConfiguration.INVALID_NETWORK_ID;
+ private int mNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
private String ssid = "TestSsid";
private NetworkInfo mNetworkInfo = null;
private String mFqdn = null;
private String mProviderFriendlyName = null;
+ private WifiConfiguration mWifiConfig;
+ private WifiInfo mWifiInfo;
Context mContext;
@@ -51,12 +54,13 @@
public AccessPoint build() {
Bundle bundle = new Bundle();
- WifiConfiguration wifiConig = new WifiConfiguration();
- wifiConig.networkId = networkId;
+ WifiConfiguration wifiConfig = new WifiConfiguration();
+ wifiConfig.networkId = mNetworkId;
bundle.putString(AccessPoint.KEY_SSID, ssid);
- bundle.putParcelable(AccessPoint.KEY_CONFIG, wifiConig);
+ bundle.putParcelable(AccessPoint.KEY_CONFIG, wifiConfig);
bundle.putParcelable(AccessPoint.KEY_NETWORKINFO, mNetworkInfo);
+ bundle.putParcelable(AccessPoint.KEY_WIFIINFO, mWifiInfo);
if (mFqdn != null) {
bundle.putString(AccessPoint.KEY_FQDN, mFqdn);
}
@@ -81,17 +85,12 @@
return this;
}
- public TestAccessPointBuilder setRssi(int rssi) {
- mRssi = rssi;
- return this;
- }
-
/**
- * Set the rssi based upon the desired signal level.
+ * Set the rssi based upon the desired signal level.
*
- * <p>Side effect: if this AccessPoint was previously unreachable,
- * setting the level will also make it reachable.
- */
+ * <p>Side effect: if this AccessPoint was previously unreachable,
+ * setting the level will also make it reachable.
+ */
public TestAccessPointBuilder setLevel(int level) {
// Reversal of WifiManager.calculateSignalLevels
if (level == 0) {
@@ -106,6 +105,16 @@
return this;
}
+ public TestAccessPointBuilder setNetworkInfo(NetworkInfo info) {
+ mNetworkInfo = info;
+ return this;
+ }
+
+ public TestAccessPointBuilder setRssi(int rssi) {
+ mRssi = rssi;
+ return this;
+ }
+
/**
* Set whether the AccessPoint is reachable.
* Side effect: if the signal level was not previously set,
@@ -125,9 +134,9 @@
public TestAccessPointBuilder setSaved(boolean saved){
if (saved) {
- networkId = 1;
+ mNetworkId = 1;
} else {
- networkId = WifiConfiguration.INVALID_NETWORK_ID;
+ mNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
}
return this;
}
@@ -146,4 +155,20 @@
mProviderFriendlyName = friendlyName;
return this;
}
+
+ public TestAccessPointBuilder setWifiInfo(WifiInfo info) {
+ mWifiInfo = info;
+ return this;
+ }
+
+ /**
+ * Set the networkId in the WifiConfig.
+ *
+ * <p>Setting this to a value other than {@link WifiConfiguration#INVALID_NETWORK_ID} makes this
+ * AccessPoint a saved network.
+ */
+ public TestAccessPointBuilder setNetworkId(int networkId) {
+ mNetworkId = networkId;
+ return this;
+ }
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index f519a90..d4ce40c 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -465,9 +465,9 @@
private void updateScoresAndWaitForAccessPointsChangedCallback() throws InterruptedException {
// Updating scores can happen together or one after the other, so the latch countdown is set
// to 2.
- mAccessPointsChangedLatch = new CountDownLatch(3);
+ mAccessPointsChangedLatch = new CountDownLatch(2);
updateScores();
- assertTrue("onAccessPointChanged was not called three times",
+ assertTrue("onAccessPointChanged was not called twice",
mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 885573e..f475361 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -696,6 +696,12 @@
Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
GlobalSettingsProto.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX);
dumpSetting(s, p,
+ Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX,
+ GlobalSettingsProto.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX);
+ dumpSetting(s, p,
+ Settings.Global.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX,
+ GlobalSettingsProto.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX);
+ dumpSetting(s, p,
Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX,
GlobalSettingsProto.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX);
dumpSetting(s, p,
@@ -979,9 +985,6 @@
Settings.Secure.AUTOFILL_SERVICE,
SecureSettingsProto.AUTOFILL_SERVICE);
dumpSetting(s, p,
- Settings.Secure.BLUETOOTH_HCI_LOG,
- SecureSettingsProto.BLUETOOTH_HCI_LOG);
- dumpSetting(s, p,
Settings.Secure.USER_SETUP_COMPLETE,
SecureSettingsProto.USER_SETUP_COMPLETE);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a6347c6..4b304b2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -35,6 +35,7 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
+import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
@@ -185,6 +186,26 @@
private static final Bundle NULL_SETTING_BUNDLE = Bundle.forPair(
Settings.NameValueTable.VALUE, null);
+ // Overlay specified settings whitelisted for Instant Apps
+ private static final Set<String> OVERLAY_ALLOWED_GLOBAL_INSTANT_APP_SETTINGS = new ArraySet<>();
+ private static final Set<String> OVERLAY_ALLOWED_SYSTEM_INSTANT_APP_SETTINGS = new ArraySet<>();
+ private static final Set<String> OVERLAY_ALLOWED_SECURE_INSTANT_APP_SETTINGS = new ArraySet<>();
+
+ static {
+ for (String name : Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_allowedGlobalInstantAppSettings)) {
+ OVERLAY_ALLOWED_GLOBAL_INSTANT_APP_SETTINGS.add(name);
+ }
+ for (String name : Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_allowedSystemInstantAppSettings)) {
+ OVERLAY_ALLOWED_SYSTEM_INSTANT_APP_SETTINGS.add(name);
+ }
+ for (String name : Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_allowedSecureInstantAppSettings)) {
+ OVERLAY_ALLOWED_SECURE_INSTANT_APP_SETTINGS.add(name);
+ }
+ }
+
// Changes to these global settings are synchronously persisted
private static final Set<String> CRITICAL_GLOBAL_SETTINGS = new ArraySet<>();
static {
@@ -898,14 +919,13 @@
Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")");
}
+ // Ensure the caller can access the setting.
+ enforceSettingReadable(name, SETTINGS_TYPE_GLOBAL, UserHandle.getCallingUserId());
+
// Get the value.
synchronized (mLock) {
- Setting setting = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL,
+ return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL,
UserHandle.USER_SYSTEM, name);
- // Ensure the caller can access the setting before we return it.
- enforceSettingReadable(setting, name, SETTINGS_TYPE_GLOBAL,
- UserHandle.getCallingUserId());
- return setting;
}
}
@@ -1063,6 +1083,9 @@
// Resolve the userId on whose behalf the call is made.
final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
+ // Ensure the caller can access the setting.
+ enforceSettingReadable(name, SETTINGS_TYPE_SECURE, UserHandle.getCallingUserId());
+
// Determine the owning user as some profile settings are cloned from the parent.
final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
@@ -1076,7 +1099,6 @@
// As of Android O, the SSAID is read from an app-specific entry in table
// SETTINGS_FILE_SSAID, unless accessed by a system process.
- // All apps are allowed to access their SSAID, so we skip the permission check.
if (isNewSsaidSetting(name)) {
PackageInfo callingPkg = getCallingPackageInfo(owningUserId);
synchronized (mLock) {
@@ -1086,12 +1108,8 @@
// Not the SSAID; do a straight lookup
synchronized (mLock) {
- Setting setting = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE,
+ return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE,
owningUserId, name);
- // Ensure the caller can access the setting before we return it.
- enforceSettingReadable(setting, name, SETTINGS_TYPE_SECURE,
- UserHandle.getCallingUserId());
- return setting;
}
}
@@ -1292,18 +1310,15 @@
// Resolve the userId on whose behalf the call is made.
final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
+ // Ensure the caller can access the setting.
+ enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, UserHandle.getCallingUserId());
// Determine the owning user as some profile settings are cloned from the parent.
final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
// Get the value.
synchronized (mLock) {
- Setting setting = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SYSTEM,
- owningUserId, name);
- // Ensure the caller can access the setting before we return it.
- enforceSettingReadable(setting, name, SETTINGS_TYPE_SYSTEM,
- UserHandle.getCallingUserId());
- return setting;
+ return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SYSTEM, owningUserId, name);
}
}
@@ -1635,6 +1650,19 @@
}
}
+ private Set<String> getOverlayInstantAppAccessibleSettings(int settingsType) {
+ switch (settingsType) {
+ case SETTINGS_TYPE_GLOBAL:
+ return OVERLAY_ALLOWED_GLOBAL_INSTANT_APP_SETTINGS;
+ case SETTINGS_TYPE_SYSTEM:
+ return OVERLAY_ALLOWED_SYSTEM_INSTANT_APP_SETTINGS;
+ case SETTINGS_TYPE_SECURE:
+ return OVERLAY_ALLOWED_SECURE_INSTANT_APP_SETTINGS;
+ default:
+ throw new IllegalArgumentException("Invalid settings type: " + settingsType);
+ }
+ }
+
private List<String> getSettingsNamesLocked(int settingsType, int userId) {
boolean instantApp;
if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
@@ -1650,23 +1678,16 @@
}
}
- private void enforceSettingReadable(Setting setting, String settingName, int settingsType,
- int userId) {
+ private void enforceSettingReadable(String settingName, int settingsType, int userId) {
if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
return;
}
ApplicationInfo ai = getCallingApplicationInfoOrThrow();
- // Installed apps are allowed to read all settings.
if (!ai.isInstantApp()) {
return;
}
- // Instant Apps are allowed to read settings defined by applications.
- // TODO: Replace this with an API that allows the setting application to say if a setting
- // shoud/shouldn't be accessible.
- if (!setting.isDefaultFromSystem()) {
- return;
- }
- if (!getInstantAppAccessibleSettings(settingsType).contains(settingName)) {
+ if (!getInstantAppAccessibleSettings(settingsType).contains(settingName)
+ && !getOverlayInstantAppAccessibleSettings(settingsType).contains(settingName)) {
throw new SecurityException("Setting " + settingName + " is not accessible from"
+ " ephemeral package " + getCallingPackage());
}
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 5ee0c64..c7bae66 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -37,7 +37,8 @@
android-support-v7-mediarouter \
android-support-v7-palette \
android-support-v14-preference \
- android-support-v17-leanback
+ android-support-v17-leanback \
+ colorextraction
LOCAL_STATIC_JAVA_LIBRARIES := \
SystemUI-tags \
diff --git a/packages/SystemUI/colorextraction/Android.mk b/packages/SystemUI/colorextraction/Android.mk
new file mode 100644
index 0000000..e818c99
--- /dev/null
+++ b/packages/SystemUI/colorextraction/Android.mk
@@ -0,0 +1,26 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_USE_AAPT2 := true
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_ANDROID_LIBRARIES := android-support-annotations \
+ android-support-v7-palette \
+ android-support-v4
+LOCAL_MODULE := colorextraction
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/packages/SystemUI/colorextraction/AndroidManifest.xml b/packages/SystemUI/colorextraction/AndroidManifest.xml
new file mode 100644
index 0000000..6e082cf
--- /dev/null
+++ b/packages/SystemUI/colorextraction/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.colorextraction">
+</manifest>
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java
new file mode 100644
index 0000000..a91aa61
--- /dev/null
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.google.android.colorextraction;
+
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Color;
+import android.util.Log;
+
+import com.google.android.colorextraction.types.ExtractionType;
+import com.google.android.colorextraction.types.Tonal;
+
+/**
+ * Class to process wallpaper colors and generate a tonal palette based on them.
+ */
+public class ColorExtractor implements WallpaperManager.OnColorsChangedListener {
+ private static final String TAG = "ColorExtractor";
+ private static final int FALLBACK_COLOR = Color.BLACK;
+
+ private int mMainFallbackColor = FALLBACK_COLOR;
+ private int mSecondaryFallbackColor = FALLBACK_COLOR;
+ private final GradientColors mSystemColors;
+ private final GradientColors mLockColors;
+ private final Context mContext;
+ private final ExtractionType mExtractionType;
+ private OnColorsChangedListener mListener;
+
+ public ColorExtractor(Context context) {
+ mContext = context;
+ mSystemColors = new GradientColors();
+ mLockColors = new GradientColors();
+ mExtractionType = new Tonal();
+
+ WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
+
+ if (wallpaperManager == null) {
+ Log.w(TAG, "Can't listen to color changes!");
+ } else {
+ wallpaperManager.addOnColorsChangedListener(this);
+ extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM),
+ mSystemColors);
+ extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK),
+ mLockColors);
+ }
+ }
+
+ public GradientColors getColors(int which) {
+ if (which == WallpaperManager.FLAG_LOCK) {
+ return mLockColors;
+ } else if (which == WallpaperManager.FLAG_SYSTEM) {
+ return mSystemColors;
+ } else {
+ throw new IllegalArgumentException("which should be either FLAG_SYSTEM or FLAG_LOCK");
+ }
+ }
+
+ public void setListener(OnColorsChangedListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void onColorsChanged(WallpaperColors colors, int which) {
+ if ((which & WallpaperManager.FLAG_LOCK) != 0) {
+ extractInto(colors, mLockColors);
+ if (mListener != null) {
+ mListener.onColorsChanged(mLockColors, WallpaperManager.FLAG_LOCK);
+ }
+ }
+ if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+ extractInto(colors, mSystemColors);
+ if (mListener != null) {
+ mListener.onColorsChanged(mSystemColors, WallpaperManager.FLAG_SYSTEM);
+ }
+ }
+ }
+
+ private void extractInto(WallpaperColors inWallpaperColors, GradientColors outGradientColors) {
+ applyFallback(outGradientColors);
+ if (inWallpaperColors == null) {
+ return;
+ }
+ mExtractionType.extractInto(inWallpaperColors, outGradientColors);
+ }
+
+ private void applyFallback(GradientColors outGradientColors) {
+ outGradientColors.setMainColor(mMainFallbackColor);
+ outGradientColors.setSecondaryColor(mSecondaryFallbackColor);
+ }
+
+ public void destroy() {
+ WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
+ if (wallpaperManager != null) {
+ wallpaperManager.removeOnColorsChangedListener(this);
+ }
+ }
+
+ public static class GradientColors {
+ private int mMainColor = FALLBACK_COLOR;
+ private int mSecondaryColor = FALLBACK_COLOR;
+ private boolean mSupportsDarkText;
+
+ public void setMainColor(int mainColor) {
+ mMainColor = mainColor;
+ }
+
+ public void setSecondaryColor(int secondaryColor) {
+ mSecondaryColor = secondaryColor;
+ }
+
+ public void setSupportsDarkText(boolean supportsDarkText) {
+ mSupportsDarkText = supportsDarkText;
+ }
+
+ public void set(GradientColors other) {
+ mMainColor = other.mMainColor;
+ mSecondaryColor = other.mSecondaryColor;
+ mSupportsDarkText = other.mSupportsDarkText;
+ }
+
+ public int getMainColor() {
+ return mMainColor;
+ }
+
+ public int getSecondaryColor() {
+ return mSecondaryColor;
+ }
+
+ public boolean supportsDarkText() {
+ return mSupportsDarkText;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || o.getClass() != getClass()) {
+ return false;
+ }
+ GradientColors other = (GradientColors) o;
+ return other.mMainColor == mMainColor &&
+ other.mSecondaryColor == mSecondaryColor &&
+ other.mSupportsDarkText == mSupportsDarkText;
+ }
+
+ @Override
+ public int hashCode() {
+ int code = mMainColor;
+ code = 31 * code + mSecondaryColor;
+ code = 31 * code + (mSupportsDarkText ? 0 : 1);
+ return code;
+ }
+ }
+
+ public interface OnColorsChangedListener {
+ void onColorsChanged(GradientColors colors, int which);
+ }
+}
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/drawable/GradientDrawable.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/drawable/GradientDrawable.java
new file mode 100644
index 0000000..e046fb3
--- /dev/null
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/drawable/GradientDrawable.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.google.android.colorextraction.drawable;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.RadialGradient;
+import android.graphics.Rect;
+import android.graphics.Shader;
+import android.graphics.Xfermode;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.graphics.ColorUtils;
+import android.view.animation.DecelerateInterpolator;
+
+import com.google.android.colorextraction.ColorExtractor;
+
+/**
+ * Draws a gradient based on a Palette
+ */
+public class GradientDrawable extends Drawable {
+ private static final String TAG = "GradientDrawable";
+
+ private static final float CENTRALIZED_CIRCLE_1 = -2;
+ private static final int GRADIENT_RADIUS = 480; // in dp
+ private static final long COLOR_ANIMATION_DURATION = 2000;
+
+ private int mAlpha = 255;
+
+ private float mDensity;
+ private final Paint mPaint;
+ private final Rect mWindowBounds;
+ private final Splat mSplat;
+
+ private int mMainColor;
+ private int mSecondaryColor;
+ private ValueAnimator mColorAnimation;
+
+ public GradientDrawable(@NonNull Context context) {
+ mDensity = context.getResources().getDisplayMetrics().density;
+ mSplat = new Splat(0.50f, 1.00f, GRADIENT_RADIUS, CENTRALIZED_CIRCLE_1);
+ mWindowBounds = new Rect();
+
+ mPaint = new Paint();
+ mPaint.setStyle(Paint.Style.FILL);
+ }
+
+ public void setColors(@NonNull ColorExtractor.GradientColors colors) {
+ setColors(colors.getMainColor(), colors.getSecondaryColor(), true);
+ }
+
+ public void setColors(@NonNull ColorExtractor.GradientColors colors, boolean animated) {
+ setColors(colors.getMainColor(), colors.getSecondaryColor(), animated);
+ }
+
+ public void setColors(int mainColor, int secondaryColor, boolean animated) {
+ if (mainColor == mMainColor && secondaryColor == mSecondaryColor) {
+ return;
+ }
+
+ if (mColorAnimation != null && mColorAnimation.isRunning()) {
+ mColorAnimation.cancel();
+ }
+
+ if (animated) {
+ final int mainFrom = mMainColor;
+ final int secFrom = mSecondaryColor;
+
+ ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
+ anim.setDuration(COLOR_ANIMATION_DURATION);
+ anim.addUpdateListener(animation -> {
+ float ratio = (float) animation.getAnimatedValue();
+ mMainColor = ColorUtils.blendARGB(mainFrom, mainColor, ratio);
+ mSecondaryColor = ColorUtils.blendARGB(secFrom, secondaryColor, ratio);
+ buildPaints();
+ invalidateSelf();
+ });
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation, boolean isReverse) {
+ if (mColorAnimation == animation) {
+ mColorAnimation = null;
+ }
+ }
+ });
+ anim.setInterpolator(new DecelerateInterpolator());
+ anim.start();
+ mColorAnimation = anim;
+ } else {
+ mMainColor = mainColor;
+ mSecondaryColor = secondaryColor;
+ buildPaints();
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ if (alpha != mAlpha) {
+ mAlpha = alpha;
+ mPaint.setAlpha(mAlpha);
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public int getAlpha() {
+ return mAlpha;
+ }
+
+ @Override
+ public void setXfermode(@Nullable Xfermode mode) {
+ mPaint.setXfermode(mode);
+ invalidateSelf();
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ mPaint.setColorFilter(colorFilter);
+ }
+
+ @Override
+ public ColorFilter getColorFilter() {
+ return mPaint.getColorFilter();
+ }
+
+ @Override
+ public int getOpacity() {
+ return mAlpha == 255 ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
+ }
+
+ public void setScreenSize(int width, int height) {
+ mWindowBounds.set(0, 0, width, height);
+ setBounds(0, 0, width, height);
+ buildPaints();
+ }
+
+ private void buildPaints() {
+ final Rect bounds = mWindowBounds;
+
+ float w = bounds.width();
+ float h = bounds.height();
+
+ float x = mSplat.x * w;
+ float y = mSplat.y * h;
+
+ float radius = mSplat.radius * mDensity;
+
+ // When we have only a single alpha gradient, we increase quality
+ // (avoiding banding) by merging the background solid color into
+ // the gradient directly
+ RadialGradient radialGradient = new RadialGradient(x, y, radius,
+ mMainColor, mSecondaryColor, Shader.TileMode.CLAMP);
+ mPaint.setShader(radialGradient);
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ final Rect bounds = mWindowBounds;
+
+ // Splat each gradient
+ float w = bounds.width();
+ float h = bounds.height();
+
+ float x = mSplat.x * w;
+ float y = mSplat.y * h;
+
+ float radius = Math.max(w, h);
+ canvas.drawRect(x - radius, y - radius, x + radius, y + radius, mPaint);
+ }
+
+ static final class Splat {
+ final float x;
+ final float y;
+ final float radius;
+ final float colorIndex;
+
+ Splat(float x, float y, float radius, float colorIndex) {
+ this.x = x;
+ this.y = y;
+ this.radius = radius;
+ this.colorIndex = colorIndex;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java
new file mode 100644
index 0000000..937107c
--- /dev/null
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.google.android.colorextraction.types;
+
+import android.app.WallpaperColors;
+
+import com.google.android.colorextraction.ColorExtractor;
+
+/**
+ * Interface to allow various color extraction implementations.
+ */
+public interface ExtractionType {
+
+ /**
+ * Executes color extraction by reading WallpaperColors and setting
+ * main and secondary colors on GradientColors.
+ *
+ * @param inWallpaperColors where to read from
+ * @param outGradientColors object that should receive the colors
+ */
+ void extractInto(WallpaperColors inWallpaperColors,
+ ColorExtractor.GradientColors outGradientColors);
+}
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java
new file mode 100644
index 0000000..a7b2b99
--- /dev/null
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.google.android.colorextraction.types;
+
+import android.app.WallpaperColors;
+import android.graphics.Color;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.graphics.ColorUtils;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.Pair;
+
+import com.google.android.colorextraction.ColorExtractor;
+
+/**
+ * Implementation of tonal color extraction
+ */
+public class Tonal implements ExtractionType {
+ private static final String TAG = "Tonal";
+
+ // Used for tonal palette fitting
+ private static final float FIT_WEIGHT_H = 1.0f;
+ private static final float FIT_WEIGHT_S = 1.0f;
+ private static final float FIT_WEIGHT_L = 10.0f;
+
+ private static final float MIN_COLOR_OCCURRENCE = 0.1f;
+ private static final float MIN_LUMINOSITY = 0.5f;
+
+ public void extractInto(WallpaperColors wallpaperColors,
+ ColorExtractor.GradientColors gradientColors) {
+
+ if (wallpaperColors.getColors().size() == 0) {
+ return;
+ }
+ // Tonal is not really a sort, it takes a color from the extracted
+ // palette and finds a best fit amongst a collection of pre-defined
+ // palettes. The best fit is tweaked to be closer to the source color
+ // and replaces the original palette
+
+ // First find the most representative color in the image
+ populationSort(wallpaperColors);
+ // Calculate total
+ int total = 0;
+ for (Pair<Color, Integer> weightedColor : wallpaperColors.getColors()) {
+ total += weightedColor.second;
+ }
+
+ // Get bright colors that occur often enough in this image
+ Pair<Color, Integer> bestColor = null;
+ float[] hsl = new float[3];
+ for (Pair<Color, Integer> weightedColor : wallpaperColors.getColors()) {
+ float colorOccurrence = weightedColor.second / (float) total;
+ if (colorOccurrence < MIN_COLOR_OCCURRENCE) {
+ break;
+ }
+
+ int colorValue = weightedColor.first.toArgb();
+ ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue),
+ Color.blue(colorValue), hsl);
+ if (hsl[2] > MIN_LUMINOSITY) {
+ bestColor = weightedColor;
+ }
+ }
+
+ // Fallback to first color
+ if (bestColor == null) {
+ bestColor = wallpaperColors.getColors().get(0);
+ }
+
+ int colorValue = bestColor.first.toArgb();
+ ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue), Color.blue(colorValue),
+ hsl);
+ hsl[0] /= 360.0f; // normalize
+
+ // TODO, we're finding a tonal palette for a hue, not all components
+ TonalPalette palette = findTonalPalette(hsl[0]);
+
+ // Fall back to population sort if we couldn't find a tonal palette
+ if (palette == null) {
+ Log.w(TAG, "Could not find a tonal palette!");
+ return;
+ }
+
+ int fitIndex = bestFit(palette, hsl[0], hsl[1], hsl[2]);
+ if (fitIndex == -1) {
+ Log.w(TAG, "Could not find best fit!");
+ return;
+ }
+ float[] h = fit(palette.h, hsl[0], fitIndex,
+ Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
+ float[] s = fit(palette.s, hsl[1], fitIndex, 0.0f, 1.0f);
+ float[] l = fit(palette.l, hsl[2], fitIndex, 0.0f, 1.0f);
+
+
+ hsl[0] = fract(h[0]) * 360.0f;
+ hsl[1] = s[0];
+ hsl[2] = l[0];
+ gradientColors.setMainColor(ColorUtils.HSLToColor(hsl));
+
+ hsl[0] = fract(h[1]) * 360.0f;
+ hsl[1] = s[1];
+ hsl[2] = l[1];
+ gradientColors.setSecondaryColor(ColorUtils.HSLToColor(hsl));
+ }
+
+ private static void populationSort(@NonNull WallpaperColors wallpaperColors) {
+ wallpaperColors.getColors().sort((a, b) -> b.second - a.second);
+ }
+
+ /**
+ * Offsets all colors by a delta, clamping values that go beyond what's
+ * supported on the color space.
+ * @param data what you want to fit
+ * @param v how big should be the offset
+ * @param index which index to calculate the delta against
+ * @param min minimum accepted value (clamp)
+ * @param max maximum accepted value (clamp)
+ * @return
+ */
+ private static float[] fit(float[] data, float v, int index, float min, float max) {
+ float[] fitData = new float[data.length];
+ float delta = v - data[index];
+
+ for (int i = 0; i < data.length; i++) {
+ fitData[i] = MathUtils.constrain(data[i] + delta, min, max);
+ }
+
+ return fitData;
+ }
+
+ /*function adjustSatLumForFit(val, points, fitIndex) {
+ var fitValue = lerpBetweenPoints(points, fitIndex);
+ var diff = val - fitValue;
+
+ var newPoints = [];
+ for (var ii=0; ii<points.length; ii++) {
+ var point = [points[ii][0], points[ii][1]];
+ point[1] += diff;
+ if (point[1] > 1) point[1] = 1;
+ if (point[1] < 0) point[1] = 0;
+ newPoints[ii] = point;
+ }
+ return newPoints;
+ }*/
+
+ /**
+ * Finds the closest color in a palette, given another HSL color
+ *
+ * @param palette where to search
+ * @param h hue
+ * @param s saturation
+ * @param l lightness
+ * @return closest index or -1 if palette is empty.
+ */
+ private static int bestFit(@NonNull TonalPalette palette, float h, float s, float l) {
+ int minErrorIndex = -1;
+ float minError = Float.POSITIVE_INFINITY;
+
+ for (int i = 0; i < palette.h.length; i++) {
+ float error =
+ FIT_WEIGHT_H * Math.abs(h - palette.h[i])
+ + FIT_WEIGHT_S * Math.abs(s - palette.s[i])
+ + FIT_WEIGHT_L * Math.abs(l - palette.l[i]);
+ if (error < minError) {
+ minError = error;
+ minErrorIndex = i;
+ }
+ }
+
+ return minErrorIndex;
+ }
+
+ @Nullable
+ private static TonalPalette findTonalPalette(float h) {
+ TonalPalette best = null;
+ float error = Float.POSITIVE_INFINITY;
+
+ for (TonalPalette candidate : TONAL_PALETTES) {
+ if (h >= candidate.minHue && h <= candidate.maxHue) {
+ best = candidate;
+ break;
+ }
+
+ if (candidate.maxHue > 1.0f && h >= 0.0f && h <= fract(candidate.maxHue)) {
+ best = candidate;
+ break;
+ }
+
+ if (candidate.minHue < 0.0f && h >= fract(candidate.minHue) && h <= 1.0f) {
+ best = candidate;
+ break;
+ }
+
+ if (h <= candidate.minHue && candidate.minHue - h < error) {
+ best = candidate;
+ error = candidate.minHue - h;
+ } else if (h >= candidate.maxHue && h - candidate.maxHue < error) {
+ best = candidate;
+ error = h - candidate.maxHue;
+ } else if (candidate.maxHue > 1.0f && h >= fract(candidate.maxHue)
+ && h - fract(candidate.maxHue) < error) {
+ best = candidate;
+ error = h - fract(candidate.maxHue);
+ } else if (candidate.minHue < 0.0f && h <= fract(candidate.minHue)
+ && fract(candidate.minHue) - h < error) {
+ best = candidate;
+ error = fract(candidate.minHue) - h;
+ }
+ }
+
+ return best;
+ }
+
+ private static float fract(float v) {
+ return v - (float) Math.floor(v);
+ }
+
+ static class TonalPalette {
+ final float[] h;
+ final float[] s;
+ final float[] l;
+ final float minHue;
+ final float maxHue;
+
+ TonalPalette(float[] h, float[] s, float[] l) {
+ this.h = h;
+ this.s = s;
+ this.l = l;
+
+ float minHue = Float.POSITIVE_INFINITY;
+ float maxHue = Float.NEGATIVE_INFINITY;
+
+ for (float v : h) {
+ minHue = Math.min(v, minHue);
+ maxHue = Math.max(v, maxHue);
+ }
+
+ this.minHue = minHue;
+ this.maxHue = maxHue;
+ }
+ }
+
+ // Data definition of Material Design tonal palettes
+ // When the sort type is set to TONAL, these palettes are used to find
+ // a best fist. Each palette is defined as 10 HSL colors
+ private static final TonalPalette[] TONAL_PALETTES = {
+ // Orange
+ new TonalPalette(
+ new float[] { 0.028f, 0.042f, 0.053f, 0.061f, 0.078f, 0.1f, 0.111f, 0.111f, 0.111f, 0.111f },
+ new float[] { 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f },
+ new float[] { 0.5f, 0.53f, 0.54f, 0.55f, 0.535f, 0.52f, 0.5f, 0.63f, 0.75f, 0.85f }
+ ),
+ // Yellow
+ new TonalPalette(
+ new float[] { 0.111f, 0.111f, 0.125f, 0.133f, 0.139f, 0.147f, 0.156f, 0.156f, 0.156f, 0.156f },
+ new float[] { 1f, 0.942f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f },
+ new float[] { 0.43f, 0.484f, 0.535f, 0.555f, 0.57f, 0.575f, 0.595f, 0.715f, 0.78f, 0.885f }
+ ),
+ // Green
+ new TonalPalette(
+ new float[] { 0.325f, 0.336f, 0.353f, 0.353f, 0.356f, 0.356f, 0.356f, 0.356f, 0.356f, 0.356f },
+ new float[] { 1f, 1f, 0.852f, 0.754f, 0.639f, 0.667f, 0.379f, 0.542f, 1f, 1f },
+ new float[] { 0.06f, 0.1f, 0.151f, 0.194f, 0.25f, 0.312f, 0.486f, 0.651f, 0.825f, 0.885f }
+ ),
+ // Blue
+ new TonalPalette(
+ new float[] { 0.631f, 0.603f, 0.592f, 0.586f, 0.572f, 0.544f, 0.519f, 0.519f, 0.519f, 0.519f },
+ new float[] { 0.852f, 1f, 0.887f, 0.852f, 0.871f, 0.907f, 0.949f, 0.934f, 0.903f, 0.815f },
+ new float[] { 0.34f, 0.38f, 0.482f, 0.497f, 0.536f, 0.571f, 0.608f, 0.696f, 0.794f, 0.892f }
+ ),
+ // Purple
+ new TonalPalette(
+ new float[] { 0.839f, 0.831f, 0.825f, 0.819f, 0.803f, 0.803f, 0.772f, 0.772f, 0.772f, 0.772f },
+ new float[] { 1f, 1f, 1f, 1f, 1f, 1f, 0.769f, 0.701f, 0.612f, 0.403f },
+ new float[] { 0.125f, 0.15f, 0.2f, 0.245f, 0.31f, 0.36f, 0.567f, 0.666f, 0.743f, 0.833f }
+ ),
+ // Red
+ new TonalPalette(
+ new float[] { 0.964f, 0.975f, 0.975f, 0.975f, 0.972f, 0.992f, 1.003f, 1.011f, 1.011f, 1.011f },
+ new float[] { 0.869f, 0.802f, 0.739f, 0.903f, 1f, 1f, 1f, 1f, 1f, 1f },
+ new float[] { 0.241f, 0.316f, 0.46f, 0.586f, 0.655f, 0.7f, 0.75f, 0.8f, 0.84f, 0.88f }
+ )
+ };
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/doze/DozeProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/doze/DozeProvider.java
deleted file mode 100644
index 0688481..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/doze/DozeProvider.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.doze;
-
-import android.app.PendingIntent;
-import android.content.Context;
-
-import com.android.systemui.plugins.Plugin;
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
-/**
- * Provides a {@link DozeUi}.
- */
-@ProvidesInterface(action = DozeProvider.ACTION, version = DozeProvider.VERSION)
-public interface DozeProvider extends Plugin {
-
- String ACTION = "com.android.systemui.action.PLUGIN_DOZE";
- int VERSION = 1;
-
- /**
- * Caution: Even if this is called, the DozeUi provided may still be in use until it transitions
- * to DozeState.FINISH
- */
- @Override
- default void onDestroy() {
- }
-
- /**
- * @return the plugin's implementation of DozeUi.
- */
- DozeUi provideDozeUi(Context context, DozeMachine machine, WakeLock wakeLock);
-
- /**
- * If true, the plugin allows the default pulse triggers to fire, otherwise they are disabled.
- */
- default boolean allowDefaultPulseTriggers() {
- return false;
- }
-
- /**
- * Ui for use in DozeMachine.
- */
- interface DozeUi {
- /** Called whenever the DozeMachine state transitions */
- void transitionTo(DozeState oldState, DozeState newState);
- }
-
- /** WakeLock wrapper for testability */
- interface WakeLock {
- /** @see android.os.PowerManager.WakeLock#acquire() */
- void acquire();
- /** @see android.os.PowerManager.WakeLock#release() */
- void release();
- /** @see android.os.PowerManager.WakeLock#wrap(Runnable) */
- Runnable wrap(Runnable r);
- }
-
- /** Plugin version of the DozeMachine's state */
- enum DozeState {
- /** Default state. Transition to INITIALIZED to get Doze going. */
- UNINITIALIZED,
- /** Doze components are set up. Followed by transition to DOZE or DOZE_AOD. */
- INITIALIZED,
- /** Regular doze. Device is asleep and listening for pulse triggers. */
- DOZE,
- /** Always-on doze. Device is asleep, showing UI and listening for pulse triggers. */
- DOZE_AOD,
- /** Pulse has been requested. Device is awake and preparing UI */
- DOZE_REQUEST_PULSE,
- /** Pulse is showing. Device is awake and showing UI. */
- DOZE_PULSING,
- /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
- DOZE_PULSE_DONE,
- /** Doze is done. DozeService is finished. */
- FINISH,
- /** WakeUp. */
- WAKE_UP,
- }
-
- /** Plugin interface for the doze machine. */
- interface DozeMachine {
- /** Request that the DozeMachine transitions to {@code state} */
- void requestState(DozeState state);
-
- /** Request that the PendingIntent is sent. */
- void requestSendIntent(PendingIntent intent);
- }
-}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index 7d78c08..9ef05c5 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -16,6 +16,7 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
import android.service.quicksettings.Tile;
import com.android.systemui.plugins.annotations.DependsOn;
@@ -66,6 +67,10 @@
State getState();
+ default LogMaker populate(LogMaker logMaker) {
+ return logMaker;
+ }
+
@ProvidesInterface(version = Callback.VERSION)
public interface Callback {
public static final int VERSION = 1;
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
index 4a7d0fd..28f78e5 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
@@ -96,4 +96,7 @@
public default boolean useDefaultMenuItems() {
return false;
}
+
+ public default void onConfigurationChanged() {
+ }
}
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 6ca33a6..e55d996 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -36,7 +36,7 @@
<string name="keyguard_low_battery" msgid="9218432555787624490">"Tilslut din oplader."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Tryk på menuen for at låse op."</string>
<string name="keyguard_network_locked_message" msgid="6743537524631420759">"Netværket er låst"</string>
- <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Der er ikke noget SIM-kort"</string>
+ <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Intet SIM-kort"</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"Der er ikke noget SIM-kort i denne tablet."</string>
<string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"Der er ikke noget SIM-kort i telefonen."</string>
<string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Indsæt et SIM-kort."</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 19fb792..0011c26 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -39,8 +39,8 @@
<string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"SIM karta yo‘q"</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"Planshetingizda SIM karta yo‘q."</string>
<string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"Telefoningizda SIM karta yo‘q."</string>
- <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Telefonga SIM kartani joylashtiring."</string>
- <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM karta qo‘yilmagan yoki o‘qib bo‘lmayapti. SIM kartani joylashtiring."</string>
+ <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Telefonga SIM karta soling."</string>
+ <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM karta solinmagan yoki u yaroqsiz. SIM karta soling."</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"Foydalanib bo‘lmaydigan SIM karta."</string>
<string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"SIM kartangiz butunlay bloklab qo‘yilgan.\n Yangi SIM karta olish uchun aloqa operatoringiz bilan bog‘laning."</string>
<string name="keyguard_sim_locked_message" msgid="953766009432168127">"SIM karta qulflangan."</string>
diff --git a/packages/SystemUI/res/color/qs_background_dark.xml b/packages/SystemUI/res/color/qs_background_dark.xml
new file mode 100644
index 0000000..1aa732f
--- /dev/null
+++ b/packages/SystemUI/res/color/qs_background_dark.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.93"
+ android:color="?android:attr/colorPrimaryDark"/>
+</selector>
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 0bdbc5f..03bba53 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -15,6 +15,6 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorPrimaryDark"/>
+ <solid android:color="@color/qs_background_dark"/>
</shape>
</inset>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 30442ea..718142f 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Jy is gekoppel aan <xliff:g id="APPLICATION">%1$s</xliff:g>, wat jou persoonlike netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> bestuur jou werkprofiel. Die profiel is gekoppel aan <xliff:g id="APPLICATION">%2$s</xliff:g>, wat jou netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor.\n\nKontak jou administrateur vir meer inligting."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> bestuur jou werkprofiel. Die profiel is gekoppel aan <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, wat jou netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor.\n\nJy is ook gekoppel aan <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, wat jou persoonlike netwerkaktiwiteit kan monitor."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Ontsluit vir <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Toestel sal gesluit bly totdat jy dit handmatig ontsluit"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Kry kennisgewings vinniger"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Sien hulle voordat jy ontsluit"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Tot <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Hou"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Vervang"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 30ddf19..91e6b2e 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"እስከ <xliff:g id="ID_1">%s</xliff:g> ድረስ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"አቆይ"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ተካ"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 32a181b..c04d0db 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -474,8 +474,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"أنت متصل بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك الشخصية على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"يخضع الملف الشخصي للعمل لإدارة <xliff:g id="ORGANIZATION">%1$s</xliff:g>. تم ربط الملف الشخصي بـ <xliff:g id="APPLICATION">%2$s</xliff:g>، الذي يمكنه مراقبة أنشطة شبكتك، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب.\n\nيمكنك الاتصال بالمشرف للحصول على مزيد من المعلومات."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"يخضع الملف الشخصي للعمل لإدارة <xliff:g id="ORGANIZATION">%1$s</xliff:g>. تم ربط هذا الملف الشخصي بـ <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>، الذي يمكنه مراقبة أنشطة شبكتك، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب.\n\nتم ربطك بـ <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>، الذي يمكنه مراقبة أنشطة شبكتك الشخصية."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"تم إلغاء القفل لـ <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"سيظل الجهاز مقفلاً إلى أن يتم إلغاء قفله يدويًا"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"الحصول على الإشعارات بشكل أسرع"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"الاطلاع عليها قبل إلغاء القفل"</string>
@@ -779,4 +778,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"حتى <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"الإبقاء على الإعدادات"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"استبدال"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index e463543..4b9971b 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə qoşulmusunuz və o, e-məktublar, tətbiq və veb saytlar daxil olmaqla şəxsi şəbəkə fəaliyyətinizə nəzarət edə bilər."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"İş profili <xliff:g id="ORGANIZATION">%1$s</xliff:g> tərəfindən idarə olunur. Profil e-poçt, tətbiq və veb saytlar da daxil olmaqla şəbəkə fəaliyyətinə nəzarət edən <xliff:g id="APPLICATION">%2$s</xliff:g> tətbiqinə qoşuludur.\n\nƏtraflı məlumat üçün admin ilə əlaqə saxlayın."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"İş profili <xliff:g id="ORGANIZATION">%1$s</xliff:g> tərəfindən idarə edilir. Profil e-poçt, tətbiq və veb saytlar da daxil olmaqla şəbəkə fəaliyyətinə nəzarət edən <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> tətbiqinə qoşuludur.\n\nEyni zamanda şəxsi şəbəkə fəaliyyətinə nəzarət edən <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> tətbiqinə qoşulusunuz."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> üçün kiliddən çıxarıldı"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Device will stay locked until you manually unlock"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Bildirişləri daha sürətlə əldə edin"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Kiliddən çıxarmadan öncə onları görün"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> vaxtına qədər"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Saxlayın"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Əvəz edin"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 7210a82..0065ffe 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -767,4 +767,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zameni"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index e4431cb..313285be 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -472,8 +472,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Вы падключаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая можа сачыць за вашай асабістай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ён падключаны да праграмы <xliff:g id="APPLICATION">%2$s</xliff:g>, якая можа сачыць за вашай працоўнай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ён падключаны да праграмы <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, якая можа сачыць за вашай працоўнай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nВы таксама падключаны да праграмы <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, якая можа сачыць за вашай асабістай сеткавай актыўнасцю."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Разблакіравана для карыстальніка <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Прылада будзе заставацца заблакіраванай, пакуль вы не разблакіруеце яе ўручную"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Атрымлівайце апавяшчэнні хутчэй"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Праглядайце іх перад разблакіроўкай"</string>
@@ -773,4 +772,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Да <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Пакінуць"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замяніць"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 3df3def..5934bd2 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Установена е връзка с приложението <xliff:g id="APPLICATION">%1$s</xliff:g>, което може да наблюдава личната ви активност в мрежата, включително имейли, приложения и уебсайтове."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Служебният ви потребителски профил се управлява от <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Той е свързан с приложението <xliff:g id="APPLICATION">%2$s</xliff:g>, което може да наблюдава служебната ви активност в мрежата, включително имейли, приложения и уебсайтове.\n\nЗа още информация се свържете с администратора си."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Служебният ви потребителски профил се управлява от <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Той е свързан с приложението <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, което може да наблюдава служебната ви активност в мрежата, включително имейли, приложения и уебсайтове.\n\nУстановена е връзка и с приложението <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, което може да наблюдава личната ви активност в мрежата."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Отключено за <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Устройството ще остане заключено, докато не го отключите ръчно"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Получавайте известия по-бързо"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Вижте известията, преди да отключите"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Запазване"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замяна"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 2ab8585..181c0871 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> পর্যন্ত"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"রাখুন"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"বদলে দিন"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index f313e62..a06da7c 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -303,7 +303,7 @@
<string name="quick_settings_cast_title" msgid="7709016546426454729">"Prebacivanje"</string>
<string name="quick_settings_casting" msgid="6601710681033353316">"Prebacivanje"</string>
<string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Neimenovani uređaj"</string>
- <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Spreman za prebacivanje"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Spreman za emitiranje"</string>
<string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Nema dostupnih uređaja"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Osvjetljenje"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
@@ -354,7 +354,7 @@
<string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Povucite gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Povucite lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_priority_introduction" msgid="3070506961866919502">"Zvukovi i vibracije vas neće uznemiravati, osim alarma, podsjetnika, događaja i pozivalaca koje odredite."</string>
+ <string name="zen_priority_introduction" msgid="3070506961866919502">"Neće vas ometati zvukovi i vibracije, osim alarma, podsjetnika, događaja i pozivalaca koje odredite."</string>
<string name="zen_priority_customize_button" msgid="7948043278226955063">"Prilagodi"</string>
<string name="zen_silence_introduction_voice" msgid="2284540992298200729">"Ovim se blokiraju SVI zvukovi i vibracije, uključujući alarme, muziku, videozapise i igre. I dalje ćete moći obavljati pozive."</string>
<string name="zen_silence_introduction" msgid="3137882381093271568">"Ovim se blokiraju SVI zvukovi i vibracije, uključujući alarme, muziku, video zapise i igre."</string>
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste na aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vaše privatne aktivnosti na mreži, uključujući e-poštu, aplikacije i web stranice."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nZa više informacija, obratite se svom administratoru."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nPovezani ste i sa aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Otključano za korisnika <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Uređaj će ostati zaključan dok ga ručno ne otključate"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Brže primaj obavještenja"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Vidi ih prije otključavanja"</string>
@@ -669,7 +668,7 @@
<string name="right_keycode" msgid="708447961000848163">"Kôd tipke desno"</string>
<string name="left_icon" msgid="3096287125959387541">"Ikona lijevo"</string>
<string name="right_icon" msgid="3952104823293824311">"Ikona desno"</string>
- <string name="drag_to_add_tiles" msgid="7058945779098711293">"Povucite da dodate polja"</string>
+ <string name="drag_to_add_tiles" msgid="7058945779098711293">"Prevucite da dodate pločice"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Prevucite ovdje za uklanjanje"</string>
<string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
<string name="tuner_time" msgid="6572217313285536011">"Vrijeme"</string>
@@ -769,4 +768,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zamijeni"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index efe0aa3..bd5e6cc 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Estàs connectat a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pot supervisar la teva activitat personal a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional. El perfil està connectat a <xliff:g id="APPLICATION">%2$s</xliff:g>, que pot supervisar la teva activitat a la xarxa de treball, com ara els correus electrònics, les aplicacions i els llocs web.\n\nPer obtenir més informació, contacta amb l\'administrador."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional. El perfil està connectat a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pot supervisar la teva activitat a la xarxa de treball, com ara els correus electrònics, les aplicacions i els llocs web.\n\nTambé estàs connectat a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pot supervisar la teva activitat personal a la xarxa."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Desbloquejat per a <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositiu continuarà bloquejat fins que no el desbloquegis manualment."</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Rep notificacions més ràpidament"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Mostra-les abans de desbloquejar"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Fins a les <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Conserva"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substitueix"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c8c6ee5..e3af288 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -472,8 +472,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Jste připojeni k aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g>, která může sledovat vaši osobní aktivitu v síti, včetně e-mailů, aplikací a webů."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Váš pracovní profil spravuje organizace <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Je připojen k aplikaci <xliff:g id="APPLICATION">%2$s</xliff:g>, která může sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a webů.\n\nDalší informace vám poskytne administrátor."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Váš pracovní profil spravuje organizace <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Je připojen k aplikaci <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, která může sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a webů.\n\nTaké jste připojeni k aplikaci <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, která může sledovat vaši osobní aktivitu v síti."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Odemknuto pro uživatele <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Zařízení zůstane uzamčeno, dokud je ručně neodemknete"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Čtěte si oznámení rychleji"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Můžete si je přečíst před odemčením obrazovky."</string>
@@ -773,4 +772,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Zachovat"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Nahradit"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index fa3eac1..fefbff7 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din private netværksaktivitet, bl.a. e-mails, apps og websites."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Din arbejdsprofil administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profilen har forbindelse til <xliff:g id="APPLICATION">%2$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites.\n\nKontakt din administrator for at få flere oplysninger."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Din arbejdsprofil administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profilen har forbindelse til <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites.\n\nDu har også forbindelse til <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, som kan overvåge din personlige netværksaktivitet."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Låst op for <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheden vil forblive låst, indtil du manuelt låser den op"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Modtag underretninger hurtigere"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Se dem, før du låser op"</string>
@@ -718,8 +717,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Luk"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Træk nedad for at afvise"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Billede i billede-menu"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> vises i billede i billede"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Menu for integreret billede"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> vises som integreret billede"</string>
<string name="pip_notification_message" msgid="4171698133469539591">"Hvis du ikke ønsker, at <xliff:g id="NAME">%s</xliff:g> skal benytte denne funktion, kan du åbne indstillingerne og deaktivere den."</string>
<string name="pip_play" msgid="1417176722760265888">"Afspil"</string>
<string name="pip_pause" msgid="8881063404466476571">"Sæt på pause"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Indtil <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Behold"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Erstat"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 6281f35..714341d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Du bist mit der App \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" verbunden. Diese kann deine persönlichen Netzwerkaktivitäten erfassen, einschließlich E-Mails, Apps und Websites."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Dein Arbeitsprofil wird von <xliff:g id="ORGANIZATION">%1$s</xliff:g> verwaltet. Das Profil ist mit <xliff:g id="APPLICATION">%2$s</xliff:g> verknüpft. Diese App kann deine Netzwerkaktivitäten überwachen, einschließlich E-Mails, Apps und Websites.\n\nWeitere Informationen erhältst du von deinem Administrator."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Dein Arbeitsprofil wird von <xliff:g id="ORGANIZATION">%1$s</xliff:g> verwaltet. Das Profil ist mit <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> verknüpft. Diese App kann deine Netzwerkaktivitäten überwachen, einschließlich E-Mails, Apps und Websites.\n\nDu bist auch mit <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> verbunden, die deine persönlichen Netzwerkaktivitäten überwachen kann."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Entsperrt für <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Das Gerät bleibt gesperrt, bis du es manuell entsperrst."</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Benachrichtigungen schneller erhalten"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Vor dem Entsperren anzeigen"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Bis <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Beibehalten"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ersetzen"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 79ba29a..8838b66 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του προσωπικού σας δικτύου, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Ο οργανισμός <xliff:g id="ORGANIZATION">%1$s</xliff:g> διαχειρίζεται το προφίλ εργασίας σας. Το προφίλ είναι συνδεδεμένο στην εφαρμογή <xliff:g id="APPLICATION">%2$s</xliff:g>, η οποία μπορεί να παρακολουθήσει τη δραστηριότητα του δικτύου εργασίας σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή σας."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Ο οργανισμός <xliff:g id="ORGANIZATION">%1$s</xliff:g> διαχειρίζεται το προφίλ εργασίας σας. Το προφίλ συνδέεται με την εφαρμογή <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου της εργασίας σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων.\n\nΕπίσης, είστε συνδεδεμένοι στην εφαρμογή <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, που έχει τη δυνατότητα παρακολούθησης της δραστηριότητας του προσωπικού σας δικτύου."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Ξεκλειδώθηκε για τον χρήστη <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Η συσκευή θα παραμείνει κλειδωμένη μέχρι να την ξεκλειδώσετε μη αυτόματα"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Λάβετε ειδοποιήσεις γρηγορότερα"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Εμφάνιση πριν το ξεκλείδωμα"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Έως τις <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Διατήρηση"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Αντικατάσταση"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 8006409..9542d75 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -762,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 8006409..9542d75 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -762,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 8006409..9542d75 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -762,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 08e4b1d..d61d4de 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Te conectaste a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede supervisar la actividad de tu red personal, incluidos los correos electrónicos, las apps y los sitios web."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> administra tu perfil de trabajo. El perfil está conectado a <xliff:g id="APPLICATION">%2$s</xliff:g>, que puede controlar tu actividad de red de trabajo, incluidos los correos electrónicos, apps y sitios web.\n\nPara obtener más información, comunícate con tu administrador."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> administra tu perfil de red. El perfil está conectado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que puede controlar tu actividad de red de trabajo, incluidos los correos electrónicos, las apps y los sitios web.\n\nTambién estás conectado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que puede controlar tu actividad de red personal."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Se desbloqueó para <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositivo permanecerá bloqueado hasta que lo desbloquees manualmente."</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Recibe notificaciones más rápido"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ver antes de desbloquear"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Hasta la(s) <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Mantener"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Reemplazar"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f6142b7..ea88456 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Estas conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede controlar tu actividad de red personal, como correos electrónicos, aplicaciones y sitios web."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona tu perfil de trabajo. El perfil está conectado a <xliff:g id="APPLICATION">%2$s</xliff:g>, que puede supervisar tu actividad de red profesional, como los correos electrónicos, las aplicaciones y los sitios web.\n\nPara obtener más información, ponte en contacto con el administrador."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona tu perfil de trabajo. El perfil está conectado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que puede supervisar tu actividad de red profesional, como los correos electrónicos, las aplicaciones y los sitios web.\n\nTambién te has conectado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que puede supervisar tu actividad de red personal."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Desbloqueado para <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositivo permanecerá bloqueado hasta que se desbloquee manualmente"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Recibe notificaciones más rápido"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ver antes de desbloquear"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Hasta <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Conservar"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Reemplazar"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index cb8cf82..b4f1022 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Olete ühendatud rakendusega <xliff:g id="APPLICATION">%1$s</xliff:g>, mis võib jälgida teie isiklikke võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Teie tööprofiili haldab <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profiil on ühendatud rakendusega <xliff:g id="APPLICATION">%2$s</xliff:g>, mis saab jälgida teie töökoha võrgutegevusi, sh meile, rakendusi ja veebisaite.\n\nLisateabe saamiseks võtke ühendust administraatoriga."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Teie tööprofiili haldab <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profiil on ühendatud rakendusega <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, mis saab jälgida teie töökoha võrgutegevusi, sh meile, rakendusi ja veebisaite.\n\nOlete ühendatud ka rakendusega <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, mis saab jälgida teie isiklikke võrgutegevusi."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Avatud kasutaja <xliff:g id="USER_NAME">%1$s</xliff:g> jaoks"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Seade jääb lukku, kuni selle käsitsi avate"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Saate märguandeid kiiremini"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Näete neid enne avamist"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Kuni ajani <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Säilita"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Asenda"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index ee0620b..214da9a 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikaziora konektatuta zaude. Aplikazio horrek sarean egiten dituzun jarduera pertsonalak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> erakundeak kudeatzen dizu laneko profila. <xliff:g id="APPLICATION">%2$s</xliff:g> aplikaziora dago konektatuta profila, eta aplikazio horrek sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> erakundeak kudeatzen dizu laneko profila. <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> aplikaziora dago konektatuta profila, eta aplikazio horrek sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne. \n\n<xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> aplikaziora ere zaude konektatuta, eta hark sare pertsonalean egiten dituzun jarduerak kontrola ditzake."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> erabiltzailearentzat desblokeatu da"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Gailua blokeatuta egongo da eskuz desblokeatu arte"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Eskuratu jakinarazpenak azkarrago"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ikusi desblokeatu baino lehen"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> arte"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Utzi bere horretan"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ordeztu"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 77f11ee..30782e4 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"تا <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"حفظ شود"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"جایگزین کردن"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 7b790da..bbdfcdc 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Olet muodostanut yhteyden sovellukseen <xliff:g id="APPLICATION">%1$s</xliff:g>, joka voi valvoa henkilökohtaista toimintaasi verkossa. Sovellus voi esimerkiksi seurata avaamiasi sähköposteja, sovelluksia ja verkkosivustoja."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> hallinnoi työprofiiliasi. Se on yhteydessä sovellukseen <xliff:g id="APPLICATION">%2$s</xliff:g>, joka voi valvoa toimintaasi verkossa, esimerkiksi sähköposteja, sovelluksia ja verkkosivustoja.\n\nPyydä lisätietoja järjestelmänvalvojalta."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> hallinnoi työprofiiliasi. Se on yhteydessä sovellukseen <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, joka voi valvoa toimintaasi verkossa, esimerkiksi sähköposteja, sovelluksia ja verkkosivustoja.\n\nLisäksi olet yhteydessä sovellukseen <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, joka voi valvoa henkilökohtaista toimintaasi verkossa."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Lukitus avattu käyttäjälle <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Laite pysyy lukittuna, kunnes se avataan käsin"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Näe ilmoitukset nopeammin"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Näytä ennen lukituksen avaamista"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> asti"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Säilytä"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Korvaa"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index f4dca7b..a6f42c5 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Vous êtes connecté à <xliff:g id="APPLICATION">%1$s</xliff:g>. Cette application peut contrôler votre activité personnelle sur le réseau, y compris les courriels, les applications et les sites Web."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Votre profil professionnel est géré par <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ce profil est connecté à <xliff:g id="APPLICATION">%2$s</xliff:g>, qui peut contrôler votre activité professionnelle sur le réseau, y compris l\'activité relative aux courriels, aux applications et aux sites Web.\n\nPour en savoir plus, communiquez avec votre administrateur."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Votre profil professionnel est géré par <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ce profil est connecté à <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, qui peut contrôler votre activité professionnelle sur le réseau, y compris l\'activité relative aux courriels, aux applications et aux sites Web.\n\nVous êtes également connecté à <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, qui peut contrôler votre activité personnelle sur le réseau."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Déverrouillé pour for <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"L\'appareil restera verrouillé jusqu\'à ce que vous le déverrouilliez manuellement"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Voir les notifications plus rapidement"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Afficher les notifications avant de déverrouiller l\'appareil"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Jusqu\'à <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Garder"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Remplacer"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 73f3598..d00e98f 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Vous êtes connecté à <xliff:g id="APPLICATION">%1$s</xliff:g>. Cette application peut contrôler votre activité personnelle sur le réseau, y compris les e-mails, les applications et les sites Web."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Votre profil professionnel est géré par <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ce profil est connecté à <xliff:g id="APPLICATION">%2$s</xliff:g>, qui peut contrôler votre activité professionnelle sur le réseau, y compris l\'activité relative aux e-mails, aux applications et aux sites Web.\n\nPour plus d\'informations, contactez votre administrateur."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Votre profil professionnel est géré par <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ce profil est connecté à <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, qui peut contrôler votre activité professionnelle sur le réseau, y compris l\'activité relative aux e-mails, aux applications et aux sites Web.\n\nVous êtes également connecté à <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, qui peut contrôler votre activité personnelle sur le réseau."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Déverrouillé pour <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"L\'appareil restera verrouillé jusqu\'à ce que vous le déverrouilliez manuellement."</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Recevoir les notifications plus vite"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Afficher les notifications avant de déverrouiller l\'appareil"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Jusqu\'à <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Conserver"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Remplacer"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 453e0e3..416b359 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -34,7 +34,7 @@
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacións"</string>
<string name="battery_low_title" msgid="6456385927409742437">"Queda pouca batería"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string>
- <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. A función aforro de batería está activada."</string>
+ <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. A función de aforro da batería está activada."</string>
<string name="invalid_charger" msgid="4549105996740522523">"Non compatible coa carga por USB.\nUtiliza só o cargador proporcionado."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"Non se admite a carga mediante USB."</string>
<string name="invalid_charger_text" msgid="5474997287953892710">"Utiliza soamente o cargador fornecido."</string>
@@ -354,7 +354,7 @@
<string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Pasa o dedo cara arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Pasa o dedo cara a esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_priority_introduction" msgid="3070506961866919502">"Non te molestará ningún son nin vibración, agás os procedentes de alarmas, recordatorios, eventos de emisores de chamada especificados."</string>
+ <string name="zen_priority_introduction" msgid="3070506961866919502">"Non te molestará ningún son nin vibración, agás os procedentes de alarmas, recordatorios, eventos e os emisores de chamada especificados."</string>
<string name="zen_priority_customize_button" msgid="7948043278226955063">"Personalizar"</string>
<string name="zen_silence_introduction_voice" msgid="2284540992298200729">"Esta acción bloquea TODOS os sons e vibracións, incluídos os das alarmas, música, vídeos e xogos. Aínda podes facer chamadas de teléfono."</string>
<string name="zen_silence_introduction" msgid="3137882381093271568">"Esta acción bloquea TODOS os sons e vibracións, incluídos os das alarmas, música, vídeos e xogos."</string>
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Estás conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode supervisar a túa actividade persoal na rede, incluídos os correos electrónicos, as aplicacións e os sitios web."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> xestiona o teu perfil de traballo, que está conectado a <xliff:g id="APPLICATION">%2$s</xliff:g>. Esta aplicación pode controlar a túa actividade na rede, mesmo os correos electrónicos, as aplicacións e os sitios web.\n\nPara obter máis información, contacta co administrador."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> xestiona o teu perfil de traballo, que está conectado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>. Esta aplicación pode controlar a túa actividade na rede, mesmo os correos electrónicos, as aplicacións e os sitios web.\n\nTamén estás conectado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode controlar a túa actividade persoal na rede."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Desbloqueado para: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado ata que o desbloquees manualmente"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Recibir notificacións máis rápido"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Consúltaas antes de desbloquear"</string>
@@ -579,7 +578,7 @@
<string name="snooze_undo" msgid="6074877317002985129">"DESFACER"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Adiouse <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso de batería"</string>
- <string name="battery_detail_charging_summary" msgid="1279095653533044008">"A función aforro de batería non está dispoñible durante a carga"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"A función de aforro da batería non está dispoñible durante a carga"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Aforro de batería"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce o rendemento e os datos en segundo plano"</string>
<string name="keyboard_key_button_template" msgid="6230056639734377300">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Ata: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substituír"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 49abb7a0..857eaec 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> સુધી"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"રાખો"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"બદલો"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 8f45c8e..ad3bf6b 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी व्यक्तिगत नेटवर्क गतिविधि को मॉनिटर कर सकता है."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"आपकी कार्य प्रोफ़ाइल का प्रबंधन <xliff:g id="ORGANIZATION">%1$s</xliff:g> करता है. प्रोफ़ाइल <xliff:g id="APPLICATION">%2$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nअधिक जानकारी के लिए, अपने व्यवस्थापक से संपर्क करें."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"आपकी कार्य प्रोफ़ाइल का प्रबंधन <xliff:g id="ORGANIZATION">%1$s</xliff:g> करता है. प्रोफ़ाइल <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nआप <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> से भी कनेक्ट हैं, जो आपकी व्यक्तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> के लिए अनलॉक किया गया"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"जब तक कि आप मैन्युअल रूप से अनलॉक नहीं करते तब तक डिवाइस लॉक रहेगा"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"सूचनाएं अधिक तेज़ी से प्राप्त करें"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"आपके द्वारा उन्हें अनलॉक किए जाने से पहले देखें"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> तक"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"रखें"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"बदलें"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 99e2e9e..d7eab75 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g> koja može nadzirati vašu osobnu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Vašim radnim profilom upravlja organizacija <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g> koja može nadzirati vaše poslovne aktivnosti na mreži, uključujući e-poruke, aplikacije i web-lokacije.\n\nAko vam je potrebno više informacija, obratite se administratoru."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Vašim radnim profilom upravlja organizacija <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> koja može nadzirati vaše poslovne aktivnosti na mreži, uključujući e-poruke, aplikacije i web-lokacije.\n\nPovezani ste i s aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> koja može nadzirati vaše osobne aktivnosti na mreži."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Otključano za korisnika <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Uređaj će ostati zaključan dok ga ručno ne otključate"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Primajte obavijesti brže"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Pogledajte ih prije otključavanja"</string>
@@ -767,4 +766,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zamijeni"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8f823cb..815dd12 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Ön a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazáshoz csatlakozik, amely figyelheti személyes hálózati tevékenységét, beleértve az e-maileket, alkalmazásokat és webhelyeket."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Munkaprofilját a(z) <xliff:g id="ORGANIZATION">%1$s</xliff:g> kezeli. A profil csatlakozik a(z) <xliff:g id="APPLICATION">%2$s</xliff:g> alkalmazáshoz, amely figyelheti az Ön hálózati tevékenységeit, beleértve az e-maileket, alkalmazásokat és webhelyeket.\n\nTovábbi információért forduljon a rendszergazdához."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Munkaprofilját a(z) <xliff:g id="ORGANIZATION">%1$s</xliff:g> kezeli. A profil csatlakozik a(z) <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> alkalmazáshoz, amely figyelheti az Ön hálózati tevékenységeit, beleértve az e-maileket, alkalmazásokat és webhelyeket.\n\nCsatlakoztatta továbbá a(z) <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> alkalmazást, amely figyelheti az Ön személyes hálózati tevékenységeit."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Felnyitva a következő számára: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Az eszköz addig zárolva marad, amíg kézileg fel nem oldja"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Gyorsabban megkaphatja az értesítéseket"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Már a képernyőzár feloldása előtt megtekintheti őket"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Eddig: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Megtartás"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Csere"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index f09cd9c..bc37813 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Դուք կապակցված եք <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել անձնական ցանցում կատարած ձեր գործողությունները, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:"</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Ձեր աշխատանքային պրոֆիլի կառավարիչն է <xliff:g id="ORGANIZATION">%1$s</xliff:g> կազմակերպությունը: Այն կապակցված է <xliff:g id="APPLICATION">%2$s</xliff:g> հավելվածին, որը կարող է վերահսկել աշխատանքային ցանցում կատարած գործունեությունը, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:\n\nԼրացուցիչ տեղեկություններ ստանալու համար դիմեք ձեր ադմինիստրատորին։"</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Ձեր աշխատանքային պրոֆիլի կառավարիչն է <xliff:g id="ORGANIZATION">%1$s</xliff:g> կազմակերպությունը: Այն կապակցված է <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> հավելվածին, որը կարող է վերահսկել աշխատանքային ցանցում կատարած գործունեությունը, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:\n\nԴուք կապակցված եք նաև <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> հավելվածին, որը կարող է վերահսկել անձնական ցանցում կատարած ձեր գործողությունները:"</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Ապակողպվել է <xliff:g id="USER_NAME">%1$s</xliff:g> օգտատիրոջ համար"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Սարքը կմնա արգելափակված՝ մինչև ձեռքով չբացեք"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Ավելի արագ ստացեք ծանուցումները"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Տեսեք դրանք մինչև ապակողպելը"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Մինչև <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Պահել"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Փոխարինել"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index bf21c593..b73d10f 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web.."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil tersambung ke <xliff:g id="APPLICATION">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan kerja, termasuk email, aplikasi, dan situs.\n\nHubungi admin untuk mendapatkan informasi lebih lanjut."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil tersambung ke <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs.\n\nAnda juga tersambung ke <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Dibuka kuncinya untuk <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Perangkat akan tetap terkunci hingga Anda membukanya secara manual"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Dapatkan pemberitahuan lebih cepat"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Lihat sebelum membuka kunci"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Hingga <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Simpan"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ganti"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 1e8db5d..eb9b620 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Þar til <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Halda"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Skipta út"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 4559d17..402c027 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Sei collegato a <xliff:g id="APPLICATION">%1$s</xliff:g>, che consente di monitorare la tua attività di rete personale, inclusi siti web, email e app."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Il tuo profilo di lavoro è gestito da <xliff:g id="ORGANIZATION">%1$s</xliff:g> ed è collegato a <xliff:g id="APPLICATION">%2$s</xliff:g>, da cui è possibile monitorare la tua attività di rete lavorativa, inclusi siti web, email e app.\n\nPer ulteriori informazioni, contatta l\'amministratore."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Il tuo profilo di lavoro è gestito da <xliff:g id="ORGANIZATION">%1$s</xliff:g> ed è collegato a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, da cui è possibile monitorare la tua attività di rete lavorativa, inclusi siti web, email e app.\n\nSei collegato anche a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, da cui è possibile monitorare la tua attività di rete personale."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Sbloccato per <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Il dispositivo resterà bloccato fino allo sblocco manuale"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Ricevi notifiche più velocemente"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Visualizza prima di sbloccare"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Fino alle ore <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Mantieni"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Sostituisci"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 34184b7..6183774 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -130,7 +130,7 @@
<string name="accessibility_ethernet_disconnected" msgid="5896059303377589469">"אתרנט מנותק."</string>
<string name="accessibility_ethernet_connected" msgid="2692130313069182636">"אתרנט מחובר."</string>
<string name="accessibility_no_signal" msgid="7064645320782585167">"אין אות."</string>
- <string name="accessibility_not_connected" msgid="6395326276213402883">"לא מחובר."</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"אין חיבור."</string>
<string name="accessibility_zero_bars" msgid="3806060224467027887">"אפס פסים."</string>
<string name="accessibility_one_bar" msgid="1685730113192081895">"פס אחד."</string>
<string name="accessibility_two_bars" msgid="6437363648385206679">"שני פסים."</string>
@@ -297,7 +297,7 @@
<string name="quick_settings_user_title" msgid="4467690427642392403">"משתמש"</string>
<string name="quick_settings_user_new_user" msgid="9030521362023479778">"משתמש חדש"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
- <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"לא מחובר"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"אין חיבור"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"אין רשת"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi כבוי"</string>
<string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"Wi-Fi פועל"</string>
@@ -383,7 +383,7 @@
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"החלף משתמש. המשתמש הנוכחי הוא <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"משתמש נוכחי <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"הצג פרופיל"</string>
- <string name="user_add_user" msgid="5110251524486079492">"הוסף משתמש"</string>
+ <string name="user_add_user" msgid="5110251524486079492">"הוספת משתמש"</string>
<string name="user_new_user_name" msgid="426540612051178753">"משתמש חדש"</string>
<string name="guest_nickname" msgid="8059989128963789678">"אורח"</string>
<string name="guest_new_guest" msgid="600537543078847803">"הוסף אורח"</string>
@@ -470,8 +470,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת הפרטית, כולל הודעות אימייל, אפליקציות ואתרים."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"פרופיל העבודה שלך מנוהל על ידי <xliff:g id="ORGANIZATION">%1$s</xliff:g>. הפרופיל מחובר לאפליקציה <xliff:g id="APPLICATION">%2$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים.\n\nלמידע נוסף, פנה למנהל המערכת."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"פרופיל העבודה שלך מנוהל על ידי <xliff:g id="ORGANIZATION">%1$s</xliff:g>. הפרופיל מחובר לאפליקציה <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים.\n\nהפרופיל מחובר גם לאפליקציה <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"הנעילה בוטלה על ידי <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"המכשיר יישאר נעול עד שתבטל את נעילתו באופן ידני"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"קבל התראות מהר יותר"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"צפה בהן לפני שתבטל נעילה"</string>
@@ -582,7 +581,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 דקות"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 דקות"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"שעה אחת"</string>
- <string name="snooze_undo" msgid="6074877317002985129">"בטל"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"ביטול"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"נדחה לטיפול בעוד <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"שימוש בסוללה"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"תכונת החיסכון בסוללה אינה זמינה בעת טעינת המכשיר"</string>
@@ -771,4 +770,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"עד <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"שמור"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"החלף"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4917e32..5442c63 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」に接続しています。このアプリはあなたの個人のネットワーク アクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。"</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"この仕事用プロファイルは<xliff:g id="ORGANIZATION">%1$s</xliff:g>によって管理され、<xliff:g id="APPLICATION">%2$s</xliff:g> に接続しています。このアプリはあなたの仕事のネットワーク アクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。\n\n詳しくは管理者にお問い合わせください。"</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"この仕事用プロファイルは<xliff:g id="ORGANIZATION">%1$s</xliff:g>によって管理され、<xliff:g id="APPLICATION_WORK">%2$s</xliff:g> に接続しています。このアプリはあなたの仕事のネットワーク アクティビティ(メール、アプリ、ウェブサイトなど)を管理できます。\n\nまた、<xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> にも接続しているため、あなたの個人のネットワーク アクティビティも監視できます。"</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> さんのロックを解除しました"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"手動でロックを解除するまでロックされたままとなります"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"通知をすばやく確認できます"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"ロックを解除する前にご確認ください"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"終了時間: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"設定を維持"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"設定を変更"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index b16b51f..74e8441 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"თქვენ დაუკავშირდით <xliff:g id="APPLICATION">%1$s</xliff:g>-ს, რომელსაც თქვენი პირადი ქსელის აქტივობის მონიტორინგი შეუძლია, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"თქვენს სამსახურის პროფილს მართავს <xliff:g id="ORGANIZATION">%1$s</xliff:g>. პროფილი დაკავშირებულია <xliff:g id="APPLICATION">%2$s</xliff:g>-თან, რომელსაც შეუძლია ქსელში თქვენი სამსახურეობრივი აქტივობის (მათ შორის, ელფოსტის, აპებისა და ვებსაიტების) მონიტორინგი.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"თქვენს სამსახურის პროფილს მართავს <xliff:g id="ORGANIZATION">%1$s</xliff:g>. პროფილი დაკავშირებულია <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>-თან, რომელსაც შეუძლია ქსელში თქვენი სამსახურეობრივი აქტივობის (მათ შორის, ელფოსტის, აპებისა და ვებსაიტების) მონიტორინგი.\n\nგარდა ამისა, თქვენ დაკავშირებული ხართ <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>-თან, რომელსაც ქსელში თქვენი პირადი აქტივობის მონიტორინგი შეუძლია."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"განბლოკილია მომხმარებლისთვის: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"მოწყობილობის დარჩება ჩაკეტილი, სანამ ხელით არ გახსნით"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"შეტყობინებების უფრო სწრაფად მიღება"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"იხილეთ განბლოკვამდე"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g>-მდე"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"შენარჩუნება"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ჩანაცვლება"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 605dec5..193eb5f 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Жеке желідегі әрекеттеріңізді, соның ішінде электрондық пошта хабарларын, қолданбаларды және вебсайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Жұмыс профиліңізді <xliff:g id="ORGANIZATION">%1$s</xliff:g> басқарады. Бұл профиль жұмыс желісіндегі белсенділігіңізді, соның ішінде электрондық хабарларды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%2$s</xliff:g> қолданбасына қосылған.\n\nҚосымша ақпарат алу үшін әкімшіге хабарласыңыз."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Жұмыс профиліңізді <xliff:g id="ORGANIZATION">%1$s</xliff:g> басқарады. Бұл профиль жұмыс желісіндегі белсенділігіңізді, соның ішінде электрондық хабарларды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> қолданбасына қосылған.\n\nСондай-ақ сіз жеке желідегі белсенділігіңізді бақылай алатын <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> қолданбасына қосылғансыз."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> үшін құлпы ашылды"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Қолмен бекітпесін ашқанша құрылғы бекітілген күйде қалады"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Хабарландыруларды тезірек алу"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Бекітпесін ашу алдында оларды көру"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> дейін"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Қалсын"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ауыстыру"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 95da2ba..8e671cf 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"អ្នកត្រូវបានភ្ជាប់ទៅ <xliff:g id="APPLICATION">%1$s</xliff:g> ដែលអាចឃ្លាំមើលសកម្មភាពបណ្តាញរបស់អ្នក រាប់បញ្ចូលទាំងអ៊ីមែល កម្មវិធី និងគេហទំព័រ។"</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"កម្រងព័ត៌មានការងាររបស់អ្នកស្ថិតក្រោមការគ្រប់គ្រងរបស់ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ។ កម្រងព័ត៌មាននេះត្រូវបានភ្ជាប់ទៅ <xliff:g id="APPLICATION">%2$s</xliff:g> ដែលអាចតាមដានសកម្មភាពបណ្តាញរបស់អ្នក រួមទាំងអ៊ីមែល កម្មវិធី និងគេហទំព័រផងដែរ។\n\nសម្រាប់ព័ត៌មានបន្ថែម សូមទាក់ទងទៅអ្នកគ្រប់គ្រងរបស់អ្នក។"</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"កម្រងព័ត៌មានការងាររបស់អ្នកស្ថិតក្រោមគ្រប់គ្រងរបស់ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ។ កម្រងព័ត៌មាននេះត្រូវបានភ្ជាប់ទៅ <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> ដែលអាចតាមដានសកម្មភាពបណ្តាញរបស់អ្នក រួមទាំងអ៊ីមែល កម្មវិធី និងគេហទំព័រផងដែរ។\n\nអ្នកក៏ត្រូវបានភ្ជាប់ទៅ <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> ដែលអាចតាមដានសកម្មភាពបណ្តាញផ្ទាល់ខ្លួនរបស់អ្នក។"</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"បានដោះសោសម្រាប់ <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ឧបករណ៍នឹងចាក់សោរហូតដល់អ្នកដោះសោដោយដៃ"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"ទទួលបានការជូនដំណឹងកាន់តែលឿន"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"ឃើញពួកវាមុនពេលដោះសោ"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"រហូតដល់ <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"រក្សានៅដដែល"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ជំនួស"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 8ab772c..1fe29b7 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"ನೀವು ಇಮೇಲ್ಗಳು, ಅಪ್ಲಿಕೇಶನ್ಗಳು, ಮತ್ತು ವೆಬ್ಸೈಟ್ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ನೆಟ್ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದಾದ <xliff:g id="APPLICATION">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು <xliff:g id="ORGANIZATION">%1$s</xliff:g> ನಿರ್ವಹಿಸುತ್ತಿದೆ. <xliff:g id="APPLICATION">%2$s</xliff:g> ಗೆ ಪ್ರೊಫೈಲ್ ಸಂಪರ್ಕಗೊಂಡಿರುವ ಕಾರಣ, ಅದು ನಿಮ್ಮ ಇಮೇಲ್ಗಳು, ಅಪ್ಲಿಕೇಶನ್ಗಳು ಹಾಗೂ ವೆಬ್ಸೈಟ್ಗಳೂ ಸೇರಿದಂತೆ ನೆಟ್ವರ್ಕ್ ಚಟುವಟಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು <xliff:g id="ORGANIZATION">%1$s</xliff:g> ನಿರ್ವಹಿಸುತ್ತಿದೆ. <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> ಗೆ ಪ್ರೊಫೈಲ್ ಸಂಪರ್ಕಗೊಂಡಿರುವ ಕಾರಣ, ಅದು ನಿಮ್ಮ ಇಮೇಲ್ಗಳು, ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ವೆಬ್ಸೈಟ್ಗಳೂ ಸೇರಿದಂತೆ ನೆಟ್ವರ್ಕ್ ಚಟುವಟಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು.\n\nನೀವು <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> ಗೆ ಕೂಡಾ ಸಂಪರ್ಕಗೊಂಡಿದ್ದೀರಿ, ಇದು ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ನೆಟ್ವರ್ಕ್ ಚಟುವಟಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> ಗಾಗಿ ಅನ್ಲಾಕ್ ಮಾಡಿ"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ನೀವಾಗಿಯೇ ಅನ್ಲಾಕ್ ಮಾಡುವವರೆಗೆ ಸಾಧನವು ಲಾಕ್ ಆಗಿಯೇ ಇರುತ್ತದೆ"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"ವೇಗವಾಗಿ ಅಧಿಸೂಚನೆಗಳನ್ನು ಪಡೆದುಕೊಳ್ಳಿ"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"ನೀವು ಅನ್ಲಾಕ್ ಮಾಡುವ ಮೊದಲೇ ಅವುಗಳನ್ನು ನೋಡಿ"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> ತನಕ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ಇರಿಸಿ"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ಬದಲಿಸಿ"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3419886..d1e7fec 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -765,4 +765,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g>까지"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"유지"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"바꾸기"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index a73c52b..04506e90 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -287,7 +287,7 @@
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Медиа түзмөгү"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Куткаруучуларга чалуу гана"</string>
- <string name="quick_settings_settings_label" msgid="5326556592578065401">"Тууралоолор"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"Жөндөөлөр"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Убакыт"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Мен"</string>
<string name="quick_settings_user_title" msgid="4467690427642392403">"Колдонуучу"</string>
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактагы жеке аракеттериңизди тескей турган <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосуна туташып турасыз."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Жумуш профилиңизди <xliff:g id="ORGANIZATION">%1$s</xliff:g> башкарат. Ал электрондук почта, колдонмолор жана вебсайттар сыяктуу жумуш тармагыңыздагы аракеттерди көзөмөлдөй турган <xliff:g id="APPLICATION">%2$s</xliff:g> колдонмосуна туташкан.\n\nКөбүрөөк маалымат алуу үчүн администраторуңузга кайрылыңыз."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Жумуш профилиңизди <xliff:g id="ORGANIZATION">%1$s</xliff:g> башкарат. Ал электрондук почта, колдонмолор жана вебсайттар сыяктуу жумуш тармагыңыздагы аракеттерди көзөмөлдөй турган <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> колдонмосуна туташкан.\n\nМындан тышкары, тармактагы жеке аракеттериңизди көзөмөлдөгөн <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> колдонмосуна туташып турасыз."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> үчүн кулпусу ачылды"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Түзмөктүн кулпусу кол менен ачылмайынча кулпуланган бойдон алат"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Эскертмелерди тезирээк алуу"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Аларды кулпудан чыгараардан мурун көрүңүз"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> чейин"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Ушундай калтыруу"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Алмаштыруу"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 9f8d672..767f98d 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -305,7 +305,7 @@
<string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"ບໍ່ມີອຸປະກອນທີ່ສາມາດໃຊ້ໄດ້"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ຄວາມແຈ້ງ"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ອັດຕະໂນມັດ"</string>
- <string name="quick_settings_inversion_label" msgid="8790919884718619648">"ສະລັບສີ"</string>
+ <string name="quick_settings_inversion_label" msgid="8790919884718619648">"ສະຫຼັບສີ"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"ໂໝດການແກ້ໄຂສີ"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"ການຕັ້ງຄ່າເພີ່ມເຕີມ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"ແລ້ວໆ"</string>
@@ -354,7 +354,7 @@
<string name="description_direction_left" msgid="7207478719805562165">"ເລື່ອນໄປທາງຊ້າຍເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="zen_priority_introduction" msgid="3070506961866919502">"ທ່ານຈະບໍ່ຖືກລົບກວນຈາກສຽງ ແລະການສັ່ນ, ຍົກເວັ້ນຈາກໂມງປຸກ, ການເຕືອນ, ເຫດການ, ແລະຜູ້ໂທທີ່ທ່ານລະບຸ."</string>
<string name="zen_priority_customize_button" msgid="7948043278226955063">"ປັບແຕ່ງ"</string>
- <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"ອັນນີ້ບລັອກທຸກສຽງ ແລະການສັ່ນ, ລວມທັງຈາກໂມງປຸກ, ເພງ, ວິດີໂອ, ແລະເກມ. ທ່ານຍັງຈະສາມາດໂທລະສັບໄດ້."</string>
+ <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"ນີ້ຈະເປັນການປິດສຽງ ແລະ ການສັ່ນທັງໝົດ ຮວມທັງສຽງໂມງປຸກ, ເພງ, ວິດີໂອ ແລະ ເກມນຳ. ແຕ່ທ່ານຍັງສາມາດໂທລະສັບໄດ້ປົກກະຕິ."</string>
<string name="zen_silence_introduction" msgid="3137882381093271568">"ອັນນີ້ບລັອກທຸກສຽງ ແລະການສັ່ນ, ລວມທັງຈາກໂມງປຸກ, ເພງ, ວິດີໂອ, ແລະເກມ."</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"ການແຈ້ງເຕືອນທີ່ສຳຄັນໜ້ອຍກວ່າຢູ່ດ້ານລຸ່ມ"</string>
@@ -762,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"ຈົນຮອດ <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ເກັບໄວ້"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ແທນທີ່"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 3bb39a3..7caaad4 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -470,8 +470,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Esate prisijungę prie programos „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kuri gali stebėti asmeninio tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Jūsų darbo profilį tvarko „<xliff:g id="ORGANIZATION">%1$s</xliff:g>“. Profilis susietas su programa „<xliff:g id="APPLICATION">%2$s</xliff:g>“, kuri gali stebėti jūsų tinklo veiklą, įskaitant el. laiškus, programas ir svetaines.\n\nJei reikia daugiau informacijos, susisiekite su administratoriumi."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Jūsų darbo profilį tvarko „<xliff:g id="ORGANIZATION">%1$s</xliff:g>“. Profilis susietas su programa „<xliff:g id="APPLICATION_WORK">%2$s</xliff:g>“, kuri gali stebėti jūsų tinklo veiklą, įskaitant el. laiškus, programas ir svetaines.\n\nTaip pat esate prisijungę prie programos „<xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>“, kuri gali stebėti asmeninio tinklo veiklą."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Atrakinta (<xliff:g id="USER_NAME">%1$s</xliff:g>)"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Įrenginys liks užrakintas, kol neatrakinsite jo neautomatiniu būdu"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Greičiau gaukite pranešimus"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Peržiūrėti prieš atrakinant"</string>
@@ -771,4 +770,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Iki <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Palikti"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Pakeisti"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index bf8b501..3ada4ce 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Ir izveidots savienojums ar lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, kas var pārraudzīt jūsu tīklā veiktās privātās darbības, tostarp e-pasta ziņojumus, lietotnes un vietnes."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Jūsu darba profilu pārvalda <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profils ir saistīts ar lietotni <xliff:g id="APPLICATION">%2$s</xliff:g>, kura var pārraudzīt jūsu tīklā veiktās darbības, tostarp saņemtos un nosūtītos e-pasta ziņojumus, izmantotās lietotnes un apmeklētās tīmekļa vietnes.\n\nLai iegūtu plašāku informāciju, sazinieties ar administratoru."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Jūsu darba profilu pārvalda <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profils ir saistīts ar lietotni <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, kura var pārraudzīt jūsu tīklā veiktās darbības, tostarp saņemtos un nosūtītos e-pasta ziņojumus, instalētās lietotnes un apmeklētās tīmekļa vietnes.\n\nIr izveidots savienojums ar lietotni <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, kas var pārraudzīt jūsu tīklā veiktās privātās darbības, tostarp saņemtos un nosūtītos e-pasta ziņojumus, instalētās lietotnes un apmeklētās tīmekļa vietnes."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Atbloķēta lietotājam <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Ierīce būs bloķēta, līdz to manuāli atbloķēsiet."</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Saņemiet paziņojumus ātrāk"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Skatiet tos pirms atbloķēšanas."</string>
@@ -767,4 +766,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Līdz: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Paturēt"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Aizstāt"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index c390a07..92b76ea 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Поврзани сте на <xliff:g id="APPLICATION">%1$s</xliff:g>, којашто може да ја следи вашата лична активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> управува со вашиот работен профил. Профилот е поврзан на <xliff:g id="APPLICATION">%2$s</xliff:g>, што може да ја следи вашата работна активност на мрежата, заедно со е-пораките, апликациите и веб-сајтовите.\n\nЗа повеќе информации, контактирајте со вашиот администратор."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> управува со вашиот работен профил. Профилот е поврзан на <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, што може да ја следи вашата работна активност на мрежата, заедно со е-пораките, апликациите и веб-сајтовите.\n\nПоврзани сте и на <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, што може да ја следи вашата лична активност на мрежата."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Отклучен за <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Уредот ќе остане заклучен додека рачно не го отклучите"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Добивајте известувања побрзо"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Видете ги пред да отклучите"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Задржи"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замени"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index cd13086..17887b8 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> വരെ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"സൂക്ഷിക്കുക"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"മാറ്റിസ്ഥാപിക്കുക"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 6e23313..746b284 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -464,8 +464,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Та имэйл, апп, вэб хуудас зэрэг хувийн сүлжээнийхээ үйл ажиллагааг хянах боломжтой <xliff:g id="APPLICATION">%1$s</xliff:g>-д холбогдсон байна."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Таны ажлын профайлыг <xliff:g id="ORGANIZATION">%1$s</xliff:g> удирддаг. Энэ нь таны имэйл, апп, вэб хуудас зэрэг ажлын сүлжээний үйл ажиллагааг хянах боломжтой <xliff:g id="APPLICATION">%2$s</xliff:g>-д холбогдсон. \n\nДэлгэрэнгүй мэдээллийг авахын тулд админтай холбогдоно уу."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Таны ажлын профайлыг <xliff:g id="ORGANIZATION">%1$s</xliff:g> удирддаг. Энэ нь таны имэйл, апп, вэб хуудас зэрэг сүлжээний үйл ажиллагааг хянах боломжтой <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>-тай холбогдсон. \n\nМөн таны сүлжээний хувийн үйл ажиллагааг хянах боломжтой <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>-д холбогдсон байна."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g>-н түгжээг тайлсан"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Таныг гараар нээх хүртэл төхөөрөмж түгжээтэй байх болно"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Мэдэгдлийг хурдан авах"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Түгжээг тайлахын өмнө үзнэ үү"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> хүртэл"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Хадгалах"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Солих"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index ce7bc5e..1514b7c 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> पर्यंत"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ठेवा"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"पुनर्स्थित करा"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 59fee4c..8d13d62 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Hingga <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Simpan"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Gantikan"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index fad3e46..8079ecd 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"သင်သည် အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကိုယ်ရေးကိုယ်တာ ကွန်ရက်အသုံးပြုမှုကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="APPLICATION">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်။"</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"သင်၏ အလုပ်ပရိုဖိုင်ကို <xliff:g id="ORGANIZATION">%1$s</xliff:g> က စီမံခန့်ခွဲထားပါသည်။ ပရိုဖိုင်သည် အီးမေး၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင်၏ကွန်ရက် လုပ်ဆောင်ချက်များကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="APPLICATION">%2$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်။\n\nနောက်ထပ် အချက်အလက်များအတွက် သင်၏ စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"သင်၏ အလုပ်ပရိုဖိုင်ကို <xliff:g id="ORGANIZATION">%1$s</xliff:g> က စီမံခန့်ခွဲထားသည်။ ပရိုဖိုင်သည် အီးမေး၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင်၏ကွန်ရက် လုပ်ဆောင်ချက်များကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်။\n\nသင်၏ ကိုယ်ရေးကိုယ်တာ ကွန်ရက်လုပ်ဆောင်ချက်များကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> သို့လည်း ချိတ်ဆက်ထားပါသည်။"</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> အတွက် လော့ခ်ဖွင့်ထားသည်"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"သင်က လက်ဖြင့် သော့မဖွင့်မချင်း ကိရိယာမှာ သော့ပိတ်လျက် ရှိနေမည်"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"အကြောင်းကြားချက်များ မြန်မြန်ရရန်"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"မဖွင့်ခင် ၎င်းတို့ကို ကြည့်ပါ"</string>
@@ -701,8 +700,8 @@
<string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> အကြောင်းကြားချက် − <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="dock_forced_resizable" msgid="5914261505436217520">"မျက်နှာပြင် ခွဲခြမ်းပြသမှုဖြင့် အက်ပ်သည် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"အက်ပ်သည် မျက်နှာပြင်ခွဲပြရန် ပံ့ပိုးထားခြင်းမရှိပါ။"</string>
- <string name="forced_resizable_secondary_display" msgid="4230857851756391925">"အက်ပ်သည် ဒုတိယမျက်နှာပြင်ပြသမှုတွင် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string>
- <string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"အက်ပ်ကို ဒုတိယဖန်မျက်နှာပြင်ပြသမှုတွင် ဖွင့်ရန်အတွက် ပံ့ပိုးမထားပါ။"</string>
+ <string name="forced_resizable_secondary_display" msgid="4230857851756391925">"ဤအက်ပ်အနေဖြင့် ဒုတိယဖန်သားပြင်မျက်နှာပြင်ပေါ်တွင် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string>
+ <string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"ဤအက်ပ်အနေဖြင့် ဒုတိယဖန်သားပြင်မျက်နှာပြင်ပေါ်တွင် ဖွင့်ပြရန်အတွက် ပံ့ပိုးမထားပါ။"</string>
<string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"ဆက်တင်များကို ဖွင့်ပါ။"</string>
<string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"အမြန်ဆက်တင်များကို ဖွင့်ပါ။"</string>
<string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"အမြန်ဆက်တင်များကို ပိတ်ပါ။"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> အထိ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"သိမ်းထားရန်"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"အစားထိုးရန်"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index db64001..7c86d1f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Til <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Behold"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Erstatt"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d33c74d..f23d2e4 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"तपाईं <xliff:g id="APPLICATION">%1$s</xliff:g> मा जोडिनुभएको छ जसले इमेल, अनुप्रयोग र वेबसाइटहरू लगायतको तपाईंको व्यक्तिगत नेटवर्क सम्बन्धी गतिविधिको अनुगमन गर्न सक्छ।"</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> ले तपाईंको कार्य प्रोफाइलको व्यवस्थापन गर्छ। उक्त प्रोफाइल तपाईंका इमेल, अनुप्रयोग र वेवसाइटहरू लगायत तपाईंको नेटवर्कको गतिविधिको अनुगमन गर्नसक्ने <xliff:g id="APPLICATION">%2$s</xliff:g> मा जडान छ।\n\nथप जानकारीका लागि, आफ्ना प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> ले तपाईंको कार्य प्रोफाइलको व्यवस्थापन गर्छ। उक्त प्रोफाइल तपाईंका इमेल, अनुप्रयोग र वेवसाइटहरू लगायत तपाईंको नेटवर्कको गतिविधिको अनुगमन गर्नसक्ने <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> मा जडान छ। \n\nतपाईं आफ्नो व्यक्तिगत नेटवर्कको गतिविधिको अनुगमन गर्नसक्ने <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> मा पनि जडान हुनुहुन्छ।"</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> का लागि अनलक गरियो"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"तपाईँले नखोले सम्म उपकरण बन्द रहनेछ"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"छिटो सूचनाहरू प्राप्त गर्नुहोस्"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"तपाईँले अनलक गर्नअघि तिनीहरूलाई हेर्नुहोस्"</string>
@@ -655,7 +654,7 @@
</string-array>
<string name="menu_ime" msgid="4998010205321292416">"किबोर्ड स्विचर"</string>
<string name="save" msgid="2311877285724540644">"सुरक्षित गर्नुहोस्"</string>
- <string name="reset" msgid="2448168080964209908">"पुनःसेट गर्नु"</string>
+ <string name="reset" msgid="2448168080964209908">"रिसेट गर्नुहोस्"</string>
<string name="adjust_button_width" msgid="6138616087197632947">"बटनको चौडाइ समायोजन गर्नुहोस्"</string>
<string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string>
<string name="accessibility_key" msgid="5701989859305675896">"अनुकूलनको नेभिगेशन बटन"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> सम्म"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"राख्नुहोस्"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"प्रतिस्थापन गर्नुहोस्"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 9c0e578..7f52537 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Je bent verbonden met <xliff:g id="APPLICATION">%1$s</xliff:g>, waarmee je persoonlijke netwerkactiviteit kan worden gecontroleerd, inclusief e-mails, apps en websites."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Je werkprofiel wordt beheerd door <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Het profiel is verbonden met <xliff:g id="APPLICATION">%2$s</xliff:g>, waarmee je werkgerelateerde netwerkactiviteit (waaronder e-mails, apps en websites) kan worden bijgehouden.\n\nNeem contact op met je beheerder voor meer informatie."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Je werkprofiel wordt beheerd door <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Het profiel is verbonden met <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, waarmee je werkgerelateerde netwerkactiviteit (waaronder e-mails, apps en websites) kan worden bijgehouden.\n\nJe bent ook verbonden met <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, waarmee je persoonlijke netwerkactiviteit kan worden bijgehouden."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Ontgrendeld voor <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Het apparaat blijft vergrendeld totdat u het handmatig ontgrendelt"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Sneller meldingen ontvangen"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Weergeven voordat u ontgrendelt"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Tot <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Behouden"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Vervangen"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 5492b19..e973eb4 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> ਤੱਕ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ਰੱਖੋ"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ਬਦਲੋ"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 2f53988..f34e705 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -770,4 +770,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Do: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Zachowaj"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zastąp"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 7f49bcf..f2b24c7 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade pessoal na rede, incluindo e-mails, apps e websites."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está conectado a <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorar sua atividade profissional de rede, incluindo e-mails, apps e websites.\n\nPara saber mais informações, entre em contato com seu administrador."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está conectado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorar sua atividade profissional de rede, incluindo e-mails, apps e websites.\n\nVocê também está conectado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorar sua atividade pessoal de rede."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Desbloqueado para <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até que você o desbloqueie manualmente"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Receba notificações mais rápido"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Veja-as antes de desbloquear"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Até <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 065e7f7..f5152ad 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Está ligado ao <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Websites."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Websites.\n\nContacte o administrador para obter mais informações."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Websites.\n\nTambém está associado à aplicação <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorizar a atividade da rede pessoal."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Desbloqueado para <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até ser desbloqueado manualmente"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Receber notificações mais rapidamente"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ver antes de desbloquear"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Até à(s) <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 7f49bcf..f2b24c7 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -468,8 +468,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade pessoal na rede, incluindo e-mails, apps e websites."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está conectado a <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorar sua atividade profissional de rede, incluindo e-mails, apps e websites.\n\nPara saber mais informações, entre em contato com seu administrador."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está conectado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorar sua atividade profissional de rede, incluindo e-mails, apps e websites.\n\nVocê também está conectado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorar sua atividade pessoal de rede."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Desbloqueado para <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até que você o desbloqueie manualmente"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Receba notificações mais rápido"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Veja-as antes de desbloquear"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Até <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index d98aabb..46d9107 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -470,8 +470,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"V-ați conectat la aplicația <xliff:g id="APPLICATION">%1$s</xliff:g>, care vă poate monitoriza activitatea personală în rețea, inclusiv e-mailurile, aplicațiile și site-urile accesate."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Profilul de serviciu este gestionat de <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profilul este conectat la <xliff:g id="APPLICATION">%2$s</xliff:g>, care vă poate monitoriza activitatea în rețeaua de serviciu, inclusiv e-mailurile, aplicațiile și site-urile accesate.\n\nPentru mai multe informații, contactați administratorul."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Profilul de serviciu este gestionat de <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profilul este conectat la <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, care vă poate monitoriza activitatea în rețeaua de serviciu, inclusiv e-mailurile, aplicațiile și site-urile accesate.\n\nDe asemenea, v-ați conectat la <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, care vă poate monitoriza activitatea în rețeaua personală."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Deblocat pentru <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Dispozitivul va rămâne blocat până când îl deblocați manual"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Obțineți notificări mai rapid"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Doresc să se afișeze înainte de deblocare"</string>
@@ -769,4 +768,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Până la <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Păstrați"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Înlocuiți"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index dd12688..37755e3 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -472,8 +472,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Запущено приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", которое может отслеживать ваши действия в сети, включая работу с электронной почтой, приложениями и веб-сайтами."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Вашим рабочим профилем управляет организация \"<xliff:g id="ORGANIZATION">%1$s</xliff:g>\". Приложение \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" может отслеживать ваши действия в корпоративной сети, включая работу с электронной почтой, приложениями и веб-сайтами.\n\nЧтобы получить подробную информацию, обратитесь к администратору."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Вашим рабочим профилем управляет организация \"<xliff:g id="ORGANIZATION">%1$s</xliff:g>\". Приложение \"<xliff:g id="APPLICATION_WORK">%2$s</xliff:g>\" может отслеживать ваши действия в корпоративной сети, включая работу с электронной почтой, приложениями и веб-сайтами.\n\nТакже запущено приложение \"<xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>\", которое может отслеживать ваши действия в сети, выполняемые в личном профиле."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Разблокировано для пользователя <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Устройство необходимо будет разблокировать вручную"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Быстрый доступ к уведомлениям"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Просматривайте уведомления на заблокированном экране."</string>
@@ -773,4 +772,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Сохранить"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Заменить"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 4820d5e..200bb29 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"ඊ-තැපැල්, යෙදුම් සහ වෙබ් අඩවි ඇතුළු ඔබේ පෞද්ගලික ජාල ක්රියාකාරකම් නිරීක්ෂණය කළ හැකි, <xliff:g id="APPLICATION">%1$s</xliff:g> වෙත ඔබ සම්බන්ධ වී ඇත."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"ඔබේ කාර්ය පැතිකඩ කළමනාකරණය කරන්නේ <xliff:g id="ORGANIZATION">%1$s</xliff:g> මගිනි. ඔබේ ඊ-තැපැල්, යෙදුම්, සහ වෙබ් අඩවි ඇතුළු, ඔබේ ජාල ක්රියාකාරකම් නිරීක්ෂණය කළ හැකි, <xliff:g id="APPLICATION">%2$s</xliff:g> වෙත පැතිකඩ සම්බන්ධය.\n\nවැඩිදුර තොරතුරු සඳහා, ඔබගේ පරිපාලක අමතන්න."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"ඔබේ කාර්යාල පැතිකඩ කළමනාකරණය කරන්නේ <xliff:g id="ORGANIZATION">%1$s</xliff:g> විසිනි. ඊ-තැපැල්, යෙදුම් සහ වෙබ් අඩවි ඇතුළු ඔබේ කාර්යාල ජාල ක්රියාකාරකම් නිරීක්ෂණය කළ හැකි, <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, වෙත පැතිකඩ සම්බන්ධ වී ඇත.\n\nඔබ ඔබේ පෞද්ගලික ජාල ක්රියාකාරකම් නිරීක්ෂණය කළ හැකි, <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> වෙතද සම්බන්ධ වී ඇත."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> සඳහා අගුලු හරින ලදී"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ඔබ අතින් අගුළු අරින තුරු උපකරණය අගුළු වැටි තිබේ"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"දැනුම්දීම් ඉක්මනින් ලබාගන්න"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"ඔබ අඟුළු හැරීමට කලින් ඒවා බලන්න"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> දක්වා"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"තබන්න"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ප්රතිස්ථාපනය"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index efcb1d0..b265cc7 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -773,4 +773,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Ponechať"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Nahradiť"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 4b49829..5c99d97 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -773,4 +773,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Obdrži"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zamenjaj"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 061a4d6..edd78f5 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Je i lidhur me aplikacionin <xliff:g id="APPLICATION">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd personal në rrjet, përfshirë mailet, aplikacionet dhe sajtet e uebit."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profili është i lidhur me <xliff:g id="APPLICATION">%2$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd të punës në rrjet, duke përfshirë mail-et, aplikacionet dhe sajtet e uebit.\n\nPër më shumë informacione, kontakto me administratorin."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profili është i lidhur me <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd të punës në rrjet, duke përfshirë mail-et, aplikacionet dhe sajtet e uebit.\n\nJe lidhur gjithashtu edhe me <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd personal në rrjet."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Shkyçur për <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Pajisje do të qëndrojë e kyçur derisa ta shkyçësh manualisht"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Merr njoftime më shpejt"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Shikoji para se t\'i shkyçësh"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Deri në <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Mbaj"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zëvendëso"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 2799782..5bf7300 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -767,4 +767,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Задржи"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замени"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index dfc1cbb..611e3e9 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Du är ansluten till <xliff:g id="APPLICATION">%1$s</xliff:g> som kan övervaka din privata aktivitet på nätverket, inklusive e-postmeddelanden, appar och webbplatser."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Jobbprofilen hanteras av <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profilen är ansluten till <xliff:g id="APPLICATION">%2$s</xliff:g> som kan bevaka din nätverksaktivitet, exempelvis e-post, appar och webbplatser.\n\nKontakta administratören om du vill veta mer."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Jobbprofilen hanteras av <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profilen är ansluten till <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> som kan bevaka din nätverksaktivitet på jobbet, exempelvis e-post, appar och webbplatser.\n\nDu är även ansluten till <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> som kan bevaka din privata nätverksaktivitet."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Upplåst för <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheten förblir låst tills du låser upp den manuellt"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Få aviseringar snabbare"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Visa dem innan du låser upp"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Till <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Behåll"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ersätt"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index bb34bb9..d3fc010 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -702,7 +702,7 @@
<string name="dock_forced_resizable" msgid="5914261505436217520">"Huenda programu isifanye kazi kwenye skrini inayogawanywa."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Programu haiwezi kutumia skrini iliyogawanywa."</string>
<string name="forced_resizable_secondary_display" msgid="4230857851756391925">"Huenda programu isifanye kazi kwenye dirisha lingine."</string>
- <string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"Programu haiwezi kutumia kipengele cha uzinduzi kwenye madirisha mengine."</string>
+ <string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"Programu haiwezi kutumia kipengele cha kuonyesha kwenye madirisha mengine."</string>
<string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Fungua mipangilio."</string>
<string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Fungua mipangilio ya haraka."</string>
<string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Funga mipangilio ya haraka."</string>
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Hadi <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Usibadilishe"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Badilisha"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 4e294e0..e11bcd2 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"<xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்தப் பயன்பாட்டால் மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"உங்கள் பணி விவரத்தை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது. மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் பணி நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION">%2$s</xliff:g> உடன் அது இணைக்கப்பட்டுள்ளது.\n\nமேலும் தகவலுக்கு, நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"உங்கள் பணி விவரத்தை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது. மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் பணி நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> உடன் அது இணைக்கப்பட்டுள்ளது.\n\nஉங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> உடனும் இணைக்கப்பட்டுள்ளீர்கள்."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g>க்குத் திறக்கப்பட்டது"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"நீங்கள் கைமுறையாகத் திறக்கும் வரை, சாதனம் பூட்டப்பட்டிருக்கும்"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"விரைவாக அறிவிப்புகளைப் பெறுதல்"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"திறக்கும் முன் அவற்றைப் பார்க்கவும்"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> வரை"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"வைத்திரு"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"மாற்று"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 933a6e0..a4bc497 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -701,8 +701,8 @@
<string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> నోటిఫికేషన్: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="dock_forced_resizable" msgid="5914261505436217520">"స్క్రీన్ విభజనతో అనువర్తనం పని చేయకపోవచ్చు."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
- <string name="forced_resizable_secondary_display" msgid="4230857851756391925">"ప్రత్యామ్నాయ ప్రదర్శనపై యాప్ పని చేయకపోవచ్చు."</string>
- <string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"ప్రత్యామ్నాయ ప్రదర్శనలపై ప్రారంభానికి యాప్ మద్దతు లేదు."</string>
+ <string name="forced_resizable_secondary_display" msgid="4230857851756391925">"ప్రత్యామ్నాయ ప్రదర్శనపై ఆప్ పని చేయకపోవచ్చు."</string>
+ <string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"ప్రత్యామ్నాయ ప్రదర్శనలపై ప్రారంభానికి ఆప్ మద్దతు లేదు."</string>
<string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"సెట్టింగ్లను తెరవండి."</string>
<string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"శీఘ్ర సెట్టింగ్లను తెరవండి."</string>
<string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"శీఘ్ర సెట్టింగ్లను మూసివేయండి."</string>
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> వరకు"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ఉంచు"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"భర్తీ చేయి"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2e66c95..4859efb 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"คุณเชื่อมต่อกับ <xliff:g id="APPLICATION">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายส่วนตัวของคุณ รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> เป็นผู้จัดการโปรไฟล์งานของคุณ โปรไฟล์ดังกล่าวเชื่อมต่ออยู่กับ <xliff:g id="APPLICATION">%2$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์\n\nโปรดติดต่อผู้ดูแลระบบของคุณสำหรับข้อมูลเพิ่มเติม"</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> เป็นผู้จัดการโปรไฟล์งานของคุณ โปรไฟล์ดังกล่าวเชื่อมต่ออยู่กับ <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์\n\nคุณยังเชื่อมต่ออยู่กับ <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> ด้วย ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายส่วนตัวของคุณ"</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"ปลดล็อกสำหรับ <xliff:g id="USER_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"อุปกรณ์จะล็อกจนกว่าคุณจะปลดล็อกด้วยตนเอง"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"รับการแจ้งเตือนเร็วขึ้น"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"ดูก่อนปลดล็อก"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"จนถึง <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"เก็บไว้"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"แทนที่"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index b91bdf6..f23443e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Nakakonekta ka sa <xliff:g id="APPLICATION">%1$s</xliff:g>, na maaaring sumubaybay sa aktibidad sa iyong personal na network, kabilang ang mga email, app at website."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Pinamamahalaan ng <xliff:g id="ORGANIZATION">%1$s</xliff:g> ang iyong profile sa trabaho. Nakakonekta ang profile sa <xliff:g id="APPLICATION">%2$s</xliff:g>, na maaaring sumubaybay sa aktibidad sa iyong network sa trabaho, kasama ang mga email, app, at website.\n\nPara sa higit pang impormasyon, makipag-ugnayan sa iyong admin."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Pinamamahalaan ng <xliff:g id="ORGANIZATION">%1$s</xliff:g> ang iyong profile sa trabaho. Nakakonekta ang profile sa <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, na maaaring sumubaybay sa aktibidad sa iyong network sa trabaho, kasama ang mga email, app, at website.\n\nNakakonekta ka rin sa <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, na maaaring sumubaybay sa aktibidad sa iyong personal na network."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Na-unlock para kay <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Mananatiling naka-lock ang device hanggang sa manu-mano mong i-unlock"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Kunin ang notification nang mas mabilis"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Tingnan ang mga ito bago ka mag-unlock"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Hanggang <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Panatilihin"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Palitan"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 8a586b1..8f536f0 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Bitiş: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Koru"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Değiştir"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 482b50f..caf58b8 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -472,8 +472,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Ваш профіль під’єднано до додатка <xliff:g id="APPLICATION">%1$s</xliff:g>, який може відстежувати вашу особисту активність у мережі, зокрема доступ до електронної пошти, додатків і веб-сайтів."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Вашим робочим профілем керує адміністратор організації <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Цей профіль під’єднано до додатка <xliff:g id="APPLICATION">%2$s</xliff:g>, який може відстежувати вашу активність у мережі, зокрема в електронній пошті, додатках і на веб-сайтах.\n\nЩоб дізнатися більше, зв’яжіться з адміністратором."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Вашим робочим профілем керує адміністратор організації <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Цей профіль під’єднано до додатка <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, який може відстежувати вашу активність у мережі, зокрема а електронній пошті, додатках і на веб-сайтах.\n\nВаш профіль також під’єднано до додатка <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, який може відстежувати вашу особисту активність у мережі."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Розблоковано для користувача <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Пристрій залишатиметься заблокованим, доки ви не розблокуєте його вручну"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Швидше отримуйте сповіщення"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Переглядайте сповіщення, перш ніж розблокувати екран"</string>
@@ -773,4 +772,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Залишити"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замінити"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 88e0022..4734422 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> تک"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"رکھیں"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"بدلیں"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 2f34b70..7e2de2e 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -505,8 +505,8 @@
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Ovoz balandligini boshqarish tugmalari ko‘rsatilgan: %s. Yopish uchun tepaga suring."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Ovoz balandligini boshqarish tugmalari yashirilgan"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"SystemUI Tuner"</string>
- <string name="show_battery_percentage" msgid="5444136600512968798">"Batareya foizi ko‘rsatilsin"</string>
- <string name="show_battery_percentage_summary" msgid="3215025775576786037">"Batareya quvvat olmayotgan vaqtda uning foizi holat qatorida ko‘rsatilsin"</string>
+ <string name="show_battery_percentage" msgid="5444136600512968798">"Batareya foizini chiqarish"</string>
+ <string name="show_battery_percentage_summary" msgid="3215025775576786037">"Quvvat olmayotgan vaqtda batareya foizi holat qatorida chiqib turadi"</string>
<string name="quick_settings" msgid="10042998191725428">"Tezkor sozlamalar"</string>
<string name="status_bar" msgid="4877645476959324760">"Holat qatori"</string>
<string name="overview" msgid="4018602013895926956">"Umumiy ma’lumot"</string>
@@ -765,4 +765,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> gacha"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Saqlab qolish"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Almashtirish"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 88920b7..f313c44 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Bạn đang kết nối với <xliff:g id="APPLICATION">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng cá nhân của bạn bao gồm email, ứng dụng và trang web."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Hồ sơ công việc của bạn do <xliff:g id="ORGANIZATION">%1$s</xliff:g> quản lý. Hồ sơ này được kết nối với <xliff:g id="APPLICATION">%2$s</xliff:g>, ứng dụng này có thể giám sát hoạt động mạng cơ quan của bạn, bao gồm email, ứng dụng và trang web.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên của bạn."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Hồ sơ công việc của bạn do <xliff:g id="ORGANIZATION">%1$s</xliff:g> quản lý. Hồ sơ này được kết nối với <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, ứng dụng này có thể giám sát hoạt động mạng của bạn, bao gồm email, ứng dụng và trang web.\n\nBạn cũng đang kết nối với <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, ứng dụng này có thể giám sát hoạt động mạng cá nhân của bạn."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Được mở khóa cho <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Thiết bị sẽ vẫn bị khóa cho tới khi bạn mở khóa theo cách thủ công"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Nhận thông báo nhanh hơn"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Xem thông báo trước khi bạn mở khóa"</string>
@@ -765,4 +764,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Cho tới <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Giữ"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Thay thế"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 02cb28f..55e52eb 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"直到<xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"替换"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 1574fd8..e4cd9a5 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -284,8 +284,8 @@
<string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"直向"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"橫向"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"輸入法"</string>
- <string name="quick_settings_location_label" msgid="5011327048748762257">"位置"</string>
- <string name="quick_settings_location_off_label" msgid="7464544086507331459">"位置關閉"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"位置資訊"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"位置資訊已關閉"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"媒體裝置"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"只可撥打緊急電話"</string>
@@ -765,4 +765,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"直至<xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"取代"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index dfd705f..6ec8a36 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -763,4 +763,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"直到 <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"取代"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 1a925ac..6fe7aa9 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -466,8 +466,7 @@
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Uxhumeke ku-<xliff:g id="APPLICATION">%1$s</xliff:g>, engaqapha umsebenzi wakho womuntu siqu wenethiwekhi, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Iphrofayela yakho yomsebenzi iphethwe i-<xliff:g id="ORGANIZATION">%1$s</xliff:g>. Iphrofayela ixhumeke ku-<xliff:g id="APPLICATION">%2$s</xliff:g>, engaqapha umsebenzi wenethiwekhi yakho yokusebenza, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi.\n\nUkuze uthole olunye ulwazi, xhumana nomlawuli wakho."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Iphrofayela yakho yomsebenzi iphethwe i-<xliff:g id="ORGANIZATION">%1$s</xliff:g>. Iphrofayela ixhumeke ku-<xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, engaqapha umsebenzi wakho wenethiwekhi, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi.\n\nFuthi uxhumeke ku-<xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, engaqapha umsebenzi wakho siqu wenethiwekhi."</string>
- <!-- no translation found for keyguard_indication_trust_granted (4985003749105182372) -->
- <skip />
+ <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Kuvulelwe u-<xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Idivayisi izohlala ikhiyekile uze uyivule ngokwenza"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Thola izaziso ngokushesha"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ibone ngaphambi kokuthi uyivule"</string>
@@ -763,4 +762,8 @@
<string name="qs_dnd_until" msgid="3469471136280079874">"Kuze kube-<xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Gcina"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Buyisela"</string>
+ <!-- no translation found for running_foreground_services_title (381024150898615683) -->
+ <skip />
+ <!-- no translation found for running_foreground_services_msg (6326247670075574355) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a98afa9..9273f01 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -130,6 +130,9 @@
<!-- size at which Notification icons will be drawn in the status bar -->
<dimen name="status_bar_icon_drawing_size">17dp</dimen>
+ <!-- size at which Notification icons will be drawn on Ambient Display -->
+ <dimen name="status_bar_icon_drawing_size_dark">@*android:dimen/notification_header_icon_size_ambient</dimen>
+
<!-- opacity at which Notification icons will be drawn in the status bar -->
<item type="dimen" name="status_bar_icon_drawing_alpha">90%</item>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f4d4a9f..cfac2b7 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -248,7 +248,7 @@
new FragmentService(mContext));
mProviders.put(ExtensionController.class, () ->
- new ExtensionControllerImpl());
+ new ExtensionControllerImpl(mContext));
mProviders.put(PluginDependencyProvider.class, () ->
new PluginDependencyProvider(get(PluginManager.class)));
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
index 086e5e5..49e780c 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
@@ -26,6 +26,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
+import android.util.IconDrawableFactory;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -159,11 +160,13 @@
static private class PackageItemAdapter extends ArrayAdapter<ApplicationInfo> {
final PackageManager mPm;
final LayoutInflater mInflater;
+ final IconDrawableFactory mIconDrawableFactory;
public PackageItemAdapter(Context context) {
super(context, R.layout.foreground_service_item);
mPm = context.getPackageManager();
mInflater = LayoutInflater.from(context);
+ mIconDrawableFactory = IconDrawableFactory.newInstance(context, true);
}
public void setPackages(String[] packages) {
@@ -193,7 +196,7 @@
}
ImageView icon = view.findViewById(R.id.app_icon);
- icon.setImageDrawable(getItem(position).loadIcon(mPm));
+ icon.setImageDrawable(mIconDrawableFactory.getBadgedIcon(getItem(position)));
TextView label = view.findViewById(R.id.app_name);
label.setText(getItem(position).loadLabel(mPm));
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 3ae0305..1cc10c2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -18,24 +18,19 @@
import android.app.AlarmManager;
import android.app.Application;
-import android.app.PendingIntent;
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Handler;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.systemui.SystemUIApplication;
-import com.android.systemui.plugins.doze.DozeProvider;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
public class DozeFactory {
- private final DozeProvider mDozePlugin;
-
- public DozeFactory(DozeProvider plugin) {
- mDozePlugin = plugin;
+ public DozeFactory() {
}
/** Creates a DozeMachine with its parts for {@code dozeService}. */
@@ -68,89 +63,14 @@
private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
DozeHost host, AmbientDisplayConfiguration config, DozeParameters params,
Handler handler, WakeLock wakeLock, DozeMachine machine) {
- boolean allowPulseTriggers = mDozePlugin == null || mDozePlugin.allowDefaultPulseTriggers();
+ boolean allowPulseTriggers = true;
return new DozeTriggers(context, machine, host, config, params,
sensorManager, handler, wakeLock, allowPulseTriggers);
}
private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
DozeMachine machine, Handler handler, AlarmManager alarmManager) {
- if (mDozePlugin != null) {
- DozeProvider.DozeUi dozeUi = mDozePlugin.provideDozeUi(context,
- pluginMachine(context, machine, host),
- wakeLock);
- return (oldState, newState) -> {
- dozeUi.transitionTo(pluginState(oldState),
- pluginState(newState));
- };
- } else {
- return new DozeUi(context, alarmManager, machine, wakeLock, host, handler);
- }
- }
-
- private DozeProvider.DozeMachine pluginMachine(Context context, DozeMachine machine,
- DozeHost host) {
- return new DozeProvider.DozeMachine() {
- @Override
- public void requestState(DozeProvider.DozeState state) {
- if (state == DozeProvider.DozeState.WAKE_UP) {
- machine.wakeUp();
- return;
- }
- machine.requestState(implState(state));
- }
-
- @Override
- public void requestSendIntent(PendingIntent intent) {
- host.startPendingIntentDismissingKeyguard(intent);
- }
- };
- }
-
- private DozeMachine.State implState(DozeProvider.DozeState s) {
- switch (s) {
- case UNINITIALIZED:
- return DozeMachine.State.UNINITIALIZED;
- case INITIALIZED:
- return DozeMachine.State.INITIALIZED;
- case DOZE:
- return DozeMachine.State.DOZE;
- case DOZE_AOD:
- return DozeMachine.State.DOZE_AOD;
- case DOZE_REQUEST_PULSE:
- return DozeMachine.State.DOZE_REQUEST_PULSE;
- case DOZE_PULSING:
- return DozeMachine.State.DOZE_PULSING;
- case DOZE_PULSE_DONE:
- return DozeMachine.State.DOZE_PULSE_DONE;
- case FINISH:
- return DozeMachine.State.FINISH;
- default:
- throw new IllegalArgumentException("Unknown state: " + s);
- }
- }
-
- private DozeProvider.DozeState pluginState(DozeMachine.State s) {
- switch (s) {
- case UNINITIALIZED:
- return DozeProvider.DozeState.UNINITIALIZED;
- case INITIALIZED:
- return DozeProvider.DozeState.INITIALIZED;
- case DOZE:
- return DozeProvider.DozeState.DOZE;
- case DOZE_AOD:
- return DozeProvider.DozeState.DOZE_AOD;
- case DOZE_REQUEST_PULSE:
- return DozeProvider.DozeState.DOZE_REQUEST_PULSE;
- case DOZE_PULSING:
- return DozeProvider.DozeState.DOZE_PULSING;
- case DOZE_PULSE_DONE:
- return DozeProvider.DozeState.DOZE_PULSE_DONE;
- case FINISH:
- return DozeProvider.DozeState.FINISH;
- default:
- throw new IllegalArgumentException("Unknown state: " + s);
- }
+ return new DozeUi(context, alarmManager, machine, wakeLock, host, handler);
}
public static DozeHost getHost(DozeService service) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 7139d59..af02e5b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -37,6 +37,7 @@
private static final int PULSE_REASONS = 5;
+ public static final int PULSE_REASON_NONE = -1;
public static final int PULSE_REASON_INTENT = 0;
public static final int PULSE_REASON_NOTIFICATION = 1;
public static final int PULSE_REASON_SENSOR_SIGMOTION = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 34d621f..5526e6b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -107,6 +107,7 @@
private final ArrayList<State> mQueuedRequests = new ArrayList<>();
private State mState = State.UNINITIALIZED;
+ private int mPulseReason;
private boolean mWakeLockHeldForCurrentState = false;
public DozeMachine(Service service, AmbientDisplayConfiguration config,
@@ -134,6 +135,20 @@
*/
@MainThread
public void requestState(State requestedState) {
+ Preconditions.checkArgument(requestedState != State.DOZE_REQUEST_PULSE);
+ requestState(requestedState, DozeLog.PULSE_REASON_NONE);
+ }
+
+ @MainThread
+ public void requestPulse(int pulseReason) {
+ // Must not be called during a transition. There's no inherent problem with that,
+ // but there's currently no need to execute from a transition and it simplifies the
+ // code to not have to worry about keeping the pulseReason in mQueuedRequests.
+ Preconditions.checkState(!isExecutingTransition());
+ requestState(State.DOZE_REQUEST_PULSE, pulseReason);
+ }
+
+ private void requestState(State requestedState, int pulseReason) {
Assert.isMainThread();
if (DEBUG) {
Log.i(TAG, "request: current=" + mState + " req=" + requestedState,
@@ -147,7 +162,7 @@
for (int i = 0; i < mQueuedRequests.size(); i++) {
// Transitions in Parts can call back into requestState, which will
// cause mQueuedRequests to grow.
- transitionTo(mQueuedRequests.get(i));
+ transitionTo(mQueuedRequests.get(i), pulseReason);
}
mQueuedRequests.clear();
mWakeLock.release();
@@ -166,6 +181,20 @@
return mState;
}
+ /**
+ * @return the current pulse reason.
+ *
+ * This is only valid if the machine is currently in one of the pulse states.
+ */
+ @MainThread
+ public int getPulseReason() {
+ Assert.isMainThread();
+ Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE
+ || mState == State.DOZE_PULSING
+ || mState == State.DOZE_PULSE_DONE, "must be in pulsing state, but is " + mState);
+ return mPulseReason;
+ }
+
/** Requests the PowerManager to wake up now. */
public void wakeUp() {
mDozeService.requestWakeUp();
@@ -175,7 +204,7 @@
return !mQueuedRequests.isEmpty();
}
- private void transitionTo(State requestedState) {
+ private void transitionTo(State requestedState, int pulseReason) {
State newState = transitionPolicy(requestedState);
if (DEBUG) {
@@ -191,6 +220,7 @@
State oldState = mState;
mState = newState;
+ updatePulseReason(newState, oldState, pulseReason);
performTransitionOnComponents(oldState, newState);
updateScreenState(newState);
updateWakeLockState(newState);
@@ -198,6 +228,14 @@
resolveIntermediateState(newState);
}
+ private void updatePulseReason(State newState, State oldState, int pulseReason) {
+ if (newState == State.DOZE_REQUEST_PULSE) {
+ mPulseReason = pulseReason;
+ } else if (oldState == State.DOZE_PULSE_DONE) {
+ mPulseReason = DozeLog.PULSE_REASON_NONE;
+ }
+ }
+
private void performTransitionOnComponents(State oldState, State newState) {
for (Part p : mParts) {
p.transitionTo(oldState, newState);
@@ -281,7 +319,8 @@
case INITIALIZED:
case DOZE_PULSE_DONE:
transitionTo(mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)
- ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE);
+ ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE,
+ DozeLog.PULSE_REASON_NONE);
break;
default:
break;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 8181c4e8..3271caf 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -24,7 +24,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.plugins.doze.DozeProvider;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -50,9 +49,7 @@
return;
}
- DozeProvider provider = Dependency.get(PluginManager.class)
- .getOneShotPlugin(DozeProvider.class);
- mDozeMachine = new DozeFactory(provider).assembleMachine(this);
+ mDozeMachine = new DozeFactory().assembleMachine(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index a721bf8..693a690 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -238,7 +238,7 @@
mDozeHost.isPulsingBlocked());
return;
}
- mMachine.requestState(DozeMachine.State.DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(reason);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 4e72bdf..22869d8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -83,7 +83,7 @@
unscheduleTimeTick();
break;
case DOZE_REQUEST_PULSE:
- pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */);
+ pulseWhileDozing(mMachine.getPulseReason());
break;
case DOZE_PULSE_DONE:
mHost.abortPulsing();
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java b/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java
new file mode 100644
index 0000000..8809510
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.fragments;
+
+import android.app.Fragment;
+import android.util.Log;
+import android.view.View;
+
+import com.android.systemui.plugins.FragmentBase;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
+
+import java.util.function.Consumer;
+
+/**
+ * Wires up an Extension to a Fragment tag/id so that it always contains the class
+ * selected by the extension.
+ */
+public class ExtensionFragmentListener<T extends FragmentBase> implements Consumer<T> {
+
+ private static final String TAG = "ExtensionFragmentListener";
+
+ private final FragmentHostManager mFragmentHostManager;
+ private final String mTag;
+ private final Extension<T> mExtension;
+ private String mOldClass;
+
+ private ExtensionFragmentListener(View view, String tag, int id, Extension<T> extension) {
+ mTag = tag;
+ mFragmentHostManager = FragmentHostManager.get(view);
+ mExtension = extension;
+ mFragmentHostManager.getFragmentManager().beginTransaction()
+ .replace(id, (Fragment) mExtension.get(), mTag)
+ .commit();
+ }
+
+ @Override
+ public void accept(T extension) {
+ try {
+ Fragment.class.cast(extension);
+ mFragmentHostManager.getExtensionManager().setCurrentExtension(mTag,
+ mOldClass, extension.getClass().getName(), mExtension.getContext());
+ mOldClass = extension.getClass().getName();
+ } catch (ClassCastException e) {
+ Log.e(TAG, extension.getClass().getName() + " must be a Fragment", e);
+ }
+ }
+
+ public static <T> void attachExtensonToFragment(View view, String tag, int id,
+ Extension<T> extension) {
+ extension.addCallback(new ExtensionFragmentListener(view, tag, id, extension));
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 8ac97f3..4dbf6f9 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -28,6 +28,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Parcelable;
+import android.support.annotation.NonNull;
import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
@@ -51,7 +52,7 @@
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
ActivityInfo.CONFIG_FONT_SCALE);
private final FragmentService mManager;
- private final PluginFragmentManager mPlugins = new PluginFragmentManager();
+ private final ExtensionFragmentManager mPlugins = new ExtensionFragmentManager();
private FragmentController mFragments;
private FragmentLifecycleCallbacks mLifecycleCallbacks;
@@ -174,7 +175,7 @@
return mFragments.getFragmentManager();
}
- PluginFragmentManager getPluginManager() {
+ ExtensionFragmentManager getExtensionManager() {
return mPlugins;
}
@@ -261,22 +262,16 @@
}
}
- class PluginFragmentManager {
- private final ArrayMap<String, Context> mPluginLookup = new ArrayMap<>();
+ class ExtensionFragmentManager {
+ private final ArrayMap<String, Context> mExtensionLookup = new ArrayMap<>();
- public void removePlugin(String tag, String currentClass, String defaultClass) {
+ public void setCurrentExtension(@NonNull String tag, @Nullable String oldClass,
+ @NonNull String currentClass, @Nullable Context context) {
Fragment fragment = getFragmentManager().findFragmentByTag(tag);
- mPluginLookup.remove(currentClass);
- getFragmentManager().beginTransaction()
- .replace(((View) fragment.getView().getParent()).getId(),
- instantiate(mContext, defaultClass, null), tag)
- .commit();
- reloadFragments();
- }
-
- public void setCurrentPlugin(String tag, String currentClass, Context context) {
- Fragment fragment = getFragmentManager().findFragmentByTag(tag);
- mPluginLookup.put(currentClass, context);
+ if (oldClass != null) {
+ mExtensionLookup.remove(oldClass);
+ }
+ mExtensionLookup.put(currentClass, context);
getFragmentManager().beginTransaction()
.replace(((View) fragment.getView().getParent()).getId(),
instantiate(context, currentClass, null), tag)
@@ -292,11 +287,11 @@
}
Fragment instantiate(Context context, String className, Bundle arguments) {
- Context pluginContext = mPluginLookup.get(className);
- if (pluginContext != null) {
- Fragment f = Fragment.instantiate(pluginContext, className, arguments);
+ Context extensionContext = mExtensionLookup.get(className);
+ if (extensionContext != null) {
+ Fragment f = Fragment.instantiate(extensionContext, className, arguments);
if (f instanceof Plugin) {
- ((Plugin) f).onCreate(mContext, pluginContext);
+ ((Plugin) f).onCreate(mContext, extensionContext);
}
return f;
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/PluginFragmentListener.java b/packages/SystemUI/src/com/android/systemui/fragments/PluginFragmentListener.java
deleted file mode 100644
index 03bb73d..0000000
--- a/packages/SystemUI/src/com/android/systemui/fragments/PluginFragmentListener.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.fragments;
-
-import android.app.Fragment;
-import android.content.Context;
-import android.util.Log;
-import android.view.View;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.FragmentBase;
-import com.android.systemui.plugins.Plugin;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
-
-public class PluginFragmentListener implements PluginListener<Plugin> {
-
- private static final String TAG = "PluginFragmentListener";
-
- private final FragmentHostManager mFragmentHostManager;
- private final PluginManager mPluginManager;
- private final Class<? extends Fragment> mDefaultClass;
- private final Class<? extends FragmentBase> mExpectedInterface;
- private final String mTag;
-
- public PluginFragmentListener(View view, String tag, Class<? extends Fragment> defaultFragment,
- Class<? extends FragmentBase> expectedInterface) {
- mTag = tag;
- mFragmentHostManager = FragmentHostManager.get(view);
- mPluginManager = Dependency.get(PluginManager.class);
- mExpectedInterface = expectedInterface;
- mDefaultClass = defaultFragment;
- }
-
- public void startListening() {
- mPluginManager.addPluginListener(this, mExpectedInterface,
- false /* Only allow one */);
- }
-
- public void stopListening() {
- mPluginManager.removePluginListener(this);
- }
-
- @Override
- public void onPluginConnected(Plugin plugin, Context pluginContext) {
- try {
- mExpectedInterface.cast(plugin);
- Fragment.class.cast(plugin);
- mFragmentHostManager.getPluginManager().setCurrentPlugin(mTag,
- plugin.getClass().getName(), pluginContext);
- } catch (ClassCastException e) {
- Log.e(TAG, plugin.getClass().getName() + " must be a Fragment and implement "
- + mExpectedInterface.getName(), e);
- }
- }
-
- @Override
- public void onPluginDisconnected(Plugin plugin) {
- mFragmentHostManager.getPluginManager().removePlugin(mTag,
- plugin.getClass().getName(), mDefaultClass.getName());
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index df03fdc..bdc0871 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -107,12 +107,12 @@
}
@Override
- public void onPinnedActivityRestartAttempt() {
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) {
if (!checkCurrentUserId(false /* debug */)) {
return;
}
- mTouchHandler.getMotionHelper().expandPip();
+ mTouchHandler.getMotionHelper().expandPip(clearedTask /* skipAnimation */);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index fc52a2e..5121c8d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -140,14 +140,25 @@
* Resizes the pinned stack back to fullscreen.
*/
void expandPip() {
+ expandPip(false /* skipAnimation */);
+ }
+
+ /**
+ * Resizes the pinned stack back to fullscreen.
+ */
+ void expandPip(boolean skipAnimation) {
cancelAnimations();
mHandler.post(() -> {
try {
- mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */,
- true /* allowResizeInDockedMode */, true /* preserveWindows */,
- true /* animate */, EXPAND_STACK_TO_FULLSCREEN_DURATION);
+ if (skipAnimation) {
+ mActivityManager.moveTasksToFullscreenStack(PINNED_STACK_ID, true /* onTop */);
+ } else {
+ mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */,
+ true /* allowResizeInDockedMode */, true /* preserveWindows */,
+ true /* animate */, EXPAND_STACK_TO_FULLSCREEN_DURATION);
+ }
} catch (RemoteException e) {
- Log.e(TAG, "Error showing PiP menu activity", e);
+ Log.e(TAG, "Error expanding PiP activity", e);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 657f08b..9735bfc 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -625,7 +625,7 @@
}
@Override
- public void onPinnedActivityRestartAttempt() {
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) {
if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
if (!checkCurrentUserId(DEBUG)) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index f5e096eb..c4d88ae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.metrics.LogMaker;
import android.os.Handler;
import android.os.Message;
import android.service.quicksettings.Tile;
@@ -30,6 +31,7 @@
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
@@ -179,7 +181,7 @@
public void openDetails(String subPanel) {
QSTile tile = getTile(subPanel);
- showDetailAdapter(true, tile.getDetailAdapter(), new int[] {getWidth() / 2, 0});
+ showDetailAdapter(true, tile.getDetailAdapter(), new int[]{getWidth() / 2, 0});
}
private QSTile getTile(String subPanel) {
@@ -485,8 +487,9 @@
private void logTiles() {
for (int i = 0; i < mRecords.size(); i++) {
- TileRecord tileRecord = mRecords.get(i);
- mMetricsLogger.visible(tileRecord.tile.getMetricsCategory());
+ QSTile tile = mRecords.get(i).tile;
+ mMetricsLogger.write(tile.populate(new LogMaker(tile.getMetricsCategory())
+ .setType(MetricsEvent.TYPE_OPEN)));
}
}
@@ -544,12 +547,13 @@
private static final int SHOW_DETAIL = 1;
private static final int SET_TILE_VISIBILITY = 2;
private static final int ANNOUNCE_FOR_ACCESSIBILITY = 3;
+
@Override
public void handleMessage(Message msg) {
if (msg.what == SHOW_DETAIL) {
- handleShowDetail((Record)msg.obj, msg.arg1 != 0);
+ handleShowDetail((Record) msg.obj, msg.arg1 != 0);
} else if (msg.what == ANNOUNCE_FOR_ACCESSIBILITY) {
- announceForAccessibility((CharSequence)msg.obj);
+ announceForAccessibility((CharSequence) msg.obj);
}
}
}
@@ -569,8 +573,11 @@
public interface QSTileLayout {
void addTile(TileRecord tile);
+
void removeTile(TileRecord tile);
+
int getOffsetTop(TileRecord tile);
+
boolean updateResources();
void setListening(boolean listening);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index dc9176f..017365f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -157,7 +157,7 @@
}
@Override
- protected LogMaker populate(LogMaker logMaker) {
+ public LogMaker populate(LogMaker logMaker) {
return super.populate(logMaker).setComponentName(mComponent);
}
@@ -275,7 +275,6 @@
} catch (RemoteException e) {
// Called through wrapper, won't happen here.
}
- MetricsLogger.action(mContext, getMetricsCategory(), mComponent.getPackageName());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 976efb2..32af230 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -175,7 +175,7 @@
mHandler.sendEmptyMessage(H.LONG_CLICK);
}
- protected LogMaker populate(LogMaker logMaker) {
+ public LogMaker populate(LogMaker logMaker) {
if (mState instanceof BooleanState) {
logMaker.addTaggedData(FIELD_QS_VALUE, ((BooleanState) mState).value ? 1 : 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 53a9eae..2b812a5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -331,8 +331,7 @@
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!launchState.launchedWithAltTab) {
// Has the user tapped quickly?
- boolean isQuickTap = ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
- elapsedTime < ViewConfiguration.getDoubleTapTimeout();
+ boolean isQuickTap = elapsedTime < ViewConfiguration.getDoubleTapTimeout();
if (Recents.getConfiguration().isGridEnabled) {
if (isQuickTap) {
EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index a9e1f61..f431517 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -158,7 +158,7 @@
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
public void onActivityPinned(String packageName) { }
public void onActivityUnpinned() { }
- public void onPinnedActivityRestartAttempt() { }
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) { }
public void onPinnedStackAnimationStarted() { }
public void onPinnedStackAnimationEnded() { }
public void onActivityForcedResizable(String packageName, int taskId, int reason) { }
@@ -223,10 +223,11 @@
}
@Override
- public void onPinnedActivityRestartAttempt()
+ public void onPinnedActivityRestartAttempt(boolean clearedTask)
throws RemoteException{
mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
- mHandler.sendEmptyMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
+ mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT, clearedTask ? 1 : 0, 0)
+ .sendToTarget();
}
@Override
@@ -1294,7 +1295,8 @@
}
case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onPinnedActivityRestartAttempt();
+ mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(
+ msg.arg1 != 0);
}
break;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 8f9c457..2401e67 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -21,6 +21,7 @@
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.ActivityOptions.OnAnimationStartedListener;
+import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -76,6 +77,9 @@
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.google.android.colorextraction.ColorExtractor;
+import com.google.android.colorextraction.drawable.GradientDrawable;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -85,13 +89,12 @@
* This view is the the top level layout that contains TaskStacks (which are laid out according
* to their SpaceNode bounds.
*/
-public class RecentsView extends FrameLayout {
+public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsChangedListener {
private static final String TAG = "RecentsView";
private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
- private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
- private static final float GRID_LAYOUT_SCRIM_ALPHA = 0.45f;
+ private static final float DEFAULT_SCRIM_ALPHA = 0.8f;
private static final int SHOW_STACK_ACTION_BUTTON_DURATION = 134;
private static final int HIDE_STACK_ACTION_BUTTON_DURATION = 100;
@@ -108,7 +111,8 @@
private int mDividerSize;
private final float mScrimAlpha;
- private final Drawable mBackgroundScrim;
+ private final GradientDrawable mBackgroundScrim;
+ private final ColorExtractor mColorExtractor;
private Animator mBackgroundScrimAnimator;
private RecentsTransitionHelper mTransitionHelper;
@@ -137,10 +141,15 @@
mDividerSize = ssp.getDockedDividerSize(context);
mTouchHandler = new RecentsViewTouchHandler(this);
mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
- mScrimAlpha = Recents.getConfiguration().isGridEnabled
- ? GRID_LAYOUT_SCRIM_ALPHA : DEFAULT_SCRIM_ALPHA;
- mBackgroundScrim = new ColorDrawable(
- Color.argb((int) (mScrimAlpha * 255), 0, 0, 0)).mutate();
+ mScrimAlpha = DEFAULT_SCRIM_ALPHA;
+ mBackgroundScrim = new GradientDrawable(context);
+ mBackgroundScrim.setCallback(this);
+ mBackgroundScrim.setAlpha((int) (mScrimAlpha * 255));
+ mColorExtractor = new ColorExtractor(context);
+ mColorExtractor.setListener(this);
+ // We don't want to interpolate colors because we're defining the initial state.
+ // Gradient should be set/ready when you open "Recents".
+ mBackgroundScrim.setColors(mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM), false);
LayoutInflater inflater = LayoutInflater.from(context);
if (RecentsDebugFlags.Static.EnableStackActionButton) {
@@ -188,7 +197,7 @@
// the tasks for the home animation.
if (launchState.launchedViaDockGesture || launchState.launchedFromApp
|| isTaskStackEmpty) {
- mBackgroundScrim.setAlpha(255);
+ mBackgroundScrim.setAlpha((int) (mScrimAlpha * 255));
} else {
mBackgroundScrim.setAlpha(0);
}
@@ -373,6 +382,11 @@
mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
+ // Needs to know the screen size since the gradient never scales up or down
+ // even when bounds change.
+ mBackgroundScrim.setScreenSize(right - left, bottom - top);
+ mBackgroundScrim.setBounds(left, top, right, bottom);
+
if (RecentsDebugFlags.Static.EnableStackActionButton) {
// Layout the stack action button such that its drawable is start-aligned with the
// stack, vertically centered in the available space above the stack
@@ -763,8 +777,8 @@
private void animateBackgroundScrim(float alpha, int duration) {
Utilities.cancelAnimationWithoutCallbacks(mBackgroundScrimAnimator);
// Calculate the absolute alpha to animate from
- int fromAlpha = (int) ((mBackgroundScrim.getAlpha() / (mScrimAlpha * 255)) * 255);
- int toAlpha = (int) (alpha * 255);
+ int fromAlpha = mBackgroundScrim.getAlpha();
+ int toAlpha = (int) (alpha * mScrimAlpha * 255);
mBackgroundScrimAnimator = ObjectAnimator.ofInt(mBackgroundScrim, Utilities.DRAWABLE_ALPHA,
fromAlpha, toAlpha);
mBackgroundScrimAnimator.setDuration(duration);
@@ -807,4 +821,11 @@
mTaskStackView.dump(innerPrefix, writer);
}
}
+
+ @Override
+ public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
+ if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+ mBackgroundScrim.setColors(colors);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 5817e92..36be49d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -279,6 +279,7 @@
}
MetricsLogger.action(mSv.getContext(), MetricsEvent.OVERVIEW_SCROLL);
+ mLastY = mDownY = y;
}
}
if (mIsScrolling) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 4612735..8887bea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -25,6 +25,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
+import android.content.res.Configuration;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.ColorDrawable;
@@ -85,6 +86,11 @@
private static final int COLORED_DIVIDER_ALPHA = 0x7B;
private static final int MENU_VIEW_INDEX = 0;
+ public interface LayoutListener {
+ public void onLayout();
+ }
+
+ private LayoutListener mLayoutListener;
private final NotificationInflater mNotificationInflater;
private int mIconTransformContentShift;
private int mIconTransformContentShiftNoIcon;
@@ -836,6 +842,13 @@
onNotificationUpdated();
}
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ if (mMenuRow.getMenuView() != null) {
+ mMenuRow.onConfigurationChanged();
+ }
+ }
+
public void setContentBackground(int customBackgroundColor, boolean animate,
NotificationContentView notificationContentView) {
if (getShowingLayout() == notificationContentView) {
@@ -1600,6 +1613,14 @@
mIsSystemChildExpanded = expanded;
}
+ public void setLayoutListener(LayoutListener listener) {
+ mLayoutListener = listener;
+ }
+
+ public void removeListener() {
+ mLayoutListener = null;
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -1608,6 +1629,9 @@
mMenuRow.onHeightUpdate();
}
updateContentShiftHeight();
+ if (mLayoutListener != null) {
+ mLayoutListener.onLayout();
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 4305bdef..cf910a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -44,7 +44,8 @@
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
-public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener {
+public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener,
+ ExpandableNotificationRow.LayoutListener {
private static final boolean DEBUG = false;
private static final String TAG = "swipe";
@@ -165,6 +166,18 @@
createMenuViews();
}
+ @Override
+ public void onConfigurationChanged() {
+ mParent.setLayoutListener(this);
+ }
+
+ @Override
+ public void onLayout() {
+ mIconsPlaced = false; // Force icons to be re-placed
+ setMenuLocation();
+ mParent.removeListener();
+ }
+
private void createMenuViews() {
// Filter the menu items based on the notification
if (mParent != null && mParent.getStatusBarNotification() != null) {
@@ -459,22 +472,17 @@
private void setMenuLocation() {
boolean showOnLeft = mTranslation > 0;
- if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping || mParent == null) {
+ if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping
+ || !mMenuContainer.isAttachedToWindow()) {
// Do nothing
return;
}
- final boolean isRtl = mParent.isLayoutRtl();
final int count = mMenuContainer.getChildCount();
- final int width = mParent.getWidth();
for (int i = 0; i < count; i++) {
final View v = mMenuContainer.getChildAt(i);
- final float left = isRtl
- ? -(width - mHorizSpaceForIcon * (i + 1))
- : i * mHorizSpaceForIcon;
- final float right = isRtl
- ? -i * mHorizSpaceForIcon
- : width - (mHorizSpaceForIcon * (i + 1));
- v.setTranslationX(showOnLeft ? left : right);
+ final float left = i * mHorizSpaceForIcon;
+ final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1));
+ v.setX(showOnLeft ? left : right);
}
mOnLeft = showOnLeft;
mIconsPlaced = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
index ccc99c5..8b3d6d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
@@ -145,13 +145,15 @@
}
private void showSnoozeOptions(boolean show) {
- mExpanded = show;
- animateSnoozeOptions(show);
int drawableId = show ? com.android.internal.R.drawable.ic_collapse_notification
: com.android.internal.R.drawable.ic_expand_notification;
mExpandButton.setImageResource(drawableId);
- if (mGutsContainer != null) {
- mGutsContainer.onHeightChanged();
+ if (mExpanded != show) {
+ mExpanded = show;
+ animateSnoozeOptions(show);
+ if (mGutsContainer != null) {
+ mGutsContainer.onHeightChanged();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index f9d0cd6..8588668 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -19,39 +19,52 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.annotation.NonNull;
import android.content.Context;
-import android.content.res.TypedArray;
+import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Paint;
+import android.graphics.Point;
import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Display;
import android.view.View;
+import android.view.WindowManager;
import android.view.animation.Interpolator;
-import com.android.systemui.R;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+
+import com.google.android.colorextraction.ColorExtractor;
+import com.google.android.colorextraction.drawable.GradientDrawable;
/**
* A view which can draw a scrim
*/
-public class ScrimView extends View
-{
- private final Paint mPaint = new Paint();
- private int mScrimColor;
- private boolean mIsEmpty = true;
+public class ScrimView extends View implements ConfigurationController.ConfigurationListener {
+ private static final String TAG = "ScrimView";
+ private final ColorExtractor.GradientColors mColors;
private boolean mDrawAsSrc;
private float mViewAlpha = 1.0f;
private ValueAnimator mAlphaAnimator;
private Rect mExcludedRect = new Rect();
private boolean mHasExcludedArea;
- private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
- = new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mViewAlpha = (float) animation.getAnimatedValue();
- invalidate();
+ private Drawable mDrawable;
+ private PorterDuffColorFilter mColorFilter;
+ private int mTintColor;
+ private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener = animation -> {
+ if (mDrawable == null) {
+ Log.w(TAG, "Trying to animate null drawable");
+ return;
}
+ mDrawable.setAlpha((int) (255 * (float) animation.getAnimatedValue()));
};
private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
@Override
@@ -76,72 +89,142 @@
public ScrimView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrimView);
+ mDrawable = new GradientDrawable(context);
+ mDrawable.setCallback(this);
+ mColors = new ColorExtractor.GradientColors();
+ updateScreenSize();
- try {
- mScrimColor = ta.getColor(R.styleable.ScrimView_scrimColor, Color.BLACK);
- } finally {
- ta.recycle();
- }
+ // We need to know about configuration changes to update the gradient size
+ // since it's independent from view bounds.
+ ConfigurationController config = Dependency.get(ConfigurationController.class);
+ config.addCallback(this);
}
@Override
protected void onDraw(Canvas canvas) {
- if (mDrawAsSrc || (!mIsEmpty && mViewAlpha > 0f)) {
- PorterDuff.Mode mode = mDrawAsSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
- int color = getScrimColorWithAlpha();
+ if (mDrawAsSrc || mDrawable.getAlpha() > 0) {
if (!mHasExcludedArea) {
- canvas.drawColor(color, mode);
+ mDrawable.draw(canvas);
} else {
- mPaint.setColor(color);
if (mExcludedRect.top > 0) {
- canvas.drawRect(0, 0, getWidth(), mExcludedRect.top, mPaint);
+ canvas.save();
+ canvas.clipRect(0, 0, getWidth(), mExcludedRect.top);
+ mDrawable.draw(canvas);
+ canvas.restore();
}
if (mExcludedRect.left > 0) {
- canvas.drawRect(0, mExcludedRect.top, mExcludedRect.left, mExcludedRect.bottom,
- mPaint);
+ canvas.save();
+ canvas.clipRect(0, mExcludedRect.top, mExcludedRect.left,
+ mExcludedRect.bottom);
+ mDrawable.draw(canvas);
+ canvas.restore();
}
if (mExcludedRect.right < getWidth()) {
- canvas.drawRect(mExcludedRect.right,
- mExcludedRect.top,
- getWidth(),
- mExcludedRect.bottom,
- mPaint);
+ canvas.save();
+ canvas.clipRect(mExcludedRect.right, mExcludedRect.top, getWidth(),
+ mExcludedRect.bottom);
+ mDrawable.draw(canvas);
+ canvas.restore();
}
if (mExcludedRect.bottom < getHeight()) {
- canvas.drawRect(0, mExcludedRect.bottom, getWidth(), getHeight(), mPaint);
+ canvas.save();
+ canvas.clipRect(0, mExcludedRect.bottom, getWidth(), getHeight());
+ mDrawable.draw(canvas);
+ canvas.restore();
}
}
}
}
- public int getScrimColorWithAlpha() {
- int color = mScrimColor;
- color = Color.argb((int) (Color.alpha(color) * mViewAlpha), Color.red(color),
- Color.green(color), Color.blue(color));
- return color;
+ public void setDrawable(Drawable drawable) {
+ mDrawable = drawable;
+ mDrawable.setCallback(this);
+ mDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom());
+ invalidate();
+ }
+
+ @Override
+ public void invalidateDrawable(@NonNull Drawable drawable) {
+ super.invalidateDrawable(drawable);
+ if (drawable == mDrawable) {
+ invalidate();
+ }
}
public void setDrawAsSrc(boolean asSrc) {
mDrawAsSrc = asSrc;
- mPaint.setXfermode(new PorterDuffXfermode(mDrawAsSrc ? PorterDuff.Mode.SRC
- : PorterDuff.Mode.SRC_OVER));
- invalidate();
+ PorterDuff.Mode mode = asSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
+ mDrawable.setXfermode(new PorterDuffXfermode(mode));
}
- public void setScrimColor(int color) {
- if (color != mScrimColor) {
- mIsEmpty = Color.alpha(color) == 0;
- mScrimColor = color;
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed) {
+ mDrawable.setBounds(left, top, right, bottom);
invalidate();
- if (mChangeRunnable != null) {
- mChangeRunnable.run();
- }
}
}
- public int getScrimColor() {
- return mScrimColor;
+ public void setColors(@NonNull ColorExtractor.GradientColors colors) {
+ setColors(colors, false);
+ }
+
+ public void setColors(@NonNull ColorExtractor.GradientColors colors, boolean animated) {
+ if (colors == null) {
+ throw new IllegalArgumentException("Colors cannot be null");
+ }
+ if (mColors.equals(colors)) {
+ return;
+ }
+ mColors.set(colors);
+ updateColorWithTint(animated);
+ }
+
+ @VisibleForTesting
+ Drawable getDrawable() {
+ return mDrawable;
+ }
+
+ public void setTint(int color) {
+ setTint(color, false);
+ }
+
+ public void setTint(int color, boolean animated) {
+ if (mTintColor == color) {
+ return;
+ }
+ mTintColor = color;
+ updateColorWithTint(animated);
+ }
+
+ private void updateColorWithTint(boolean animated) {
+ if (mDrawable instanceof GradientDrawable) {
+ // Optimization to blend colors and avoid a color filter
+ GradientDrawable drawable = (GradientDrawable) mDrawable;
+ float tintAmount = Color.alpha(mTintColor) / 255f;
+ int mainTinted = ColorUtils.blendARGB(mColors.getMainColor(), mTintColor,
+ tintAmount);
+ int secondaryTinted = ColorUtils.blendARGB(mColors.getSecondaryColor(), mTintColor,
+ tintAmount);
+ drawable.setColors(mainTinted, secondaryTinted, animated);
+ } else {
+ if (mColorFilter == null) {
+ mColorFilter = new PorterDuffColorFilter(mTintColor, PorterDuff.Mode.SRC_OVER);
+ } else {
+ mColorFilter.setColor(mTintColor);
+ }
+ mDrawable.setColorFilter(Color.alpha(mTintColor) == 0 ? null : mColorFilter);
+ mDrawable.invalidateSelf();
+ }
+
+ if (mChangeRunnable != null) {
+ mChangeRunnable.run();
+ }
+ }
+
+ public int getTint() {
+ return mTintColor;
}
@Override
@@ -150,23 +233,30 @@
}
public void setViewAlpha(float alpha) {
- if (mAlphaAnimator != null) {
- mAlphaAnimator.cancel();
- }
if (alpha != mViewAlpha) {
mViewAlpha = alpha;
- invalidate();
+
+ if (mAlphaAnimator != null) {
+ mAlphaAnimator.cancel();
+ }
+
+ mDrawable.setAlpha((int) (255 * alpha));
if (mChangeRunnable != null) {
mChangeRunnable.run();
}
}
}
+ @VisibleForTesting
+ float getViewAlpha() {
+ return mViewAlpha;
+ }
+
public void animateViewAlpha(float alpha, long durationOut, Interpolator interpolator) {
if (mAlphaAnimator != null) {
mAlphaAnimator.cancel();
}
- mAlphaAnimator = ValueAnimator.ofFloat(mViewAlpha, alpha);
+ mAlphaAnimator = ValueAnimator.ofFloat(getViewAlpha(), alpha);
mAlphaAnimator.addUpdateListener(mAlphaUpdateListener);
mAlphaAnimator.addListener(mClearAnimatorListener);
mAlphaAnimator.setInterpolator(interpolator);
@@ -193,4 +283,25 @@
public void setChangeRunnable(Runnable changeRunnable) {
mChangeRunnable = changeRunnable;
}
+
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ updateScreenSize();
+ }
+
+ private void updateScreenSize() {
+ if (mDrawable instanceof GradientDrawable) {
+ WindowManager wm = mContext.getSystemService(WindowManager.class);
+ if (wm == null) {
+ Log.w(TAG, "Can't resize gradient drawable to fit the screen");
+ return;
+ }
+ Display display = wm.getDefaultDisplay();
+ if (display != null) {
+ Point size = new Point();
+ display.getRealSize(size);
+ ((GradientDrawable) mDrawable).setScreenSize(size.x, size.y);
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 263df79..c7fbbf9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -89,6 +89,9 @@
};
private boolean mAlwaysScaleIcon;
+ private int mStatusBarIconDrawingSizeDark = 1;
+ private int mStatusBarIconDrawingSize = 1;
+ private int mStatusBarIconSize = 1;
private StatusBarIcon mIcon;
@ViewDebug.ExportedProperty private String mSlot;
private Drawable mNumberBackground;
@@ -139,7 +142,7 @@
mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color));
mNumberPain.setAntiAlias(true);
setNotification(notification);
- maybeUpdateIconScale();
+ maybeUpdateIconScaleDimens();
setScaleType(ScaleType.CENTER);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
if (mNotification != null) {
@@ -149,18 +152,30 @@
reloadDimens();
}
- private void maybeUpdateIconScale() {
+ private void maybeUpdateIconScaleDimens() {
// We do not resize and scale system icons (on the right), only notification icons (on the
// left).
if (mNotification != null || mAlwaysScaleIcon) {
- updateIconScale();
+ updateIconScaleDimens();
}
}
- private void updateIconScale() {
+ private void updateIconScaleDimens() {
Resources res = mContext.getResources();
- final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
- final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
+ mStatusBarIconSize = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
+ mStatusBarIconDrawingSizeDark =
+ res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size_dark);
+ mStatusBarIconDrawingSize =
+ res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
+ updateIconScale();
+ }
+
+ private void updateIconScale() {
+ final float imageBounds = NotificationUtils.interpolate(
+ mStatusBarIconDrawingSize,
+ mStatusBarIconDrawingSizeDark,
+ mDarkAmount);
+ final int outerBounds = mStatusBarIconSize;
mIconScale = (float)imageBounds / (float)outerBounds;
}
@@ -174,7 +189,7 @@
int density = newConfig.densityDpi;
if (density != mDensity) {
mDensity = density;
- maybeUpdateIconScale();
+ maybeUpdateIconScaleDimens();
updateDrawable();
reloadDimens();
}
@@ -198,7 +213,7 @@
mDozer = new NotificationIconDozeHelper(context);
mBlocked = false;
mAlwaysScaleIcon = true;
- updateIconScale();
+ updateIconScaleDimens();
mDensity = context.getResources().getDisplayMetrics().densityDpi;
}
@@ -681,6 +696,7 @@
public void setDark(boolean dark, boolean fade, long delay) {
mDozer.setIntensityDark(f -> {
mDarkAmount = f;
+ updateIconScale();
updateDecorColor();
updateIconColor();
}, dark, fade, delay);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f9cf67c..f40de79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -185,6 +185,7 @@
private int mQsFalsingThreshold;
private float mKeyguardStatusBarAnimateAlpha = 1f;
+ private float mQsClockAlphaOverride = 1f;
private int mOldLayoutDirection;
private HeadsUpTouchHelper mHeadsUpTouchHelper;
private boolean mIsExpansionFromHeadsUp;
@@ -500,7 +501,7 @@
private void updateClock(float alpha, float scale) {
if (!mKeyguardStatusViewAnimating) {
- mKeyguardStatusView.setAlpha(alpha);
+ mKeyguardStatusView.setAlpha(alpha * mQsClockAlphaOverride);
}
mKeyguardStatusView.setScaleX(scale);
mKeyguardStatusView.setScaleY(scale);
@@ -1250,6 +1251,15 @@
mQsNavbarScrim.setAlpha(getQsExpansionFraction());
}
+ // Fade clock when QS is on top of it
+ float newClockAlpha = (height - mKeyguardStatusView.getY()) /
+ mKeyguardStatusView.getHeight();
+ newClockAlpha = 1 - MathUtils.constrain(newClockAlpha, 0, 1);
+ if (newClockAlpha != mQsClockAlphaOverride) {
+ mQsClockAlphaOverride = Interpolators.ALPHA_OUT.getInterpolation(newClockAlpha);
+ updateClock(mClockPositionResult.clockAlpha, mClockPositionResult.clockScale);
+ }
+
// Upon initialisation when we are not layouted yet we don't want to announce that we are
// fully expanded, hence the != 0.0f check.
if (height != 0.0f && mQsFullyExpanded && !mLastAnnouncementWasQuickSettings) {
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 67d5b6a..d29b356 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -20,9 +20,12 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
+import android.app.WallpaperManager;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.Rect;
import android.support.v4.graphics.ColorUtils;
+import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
@@ -30,6 +33,7 @@
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -38,12 +42,14 @@
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.stack.ViewState;
+import com.google.android.colorextraction.ColorExtractor;
+
/**
* Controls both the scrim behind the notifications and in front of the notifications (when a
* security method gets shown).
*/
public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
- OnHeadsUpChangedListener {
+ OnHeadsUpChangedListener, ColorExtractor.OnColorsChangedListener {
public static final long ANIMATION_DURATION = 220;
public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
= new PathInterpolator(0f, 0, 0.7f, 1f);
@@ -61,11 +67,16 @@
private final LightBarController mLightBarController;
protected final ScrimView mScrimBehind;
- private final ScrimView mScrimInFront;
+ protected final ScrimView mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
private final View mHeadsUpScrim;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final ColorExtractor mColorExtractor;
+ private ColorExtractor.GradientColors mLockColors;
+ private ColorExtractor.GradientColors mSystemColors;
+ private boolean mNeedsDrawableColorUpdate;
+
protected float mScrimBehindAlpha;
protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
protected float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
@@ -98,6 +109,7 @@
private boolean mSkipFirstFrame;
private boolean mDontAnimateBouncerChanges;
private boolean mKeyguardFadingOutInProgress;
+ private boolean mAnimatingDozeUnlock;
private ValueAnimator mKeyguardFadeoutAnimation;
public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
@@ -111,12 +123,22 @@
mLightBarController = lightBarController;
mScrimBehindAlpha = context.getResources().getFloat(R.dimen.scrim_behind_alpha);
+ mColorExtractor = new ColorExtractor(context);
+ mColorExtractor.setListener(this);
+ mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
+ mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM);
+ mNeedsDrawableColorUpdate = true;
+
updateHeadsUpScrim(false);
updateScrims();
}
public void setKeyguardShowing(boolean showing) {
mKeyguardShowing = showing;
+
+ // Showing/hiding the keyguard means that scrim colors
+ // will probably have to be switched
+ mNeedsDrawableColorUpdate = true;
scheduleUpdate();
}
@@ -157,6 +179,7 @@
public void setWakeAndUnlocking() {
mWakeAndUnlocking = true;
+ mAnimatingDozeUnlock = true;
scheduleUpdate();
}
@@ -192,7 +215,7 @@
public void animateKeyguardUnoccluding(long duration) {
mAnimateChange = false;
- setScrimBehindColor(0f);
+ setScrimBehindAlpha(0f);
mAnimateChange = true;
scheduleUpdate();
mDurationOverride = duration;
@@ -246,23 +269,35 @@
}
protected void updateScrims() {
- if (mAnimateKeyguardFadingOut || mForceHideScrims) {
- setScrimInFrontColor(0f);
- setScrimBehindColor(0f);
- } else if (mWakeAndUnlocking) {
+ // Make sure we have the right gradients
+ if (mNeedsDrawableColorUpdate) {
+ mNeedsDrawableColorUpdate = false;
+ if (mKeyguardShowing) {
+ mScrimInFront.setColors(mLockColors);
+ mScrimBehind.setColors(mLockColors);
+ } else {
+ mScrimInFront.setColors(mSystemColors, true);
+ mScrimBehind.setColors(mSystemColors, true);
+ }
+ }
+
+ if (mAnimateKeyguardFadingOut || mForceHideScrims) {
+ setScrimInFrontAlpha(0f);
+ setScrimBehindAlpha(0f);
+ } else if (mWakeAndUnlocking) {
// During wake and unlock, we first hide everything behind a black scrim, which then
// gets faded out from animateKeyguardFadingOut.
if (mDozing) {
- setScrimInFrontColor(0f);
- setScrimBehindColor(1f);
+ setScrimInFrontAlpha(0f);
+ setScrimBehindAlpha(1f);
} else {
- setScrimInFrontColor(1f);
- setScrimBehindColor(0f);
+ setScrimInFrontAlpha(1f);
+ setScrimBehindAlpha(0f);
}
} else if (!mKeyguardShowing && !mBouncerShowing) {
updateScrimNormal();
- setScrimInFrontColor(0);
+ setScrimInFrontAlpha(0);
} else {
updateScrimKeyguard();
}
@@ -275,18 +310,18 @@
float fraction = 1 - behindFraction;
fraction = (float) Math.pow(fraction, 0.8f);
behindFraction = (float) Math.pow(behindFraction, 0.8f);
- setScrimInFrontColor(fraction * getScrimInFrontAlpha());
- setScrimBehindColor(behindFraction * mScrimBehindAlphaKeyguard);
+ setScrimInFrontAlpha(fraction * getScrimInFrontAlpha());
+ setScrimBehindAlpha(behindFraction * mScrimBehindAlphaKeyguard);
} else if (mBouncerShowing && !mBouncerIsKeyguard) {
- setScrimInFrontColor(getScrimInFrontAlpha());
+ setScrimInFrontAlpha(getScrimInFrontAlpha());
updateScrimNormal();
} else if (mBouncerShowing) {
- setScrimInFrontColor(0f);
- setScrimBehindColor(mScrimBehindAlpha);
+ setScrimInFrontAlpha(0f);
+ setScrimBehindAlpha(mScrimBehindAlpha);
} else {
float fraction = Math.max(0, Math.min(mFraction, 1));
- setScrimInFrontColor(0f);
- setScrimBehindColor(fraction
+ setScrimInFrontAlpha(0f);
+ setScrimBehindAlpha(fraction
* (mScrimBehindAlphaKeyguard - mScrimBehindAlphaUnlocking)
+ mScrimBehindAlphaUnlocking);
}
@@ -297,30 +332,29 @@
// let's start this 20% of the way down the screen
frac = frac * 1.2f - 0.2f;
if (frac <= 0) {
- setScrimBehindColor(0);
+ setScrimBehindAlpha(0);
} else {
// woo, special effects
final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
- setScrimBehindColor(k * mScrimBehindAlpha);
+ setScrimBehindAlpha(k * mScrimBehindAlpha);
}
}
- private void setScrimBehindColor(float alpha) {
- setScrimColor(mScrimBehind, alpha);
+ private void setScrimBehindAlpha(float alpha) {
+ setScrimAlpha(mScrimBehind, alpha);
}
- private void setScrimInFrontColor(float alpha) {
- setScrimColor(mScrimInFront, alpha);
+ private void setScrimInFrontAlpha(float alpha) {
+ setScrimAlpha(mScrimInFront, alpha);
if (alpha == 0f) {
mScrimInFront.setClickable(false);
} else {
-
// Eat touch events (unless dozing).
mScrimInFront.setClickable(!mDozing);
}
}
- private void setScrimColor(View scrim, float alpha) {
+ private void setScrimAlpha(View scrim, float alpha) {
updateScrim(mAnimateChange, scrim, alpha, getCurrentScrimAlpha(scrim));
}
@@ -346,15 +380,20 @@
}
}
- protected void updateScrimColor(View scrim) {
+ private void updateScrimColor(View scrim) {
float alpha1 = getCurrentScrimAlpha(scrim);
if (scrim instanceof ScrimView) {
- float alpha2 = getDozeAlpha(scrim);
- float alpha = 1 - (1 - alpha1) * (1 - alpha2);
+ ScrimView scrimView = (ScrimView) scrim;
+ float dozeAlpha = getDozeAlpha(scrim);
+ float alpha = 1 - (1 - alpha1) * (1 - dozeAlpha);
alpha = Math.max(0, Math.min(1.0f, alpha));
- int baseColor = ((ScrimView) scrim).getScrimColor();
- ((ScrimView) scrim).setScrimColor(
- ColorUtils.setAlphaComponent(baseColor, (int) (alpha * 255)));
+ scrimView.setViewAlpha(alpha);
+
+ int dozeTint = Color.TRANSPARENT;
+ if (mAnimatingDozeUnlock || mDozing) {
+ dozeTint = Color.BLACK;
+ }
+ scrimView.setTint(dozeTint);
} else {
scrim.setAlpha(alpha1);
}
@@ -363,13 +402,10 @@
private void startScrimAnimation(final View scrim, float target) {
float current = getCurrentScrimAlpha(scrim);
ValueAnimator anim = ValueAnimator.ofFloat(current, target);
- anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float alpha = (float) animation.getAnimatedValue();
- setCurrentScrimAlpha(scrim, alpha);
- updateScrimColor(scrim);
- }
+ anim.addUpdateListener(animation -> {
+ float alpha = (float) animation.getAnimatedValue();
+ setCurrentScrimAlpha(scrim, alpha);
+ updateScrimColor(scrim);
});
anim.setInterpolator(getInterpolator());
anim.setStartDelay(mAnimationDelay);
@@ -384,6 +420,7 @@
if (mKeyguardFadingOutInProgress) {
mKeyguardFadeoutAnimation = null;
mKeyguardFadingOutInProgress = false;
+ mAnimatingDozeUnlock = false;
}
scrim.setTag(TAG_KEY_ANIM, null);
scrim.setTag(TAG_KEY_ANIM_TARGET, null);
@@ -436,6 +473,8 @@
mOnAnimationFinished = null;
}
mKeyguardFadingOutInProgress = false;
+ if (!mWakeAndUnlocking || force)
+ mAnimatingDozeUnlock = false;
}
}
@@ -559,8 +598,10 @@
mScrimBehind.setExcludedArea(area);
}
- public int getScrimBehindColor() {
- return mScrimBehind.getScrimColorWithAlpha();
+ public int getBackgroundColor() {
+ int color = mLockColors.getMainColor();
+ return Color.argb((int) (mScrimBehind.getAlpha() * Color.alpha(color)),
+ Color.red(color), Color.green(color), Color.blue(color));
}
public void setScrimBehindChangeRunnable(Runnable changeRunnable) {
@@ -577,4 +618,18 @@
public void setCurrentUser(int currentUser) {
// Don't care in the base class.
}
+
+ @Override
+ public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
+ if ((which & WallpaperManager.FLAG_LOCK) != 0) {
+ mLockColors = colors;
+ mNeedsDrawableColorUpdate = true;
+ scheduleUpdate();
+ }
+ if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+ mSystemColors = colors;
+ mNeedsDrawableColorUpdate = true;
+ scheduleUpdate();
+ }
+ }
}
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 e146e93..28895d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -21,6 +21,7 @@
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
+import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
@@ -36,11 +37,17 @@
import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
+import android.app.INotificationManager;
+import android.app.KeyguardManager;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.RemoteInput;
import android.app.StatusBarManager;
+import android.app.TaskStackBuilder;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -49,8 +56,11 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -75,7 +85,9 @@
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
@@ -88,63 +100,86 @@
import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
+import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.view.ContextThemeWrapper;
import android.view.Display;
+import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ThreadedRenderer;
import android.view.View;
+import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.DateTimeView;
import android.widget.ImageView;
+import android.widget.RemoteViews;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationMessagingUtil;
+import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.ActivityStarterDelegate;
+import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.fragments.ExtensionFragmentListener;
import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.fragments.PluginFragmentListener;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
@@ -183,6 +218,7 @@
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
@@ -190,11 +226,15 @@
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.PreviewInflater;
+import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+ .OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.util.NotificationChannels;
import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.volume.VolumeComponent;
@@ -205,50 +245,10 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import android.app.ActivityManager.StackId;
-import android.app.INotificationManager;
-import android.app.KeyguardManager;
-import android.app.NotificationChannel;
-import android.app.RemoteInput;
-import android.app.TaskStackBuilder;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
-import android.os.Build;
-import android.os.Handler;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
-import android.service.notification.NotificationListenerService;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
-import android.text.TextUtils;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-import android.view.IWindowManager;
-import android.view.ViewAnimationUtils;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.RemoteViews;
-import android.widget.Toast;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.SystemUI;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
-import com.android.systemui.util.NotificationChannels;
-
import java.util.HashSet;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Set;
import java.util.Stack;
@@ -1133,11 +1133,12 @@
View container = mStatusBarWindow.findViewById(R.id.qs_frame);
if (container != null) {
FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
- fragmentHostManager.getFragmentManager().beginTransaction()
- .replace(R.id.qs_frame, new QSFragment(), QS.TAG)
- .commit();
- new PluginFragmentListener(container, QS.TAG, QSFragment.class, QS.class)
- .startListening();
+ ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
+ Dependency.get(ExtensionController.class).newExtension(QS.class)
+ .withPlugin(QS.class)
+ .withUiMode(UI_MODE_TYPE_CAR, () -> new QSFragment())
+ .withDefault(() -> new QSFragment())
+ .build());
final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
mIconController);
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
@@ -4061,7 +4062,10 @@
public void showKeyguard() {
mKeyguardRequested = true;
- updateIsKeyguard();
+ // Unconditionally show keyguard again. There's some logic that relies on this
+ // being called even when the keyguard is already showing, e.g. for updating
+ // sensitiveness of notifications and making sure the panels are expanded.
+ showKeyguardImpl();
}
public boolean hideKeyguard() {
@@ -4074,7 +4078,10 @@
// there's no surface we can show to the user.
boolean keyguardForDozing = mDozingRequested && !mDeviceInteractive;
boolean shouldBeKeyguard = mKeyguardRequested || keyguardForDozing;
- if (shouldBeKeyguard && !mIsKeyguard) {
+ if (keyguardForDozing) {
+ updatePanelExpansionForKeyguard();
+ }
+ if (shouldBeKeyguard) {
showKeyguardImpl();
} else if (!shouldBeKeyguard && mIsKeyguard) {
return hideKeyguardImpl();
@@ -4102,11 +4109,7 @@
// Keyguard.
mNotificationPanel.setTouchDisabled(true);
}
- if (mState == StatusBarState.KEYGUARD) {
- instantExpandNotificationsPanel();
- } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
- instantCollapseNotificationPanel();
- }
+ updatePanelExpansionForKeyguard();
mLeaveOpenOnKeyguardHide = false;
if (mDraggedDownRow != null) {
mDraggedDownRow.setUserLocked(false);
@@ -4117,6 +4120,14 @@
mAssistManager.onLockscreenShown();
}
+ private void updatePanelExpansionForKeyguard() {
+ if (mState == StatusBarState.KEYGUARD) {
+ instantExpandNotificationsPanel();
+ } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
+ instantCollapseNotificationPanel();
+ }
+ }
+
private void onLaunchTransitionFadingEnded() {
mNotificationPanel.setAlpha(1.0f);
mNotificationPanel.onAffordanceLaunchEnded();
@@ -4505,7 +4516,6 @@
}
private void instantExpandNotificationsPanel() {
-
// Make our window larger and the panel expanded.
makeExpandedVisible(true);
mNotificationPanel.expand(false /* animate */);
@@ -5086,6 +5096,7 @@
mDozingRequested = true;
DozeLog.traceDozing(mContext, mDozing);
updateDozing();
+
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
index eaf8925..6128749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
@@ -14,8 +14,7 @@
package com.android.systemui.statusbar.policy;
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.Plugin;
+import android.content.Context;
import java.util.Map;
import java.util.function.Consumer;
@@ -31,7 +30,9 @@
interface Extension<T> {
T get();
+ Context getContext();
void destroy();
+ void addCallback(Consumer<T> callback);
}
interface ExtensionBuilder<T> {
@@ -42,6 +43,7 @@
PluginConverter<T, P> converter);
ExtensionBuilder<T> withDefault(Supplier<T> def);
ExtensionBuilder<T> withCallback(Consumer<T> callback);
+ ExtensionBuilder<T> withUiMode(int mode, Supplier<T> def);
Extension build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
index fefbaa3..91b6160 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -14,23 +14,38 @@
package com.android.systemui.statusbar.policy;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Handler;
+import android.util.ArrayMap;
+
import com.android.systemui.Dependency;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
-import android.content.Context;
-import android.util.ArrayMap;
-
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class ExtensionControllerImpl implements ExtensionController {
+ public static final int SORT_ORDER_PLUGIN = 0;
+ public static final int SORT_ORDER_TUNER = 1;
+ public static final int SORT_ORDER_UI_MODE = 2;
+ public static final int SORT_ORDER_DEFAULT = 3;
+
+ private final Context mDefaultContext;
+
+ public ExtensionControllerImpl(Context context) {
+ mDefaultContext = context;
+ }
+
@Override
public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
return new ExtensionBuilder<>();
@@ -38,6 +53,7 @@
private interface Producer<T> {
T get();
+
void destroy();
}
@@ -75,6 +91,12 @@
return this;
}
+ public ExtensionController.ExtensionBuilder<T> withUiMode(int uiMode,
+ Supplier<T> supplier) {
+ mExtension.addUiMode(uiMode, supplier);
+ return this;
+ }
+
@Override
public ExtensionController.ExtensionBuilder<T> withCallback(
Consumer<T> callback) {
@@ -85,34 +107,21 @@
@Override
public ExtensionController.Extension build() {
// Manually sort, plugins first, tuners second, defaults last.
- Collections.sort(mExtension.mProducers, (o1, o2) -> {
- if (o1 instanceof ExtensionImpl.PluginItem) {
- if (o2 instanceof ExtensionImpl.PluginItem) {
- return 0;
- } else {
- return -1;
- }
- }
- if (o1 instanceof ExtensionImpl.TunerItem) {
- if (o2 instanceof ExtensionImpl.PluginItem) {
- return 1;
- } else if (o2 instanceof ExtensionImpl.TunerItem) {
- return 0;
- } else {
- return -1;
- }
- }
- return 0;
- });
+ Collections.sort(mExtension.mProducers, Comparator.comparingInt(Item::sortOrder));
mExtension.notifyChanged();
return mExtension;
}
}
private class ExtensionImpl<T> implements ExtensionController.Extension<T> {
- private final ArrayList<Producer<T>> mProducers = new ArrayList<>();
+ private final ArrayList<Item<T>> mProducers = new ArrayList<>();
private final ArrayList<Consumer<T>> mCallbacks = new ArrayList<>();
private T mItem;
+ private Context mPluginContext;
+
+ public void addCallback(Consumer<T> callback) {
+ mCallbacks.add(callback);
+ }
@Override
public T get() {
@@ -120,6 +129,11 @@
}
@Override
+ public Context getContext() {
+ return mPluginContext != null ? mPluginContext : mDefaultContext;
+ }
+
+ @Override
public void destroy() {
for (int i = 0; i < mProducers.size(); i++) {
mProducers.get(i).destroy();
@@ -127,6 +141,7 @@
}
private void notifyChanged() {
+ mItem = null;
for (int i = 0; i < mProducers.size(); i++) {
final T item = mProducers.get(i).get();
if (item != null) {
@@ -151,7 +166,11 @@
mProducers.add(new TunerItem(factory, factory.keys()));
}
- private class PluginItem<P extends Plugin> implements Producer<T>, PluginListener<P> {
+ public void addUiMode(int uiMode, Supplier<T> mode) {
+ mProducers.add(new UiModeItem(uiMode, mode));
+ }
+
+ private class PluginItem<P extends Plugin> implements Item<T>, PluginListener<P> {
private final PluginConverter<T, P> mConverter;
private T mItem;
@@ -162,6 +181,7 @@
@Override
public void onPluginConnected(P plugin, Context pluginContext) {
+ mPluginContext = pluginContext;
if (mConverter != null) {
mItem = mConverter.getInterfaceFromPlugin(plugin);
} else {
@@ -172,6 +192,7 @@
@Override
public void onPluginDisconnected(P plugin) {
+ mPluginContext = null;
mItem = null;
notifyChanged();
}
@@ -185,9 +206,14 @@
public void destroy() {
Dependency.get(PluginManager.class).removePluginListener(this);
}
+
+ @Override
+ public int sortOrder() {
+ return SORT_ORDER_PLUGIN;
+ }
}
- private class TunerItem<T> implements Producer<T>, Tunable {
+ private class TunerItem<T> implements Item<T>, Tunable {
private final TunerFactory<T> mFactory;
private final ArrayMap<String, String> mSettings = new ArrayMap<>();
private T mItem;
@@ -213,9 +239,54 @@
mItem = mFactory.create(mSettings);
notifyChanged();
}
+
+ @Override
+ public int sortOrder() {
+ return SORT_ORDER_TUNER;
+ }
}
- private class Default<T> implements Producer<T> {
+ private class UiModeItem<T> implements Item<T>, ConfigurationListener {
+
+ private final int mDesiredUiMode;
+ private final Supplier<T> mSupplier;
+ private int mUiMode;
+ private Handler mHandler = new Handler();
+
+ public UiModeItem(int uiMode, Supplier<T> supplier) {
+ mDesiredUiMode = uiMode;
+ mSupplier = supplier;
+ mUiMode = mDefaultContext.getResources().getConfiguration().uiMode;
+ Dependency.get(ConfigurationController.class).addCallback(this);
+ }
+
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ int newMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
+ if (newMode != mUiMode) {
+ mUiMode = newMode;
+ // Post to make sure we don't have concurrent modifications.
+ mHandler.post(ExtensionImpl.this::notifyChanged);
+ }
+ }
+
+ @Override
+ public T get() {
+ return (mUiMode == mDesiredUiMode) ? mSupplier.get() : null;
+ }
+
+ @Override
+ public void destroy() {
+ Dependency.get(ConfigurationController.class).removeCallback(this);
+ }
+
+ @Override
+ public int sortOrder() {
+ return SORT_ORDER_UI_MODE;
+ }
+ }
+
+ private class Default<T> implements Item<T> {
private final Supplier<T> mSupplier;
public Default(Supplier<T> supplier) {
@@ -231,6 +302,15 @@
public void destroy() {
}
+
+ @Override
+ public int sortOrder() {
+ return SORT_ORDER_DEFAULT;
+ }
}
}
+
+ private interface Item<T> extends Producer<T> {
+ int sortOrder();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 7349ee4..94b6aaa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -58,6 +58,7 @@
import android.view.animation.Interpolator;
import android.widget.OverScroller;
import android.widget.ScrollView;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.ExpandHelper;
@@ -87,6 +88,8 @@
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ScrollAdapter;
+import android.support.v4.graphics.ColorUtils;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -477,16 +480,8 @@
float alpha = BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
alpha *= mBackgroundFadeAmount;
// We need to manually blend in the background color
- int scrimColor = mScrimController.getScrimBehindColor();
- // SRC_OVER blending Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc
- float alphaInv = 1 - alpha;
- int color = Color.argb((int) (alpha * 255 + alphaInv * Color.alpha(scrimColor)),
- (int) (mBackgroundFadeAmount * Color.red(mBgColor)
- + alphaInv * Color.red(scrimColor)),
- (int) (mBackgroundFadeAmount * Color.green(mBgColor)
- + alphaInv * Color.green(scrimColor)),
- (int) (mBackgroundFadeAmount * Color.blue(mBgColor)
- + alphaInv * Color.blue(scrimColor)));
+ int scrimColor = mScrimController.getBackgroundColor();
+ int color = ColorUtils.blendARGB(scrimColor, mBgColor, alpha);
if (mCachedBackgroundColor != color) {
mCachedBackgroundColor = color;
mBackgroundPaint.setColor(color);
@@ -4059,12 +4054,7 @@
public void setScrimController(ScrimController scrimController) {
mScrimController = scrimController;
- mScrimController.setScrimBehindChangeRunnable(new Runnable() {
- @Override
- public void run() {
- updateBackgroundDimming();
- }
- });
+ mScrimController.setScrimBehindChangeRunnable(this::updateBackgroundDimming);
}
public void forceNoOverlappingRendering(boolean force) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index 23c51d2..edf294e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -20,10 +20,17 @@
import android.os.PowerManager;
import android.support.annotation.VisibleForTesting;
-import com.android.systemui.plugins.doze.DozeProvider;
-
/** WakeLock wrapper for testability */
-public interface WakeLock extends DozeProvider.WakeLock {
+public interface WakeLock {
+
+ /** @see android.os.PowerManager.WakeLock#acquire() */
+ void acquire();
+
+ /** @see android.os.PowerManager.WakeLock#release() */
+ void release();
+
+ /** @see android.os.PowerManager.WakeLock#wrap(Runnable) */
+ Runnable wrap(Runnable r);
static WakeLock createPartial(Context context, String tag) {
return wrap(createPartialInner(context, tag));
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 5e8b3f9..8ac18e3 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -44,7 +44,8 @@
android-support-v7-mediarouter \
android-support-v7-palette \
android-support-v14-preference \
- android-support-v17-leanback
+ android-support-v17-leanback \
+ colorextraction
LOCAL_STATIC_JAVA_LIBRARIES := \
metrics-helper-lib \
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 24d8b92..fa6ba96 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -106,7 +106,7 @@
public void testPulseDone_goesToDoze() {
when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false);
mMachine.requestState(INITIALIZED);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
mMachine.requestState(DOZE_PULSE_DONE);
@@ -119,7 +119,7 @@
public void testPulseDone_goesToAoD() {
when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
mMachine.requestState(INITIALIZED);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
mMachine.requestState(DOZE_PULSE_DONE);
@@ -163,7 +163,7 @@
public void testWakeLock_heldInPulseStates() {
mMachine.requestState(INITIALIZED);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
assertTrue(mWakeLockFake.isHeld());
mMachine.requestState(DOZE_PULSING);
@@ -186,7 +186,7 @@
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
mMachine.requestState(DOZE_PULSE_DONE);
@@ -198,9 +198,9 @@
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSE_DONE);
}
@@ -209,7 +209,7 @@
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSE_DONE);
}
@@ -235,7 +235,7 @@
public void testScreen_onInPulse() {
mMachine.requestState(INITIALIZED);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
assertEquals(Display.STATE_ON, mServiceFake.screenState);
@@ -246,7 +246,7 @@
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
assertEquals(Display.STATE_OFF, mServiceFake.screenState);
}
@@ -256,7 +256,7 @@
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE_AOD);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
}
@@ -270,12 +270,43 @@
return null;
}).when(mPartMock).transitionTo(any(), eq(DOZE_REQUEST_PULSE));
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
assertEquals(DOZE_PULSING, mMachine.getState());
}
@Test
+ public void testPulseReason_getMatchesRequest() {
+ mMachine.requestState(INITIALIZED);
+ mMachine.requestState(DOZE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP);
+
+ assertEquals(DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP, mMachine.getPulseReason());
+ }
+
+ @Test
+ public void testPulseReason_getFromTransition() {
+ mMachine.requestState(INITIALIZED);
+ mMachine.requestState(DOZE);
+ doAnswer(inv -> {
+ DozeMachine.State newState = inv.getArgument(1);
+ if (newState == DOZE_REQUEST_PULSE
+ || newState == DOZE_PULSING
+ || newState == DOZE_PULSE_DONE) {
+ assertEquals(DozeLog.PULSE_REASON_NOTIFICATION, mMachine.getPulseReason());
+ } else {
+ assertTrue("unexpected state " + newState,
+ newState == DOZE || newState == DOZE_AOD);
+ }
+ return null;
+ }).when(mPartMock).transitionTo(any(), any());
+
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
+ mMachine.requestState(DOZE_PULSING);
+ mMachine.requestState(DOZE_PULSE_DONE);
+ }
+
+ @Test
public void testWakeUp_wakesUp() {
mMachine.wakeUp();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 12e75a1..8934460 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -22,26 +22,28 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.withSettings;
import android.app.Instrumentation;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.WakeLock;
import com.android.systemui.util.wakelock.WakeLockFake;
+import com.android.systemui.utils.hardware.FakeSensorManager;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
-import org.mockito.Answers;
-import org.mockito.MockSettings;
+import org.junit.runner.RunWith;
+@SmallTest
+@RunWith(AndroidJUnit4.class)
public class DozeTriggersTest {
private Context mContext;
private DozeTriggers mTriggers;
@@ -49,7 +51,7 @@
private DozeHostFake mHost;
private AmbientDisplayConfiguration mConfig;
private DozeParameters mParameters;
- private SensorManagerFake mSensors;
+ private FakeSensorManager mSensors;
private Handler mHandler;
private WakeLock mWakeLock;
private Instrumentation mInstrumentation;
@@ -68,7 +70,7 @@
mHost = new DozeHostFake();
mConfig = DozeConfigurationUtil.createMockConfig();
mParameters = DozeConfigurationUtil.createMockParameters();
- mSensors = new SensorManagerFake(mContext);
+ mSensors = new FakeSensorManager(mContext);
mHandler = new Handler(Looper.getMainLooper());
mWakeLock = new WakeLockFake();
@@ -79,32 +81,32 @@
}
@Test
- @Ignore("setup crashes on virtual devices")
public void testOnNotification_stillWorksAfterOneFailedProxCheck() throws Exception {
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
mInstrumentation.runOnMainSync(()->{
mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
- mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.DOZE);
+ mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
mHost.callback.onNotificationHeadsUp();
});
mInstrumentation.runOnMainSync(() -> {
- mSensors.PROXIMITY.sendProximityResult(false); /* Near */
+ mSensors.getMockProximitySensor().sendProximityResult(false); /* Near */
});
verify(mMachine, never()).requestState(any());
+ verify(mMachine, never()).requestPulse(anyInt());
mInstrumentation.runOnMainSync(()->{
mHost.callback.onNotificationHeadsUp();
});
mInstrumentation.runOnMainSync(() -> {
- mSensors.PROXIMITY.sendProximityResult(true); /* Far */
+ mSensors.getMockProximitySensor().sendProximityResult(true); /* Far */
});
- verify(mMachine).requestState(DozeMachine.State.DOZE_REQUEST_PULSE);
+ verify(mMachine).requestPulse(anyInt());
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
new file mode 100644
index 0000000..ea14681
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+
+import android.graphics.drawable.VectorDrawable;
+import android.testing.AndroidTestingRunner;
+import android.view.View;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.ScrimView;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static junit.framework.Assert.assertEquals;
+
+@RunWith(AndroidTestingRunner.class)
+public class ScrimViewTest extends SysuiTestCase {
+
+ ScrimView mView;
+
+ @Before
+ public void setUp() {
+ mView = new ScrimView(getContext());
+ mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ mView.layout(0, 0, 1920, 1080);
+ }
+
+ @Test
+ public void testSetDrawable_UpdateDrawable() {
+ Drawable drawable = new ColorDrawable(Color.GREEN);
+ mView.setDrawable(drawable);
+ assertEquals(drawable, mView.getDrawable());
+ }
+
+ @Test
+ public void testSetViewAlpha_propagatesToDrawable() {
+ float alpha = 0.5f;
+ mView.setViewAlpha(alpha);
+ assertEquals(mView.getViewAlpha(), alpha);
+ }
+
+ @Test
+ public void testOnDraw_ExcludeRectDrawable() {
+ mView.setExcludedArea(new Rect(10, 10, 20, 20));
+ Canvas canvas = mock(Canvas.class);
+ mView.onDraw(canvas);
+ // One time for each rect side
+ verify(canvas, times(4)).clipRect(anyInt(), anyInt(), anyInt(), anyInt());
+ }
+
+ @Test
+ public void setTint_set() {
+ int tint = Color.BLUE;
+ mView.setTint(tint);
+ assertEquals(mView.getTint(), tint);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
new file mode 100644
index 0000000..564019c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.res.Configuration;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.util.Log;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.OverlayPlugin;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
+import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+@RunWith(AndroidTestingRunner.class)
+public class ExtensionControllerImplTest extends SysuiTestCase {
+
+ private PluginManager mPluginManager;
+ private TunerService mTunerService;
+ private ExtensionController mExtensionController;
+ private ConfigurationController mConfigurationController;
+
+ @Before
+ public void setup() {
+ mPluginManager = mDependency.injectMockDependency(PluginManager.class);
+ mTunerService = mDependency.injectMockDependency(TunerService.class);
+ mConfigurationController = mDependency.injectMockDependency(ConfigurationController.class);
+ mExtensionController = Dependency.get(ExtensionController.class);
+ }
+
+ @Test
+ public void testPlugin() {
+ OverlayPlugin plugin = mock(OverlayPlugin.class);
+
+ Extension ext = mExtensionController.newExtension(OverlayPlugin.class)
+ .withPlugin(OverlayPlugin.class)
+ .build();
+ ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class);
+ verify(mPluginManager).addPluginListener(eq(OverlayPlugin.ACTION), listener.capture(),
+ eq(OverlayPlugin.class));
+
+ listener.getValue().onPluginConnected(plugin, null);
+ assertEquals(plugin, ext.get());
+
+ ext.destroy();
+ verify(mPluginManager).removePluginListener(any());
+ }
+
+ @Test
+ public void testTuner() {
+ String[] keys = new String[] { "key1", "key2" };
+ TunerFactory<Object> factory = new ExtensionController.TunerFactory() {
+ @Override
+ public String[] keys() {
+ return keys;
+ }
+
+ @Override
+ public Object create(Map settings) {
+ return null;
+ }
+ };
+ Extension ext = mExtensionController.newExtension(Object.class)
+ .withTunerFactory(factory)
+ .build();
+ verify(mTunerService).addTunable(any(), eq(keys[0]), eq(keys[1]));
+
+ ext.destroy();
+ verify(mTunerService).removeTunable(any());
+ }
+
+ @Test
+ @RunWithLooper
+ public void testUiMode() {
+ Object o = new Object();
+ Extension ext = mExtensionController.newExtension(Object.class)
+ .withUiMode(Configuration.UI_MODE_TYPE_CAR, () -> o)
+ .build();
+ ArgumentCaptor<ConfigurationListener> captor = ArgumentCaptor.forClass(
+ ConfigurationListener.class);
+ verify(mConfigurationController).addCallback(captor.capture());
+
+ Configuration c = new Configuration(mContext.getResources().getConfiguration());
+ c.uiMode = 0;
+ captor.getValue().onConfigChanged(c);
+ TestableLooper.get(this).processAllMessages();
+ assertNull(ext.get());
+
+ c.uiMode = Configuration.UI_MODE_TYPE_CAR;
+ captor.getValue().onConfigChanged(c);
+ TestableLooper.get(this).processAllMessages();
+ assertEquals(o, ext.get());
+
+ ext.destroy();
+ verify(mConfigurationController).removeCallback(eq(captor.getValue()));
+ }
+
+ @Test
+ public void testDefault() {
+ Object o = new Object();
+ Extension ext = mExtensionController.newExtension(Object.class)
+ .withDefault(() -> o)
+ .build();
+ assertEquals(o, ext.get());
+ }
+
+ @Test
+ @RunWithLooper
+ public void testSortOrder() {
+ Log.d("TestTest", "Config " + mContext.getResources().getConfiguration().uiMode);
+ Object def = new Object();
+ Object uiMode = new Object();
+ Object tuner = new Object();
+ Plugin plugin = mock(Plugin.class);
+ TunerFactory<Object> factory = mock(TunerFactory.class);
+ Extension ext = mExtensionController.newExtension(Object.class)
+ .withDefault(() -> def)
+ .withUiMode(Configuration.UI_MODE_TYPE_CAR, () -> uiMode)
+ .withTunerFactory(factory)
+ .withPlugin(Object.class, "some_action")
+ .build();
+
+ // Test default first.
+ assertEquals(def, ext.get());
+
+ // Enable a UI mode and check that.
+ ArgumentCaptor<ConfigurationListener> captor = ArgumentCaptor.forClass(
+ ConfigurationListener.class);
+ verify(mConfigurationController).addCallback(captor.capture());
+ Configuration c = new Configuration(mContext.getResources().getConfiguration());
+ c.uiMode |= Configuration.UI_MODE_TYPE_CAR;
+ captor.getValue().onConfigChanged(c);
+ TestableLooper.get(this).processAllMessages();
+ assertEquals(uiMode, ext.get());
+
+ // Turn on tuner item and check that.
+ when(factory.create(any())).thenReturn(tuner);
+ ArgumentCaptor<Tunable> tunable = ArgumentCaptor.forClass(Tunable.class);
+ verify(mTunerService).addTunable(tunable.capture(), any());
+ tunable.getValue().onTuningChanged(null, null);
+ assertEquals(tuner, ext.get());
+
+ // Lastly, check a plugin.
+ ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class);
+ verify(mPluginManager).addPluginListener(any(), listener.capture(), any());
+ listener.getValue().onPluginConnected(plugin, null);
+ assertEquals(plugin, ext.get());
+ }
+
+ @Test
+ public void testCallback() {
+ Consumer<Object> callback = mock(Consumer.class);
+ final Object o = new Object();
+ mExtensionController.newExtension(Object.class)
+ .withDefault(() -> o)
+ .withCallback(callback)
+ .build();
+ verify(callback).accept(eq(o));
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
deleted file mode 100644
index 3e79a04..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
+++ /dev/null
@@ -1,105 +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 com.android.systemui.statusbar.policy;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.OverlayPlugin;
-import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.statusbar.policy.ExtensionController.Extension;
-import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
-import com.android.systemui.tuner.TunerService;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.Map;
-import java.util.function.Consumer;
-
-public class ExtensionControllerTest extends SysuiTestCase {
-
- private PluginManager mPluginManager;
- private TunerService mTunerService;
- private ExtensionController mExtensionController;
-
- @Before
- public void setup() {
- mPluginManager = mDependency.injectMockDependency(PluginManager.class);
- mTunerService = mDependency.injectMockDependency(TunerService.class);
- mExtensionController = Dependency.get(ExtensionController.class);
- }
-
- @Test
- public void testPlugin() {
- Extension ext = mExtensionController.newExtension(OverlayPlugin.class)
- .withPlugin(OverlayPlugin.class)
- .build();
- verify(mPluginManager).addPluginListener(eq(OverlayPlugin.ACTION), any(),
- eq(OverlayPlugin.class));
-
- ext.destroy();
- verify(mPluginManager).removePluginListener(any());
- }
-
- @Test
- public void testTuner() {
- String[] keys = new String[] { "key1", "key2" };
- TunerFactory<Object> factory = new ExtensionController.TunerFactory() {
- @Override
- public String[] keys() {
- return keys;
- }
-
- @Override
- public Object create(Map settings) {
- return null;
- }
- };
- Extension ext = mExtensionController.newExtension(Object.class)
- .withTunerFactory(factory)
- .build();
- verify(mTunerService).addTunable(any(), eq(keys[0]), eq(keys[1]));
-
- ext.destroy();
- verify(mTunerService).removeTunable(any());
- }
-
- @Test
- public void testDefault() {
- Object o = new Object();
- Extension ext = mExtensionController.newExtension(Object.class)
- .withDefault(() -> o)
- .build();
- assertEquals(o, ext.get());
- }
-
- @Test
- public void testCallback() {
- Consumer<Object> callback = mock(Consumer.class);
- final Object o = new Object();
- mExtensionController.newExtension(Object.class)
- .withDefault(() -> o)
- .withCallback(callback)
- .build();
- verify(callback).accept(eq(o));
- }
-
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/SensorManagerFake.java b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
similarity index 60%
rename from packages/SystemUI/tests/src/com/android/systemui/doze/SensorManagerFake.java
rename to packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
index 5b4b891..30be665 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/SensorManagerFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
@@ -11,10 +11,10 @@
* 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.
+ * limitations under the License
*/
-package com.android.systemui.doze;
+package com.android.systemui.utils.hardware;
import android.content.Context;
import android.hardware.HardwareBuffer;
@@ -33,6 +33,8 @@
import com.google.android.collect.Lists;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -44,18 +46,38 @@
* Note that this class ignores the "Handler" argument, so the test is responsible for calling the
* listener on the right thread.
*/
-public class SensorManagerFake extends SensorManager {
+public class FakeSensorManager extends SensorManager {
- public MockSensor PROXIMITY;
+ private final MockProximitySensor mMockProximitySensor;
- public SensorManagerFake(Context context) {
- PROXIMITY = new MockSensor(context.getSystemService(SensorManager.class)
- .getDefaultSensor(Sensor.TYPE_PROXIMITY));
+ public FakeSensorManager(Context context) throws Exception {
+ Sensor proxSensor = context.getSystemService(SensorManager.class)
+ .getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ if (proxSensor == null) {
+ // No prox? Let's create a fake one!
+ proxSensor = createSensor(Sensor.TYPE_PROXIMITY);
+ }
+ mMockProximitySensor = new MockProximitySensor(proxSensor);
+ }
+
+ public MockProximitySensor getMockProximitySensor() {
+ return mMockProximitySensor;
+ }
+
+ @Override
+ public Sensor getDefaultSensor(int type) {
+ Sensor s = super.getDefaultSensor(type);
+ if (s != null) {
+ return s;
+ }
+ // Our mock sensors aren't wakeup, and it's a pain to create them that way. Instead, just
+ // return non-wakeup sensors if we can't find a wakeup sensor.
+ return getDefaultSensor(type, false /* wakeup */);
}
@Override
protected List<Sensor> getFullSensorList() {
- return Lists.newArrayList(PROXIMITY.sensor);
+ return Lists.newArrayList(mMockProximitySensor.sensor);
}
@Override
@@ -65,8 +87,8 @@
@Override
protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
- if (sensor == PROXIMITY.sensor || sensor == null) {
- PROXIMITY.listeners.remove(listener);
+ if (sensor == mMockProximitySensor.sensor || sensor == null) {
+ mMockProximitySensor.listeners.remove(listener);
}
}
@@ -74,8 +96,8 @@
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
int delayUs,
Handler handler, int maxReportLatencyUs, int reservedFlags) {
- if (sensor == PROXIMITY.sensor) {
- PROXIMITY.listeners.add(listener);
+ if (sensor == mMockProximitySensor.sensor) {
+ mMockProximitySensor.listeners.add(listener);
return true;
}
return false;
@@ -141,11 +163,44 @@
return false;
}
- public class MockSensor {
+ private Sensor createSensor(int type) throws Exception {
+ Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
+ constr.setAccessible(true);
+ Sensor sensor = constr.newInstance();
+
+ setSensorType(sensor, type);
+ setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
+ setSensorField(sensor, "mVendor", "Mock Vendor");
+ setSensorField(sensor, "mVersion", 1);
+ setSensorField(sensor, "mHandle", -1);
+ setSensorField(sensor, "mMaxRange", 10);
+ setSensorField(sensor, "mResolution", 1);
+ setSensorField(sensor, "mPower", 1);
+ setSensorField(sensor, "mMinDelay", 1000);
+ setSensorField(sensor, "mMaxDelay", 1000000000);
+ setSensorField(sensor, "mFlags", 0);
+ setSensorField(sensor, "mId", -1);
+
+ return sensor;
+ }
+
+ private void setSensorField(Sensor sensor, String fieldName, Object value) throws Exception {
+ Field field = Sensor.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(sensor, value);
+ }
+
+ private void setSensorType(Sensor sensor, int type) throws Exception {
+ Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
+ setter.setAccessible(true);
+ setter.invoke(sensor, type);
+ }
+
+ public class MockProximitySensor {
final Sensor sensor;
final ArraySet<SensorEventListener> listeners = new ArraySet<>();
- private MockSensor(Sensor sensor) {
+ private MockProximitySensor(Sensor sensor) {
this.sensor = sensor;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
index b9d188a..3a0f907 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
@@ -14,6 +14,7 @@
package com.android.systemui.utils.leaks;
+import android.content.Context;
import android.testing.LeakCheck;
import android.testing.LeakCheck.Tracker;
@@ -75,6 +76,11 @@
}
@Override
+ public ExtensionBuilder<T> withUiMode(int mode, Supplier<T> def) {
+ return null;
+ }
+
+ @Override
public Extension build() {
return new FakeExtension(mAllocation);
}
@@ -94,8 +100,18 @@
}
@Override
+ public Context getContext() {
+ return null;
+ }
+
+ @Override
public void destroy() {
mTracker.getLeakInfo(mAllocation).clearAllocations();
}
+
+ @Override
+ public void addCallback(Consumer<T> callback) {
+
+ }
}
}
diff --git a/preloaded-classes b/preloaded-classes
index 892c593..493e980 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1820,6 +1820,7 @@
android.text.GetChars
android.text.GraphicsOperations
android.text.Html
+android.text.Html$HtmlParser
android.text.Hyphenator
android.text.InputFilter
android.text.InputType
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 53b3fe9..ac544e8 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -180,6 +180,9 @@
// Package: android
NOTE_FOREGROUND_SERVICES = 40;
+ // Inform the user that the connected audio accessory is not supported
+ NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED = 41;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/rs/java/android/renderscript/ScriptIntrinsicLUT.java b/rs/java/android/renderscript/ScriptIntrinsicLUT.java
index 69ff64a..e90462d 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicLUT.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicLUT.java
@@ -56,6 +56,10 @@
}
+ public void destroy() {
+ mTables.destroy();
+ super.destroy();
+ }
private void validate(int index, int value) {
if (index < 0 || index > 255) {
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index 4040db3..21438e0 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -18,7 +18,8 @@
libgui \
libjnigraphics
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_HEADER_LIBRARIES := \
+ libbase_headers
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index f6d3f48..ee48289 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -27,6 +27,7 @@
#include <androidfw/Asset.h>
#include <androidfw/AssetManager.h>
#include <androidfw/ResourceTypes.h>
+#include <android-base/macros.h>
#include "jni.h"
#include "JNIHelp.h"
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 2358ec5..b536ad9 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -603,15 +603,12 @@
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
boolean oldDebug = sDebug;
- boolean oldVerbose = sVerbose;
try {
synchronized (mLock) {
oldDebug = sDebug;
- oldVerbose = sVerbose;
setDebugLocked(true);
- setVerboseLocked(true);
pw.print("Debug mode: "); pw.println(oldDebug);
- pw.print("Verbose mode: "); pw.println(oldVerbose);
+ pw.print("Verbose mode: "); pw.println(sVerbose);
pw.print("Disabled users: "); pw.println(mDisabledUsers);
final int size = mServicesCache.size();
pw.print("Cached services: ");
@@ -631,7 +628,6 @@
mRequestsHistory.reverseDump(fd, pw, args);
} finally {
setDebugLocked(oldDebug);
- setVerboseLocked(oldVerbose);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 68ade63..cbf97dd 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -20,7 +20,9 @@
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.os.Bundle;
+import android.util.DebugUtils;
import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
import java.util.Arrays;
import java.util.Objects;
@@ -40,6 +42,10 @@
*/
public static boolean sVerbose = false;
+ private Helper() {
+ throw new UnsupportedOperationException("contains static members only");
+ }
+
static void append(StringBuilder builder, Bundle bundle) {
if (bundle == null || !sVerbose) {
builder.append("null");
@@ -62,8 +68,8 @@
return builder.toString();
}
- private Helper() {
- throw new UnsupportedOperationException("contains static members only");
+ static String getUpdateActionAsString(int action) {
+ return DebugUtils.flagsToString(AutofillManager.class, "ACTION_", action);
}
static ViewNode findViewNodeById(@NonNull AssistStructure structure, @NonNull AutofillId id) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index c85ce43..23b734a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -25,9 +25,13 @@
import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
+import static com.android.server.autofill.Helper.findViewNodeById;
+import static com.android.server.autofill.Helper.getUpdateActionAsString;
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;
-import static com.android.server.autofill.Helper.findViewNodeById;
+import static com.android.server.autofill.ViewState.STATE_AUTOFILLED;
+import static com.android.server.autofill.ViewState.STATE_FILLABLE;
+import static com.android.server.autofill.ViewState.STATE_RESTARTED_SESSION;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -221,7 +225,7 @@
final int numContexts = mContexts.size();
for (int i = 0; i < numContexts; i++) {
- fillStructureWithAllowedValues(mContexts.get(i).getStructure());
+ fillStructureWithAllowedValues(mContexts.get(i).getStructure(), flags);
}
request = new FillRequest(requestId, mContexts, mClientState, flags);
@@ -235,10 +239,12 @@
* Updates values of the nodes in the structure so that:
* - proper node is focused
* - autofillValue is sent back to service when it was previously autofilled
+ * - autofillValue is sent in the view used to force a request
*
* @param structure The structure to be filled
+ * @param flags The flags that started the session
*/
- private void fillStructureWithAllowedValues(@NonNull AssistStructure structure) {
+ private void fillStructureWithAllowedValues(@NonNull AssistStructure structure, int flags) {
final int numViewStates = mViewStates.size();
for (int i = 0; i < numViewStates; i++) {
final ViewState viewState = mViewStates.valueAt(i);
@@ -249,16 +255,23 @@
continue;
}
- final AutofillValue initialValue = viewState.getInitialValue();
+ final AutofillValue currentValue = viewState.getCurrentValue();
final AutofillValue filledValue = viewState.getAutofilledValue();
final AutofillOverlay overlay = new AutofillOverlay();
- if (filledValue != null && !filledValue.equals(initialValue)) {
- overlay.value = filledValue;
- }
- if (mCurrentViewId != null) {
- overlay.focused = mCurrentViewId.equals(viewState.id);
+
+ // Sanitizes the value if the current value matches what the service sent.
+ if (filledValue != null && filledValue.equals(currentValue)) {
+ overlay.value = currentValue;
}
+ if (mCurrentViewId != null) {
+ // Updates the focus value.
+ overlay.focused = mCurrentViewId.equals(viewState.id);
+ // Sanitizes the value of the focused field in a manual request.
+ if (overlay.focused && (flags & FLAG_MANUAL_REQUEST) != 0) {
+ overlay.value = currentValue;
+ }
+ }
node.setAutofillOverlay(overlay);
}
}
@@ -883,6 +896,40 @@
}
/**
+ * Starts (if necessary) a new fill request upon entering a view.
+ *
+ * <p>A new request will be started in 2 scenarios:
+ * <ol>
+ * <li>If the user manually requested autofill after the view was already filled.
+ * <li>If the view is part of a new partition.
+ * </ol>
+ *
+ * @param id The id of the view that is entered.
+ * @param viewState The view that is entered.
+ * @param flags The flag that was passed by the AutofillManager.
+ */
+ private void requestNewFillResponseIfNecessaryLocked(@NonNull AutofillId id,
+ @NonNull ViewState viewState, int flags) {
+ // First check if this is a manual request after view was autofilled.
+ final int state = viewState.getState();
+ final boolean restart = (state & STATE_AUTOFILLED) != 0
+ && (flags & FLAG_MANUAL_REQUEST) != 0;
+ if (restart) {
+ if (sDebug) Slog.d(TAG, "Re-starting session on view " + id);
+ viewState.setState(STATE_RESTARTED_SESSION);
+ requestNewFillResponseLocked(flags);
+ return;
+ }
+
+ // If it's not, then check if it it should start a partition.
+ if (shouldStartNewPartitionLocked(id)) {
+ if (sDebug) Slog.d(TAG, "Starting partition for view id " + id);
+ viewState.setState(ViewState.STATE_STARTED_PARTITION);
+ requestNewFillResponseLocked(flags);
+ }
+ }
+
+ /**
* Determines if a new partition should be started for an id.
*
* @param id The id of the view that is entered
@@ -922,6 +969,10 @@
}
}
}
+
+ if (ArrayUtils.contains(response.getAuthenticationIds(), id)) {
+ return false;
+ }
}
return true;
@@ -934,6 +985,10 @@
+ id + " destroyed");
return;
}
+ if (sVerbose) {
+ Slog.v(TAG, "updateLocked(): id=" + id + ", action=" + getUpdateActionAsString(action)
+ + ", flags=" + flags);
+ }
ViewState viewState = mViewStates.get(id);
if (viewState == null) {
@@ -943,8 +998,14 @@
Slog.v(TAG,
"Creating viewState for " + id + " on " + getActionAsString(action));
}
- viewState = new ViewState(this, id, value, this, ViewState.STATE_INITIAL);
+ boolean isIgnored = isIgnoredLocked(id);
+ viewState = new ViewState(this, id, value, this,
+ isIgnored ? ViewState.STATE_IGNORED : ViewState.STATE_INITIAL);
mViewStates.put(id, viewState);
+ if (isIgnored) {
+ if (sDebug) Slog.d(TAG, "updateLocked(): ignoring view " + id);
+ return;
+ }
} else {
if (sVerbose) Slog.v(TAG, "Ignored " + getActionAsString(action) + " for " + id);
return;
@@ -982,18 +1043,7 @@
}
break;
case ACTION_VIEW_ENTERED:
- if (shouldStartNewPartitionLocked(id)) {
- // TODO(b/37424539): proper implementation
- if (mResponseWaitingAuth != null) {
- viewState.setState(ViewState.STATE_WAITING_RESPONSE_AUTH);
- } else {
- if (sDebug) {
- Slog.d(TAG, "Starting partition for view id " + viewState.id);
- }
- viewState.setState(ViewState.STATE_STARTED_PARTITION);
- requestNewFillResponseLocked(flags);
- }
- }
+ requestNewFillResponseIfNecessaryLocked(id, viewState, flags);
// Remove the UI if the ViewState has changed.
if (mCurrentViewId != viewState.id) {
@@ -1015,6 +1065,18 @@
}
}
+ /**
+ * Checks whether a view should be ignored.
+ */
+ private boolean isIgnoredLocked(AutofillId id) {
+ if (mResponses == null || mResponses.size() == 0) {
+ return false;
+ }
+ // Always check the latest response only
+ final FillResponse response = mResponses.valueAt(mResponses.size() - 1);
+ return ArrayUtils.contains(response.getIgnoredIds(), id);
+ }
+
@Override
public void onFillReady(FillResponse response, AutofillId filledId,
@Nullable AutofillValue value) {
@@ -1149,18 +1211,24 @@
final SaveInfo saveInfo = response.getSaveInfo();
if (saveInfo != null) {
final AutofillId[] requiredIds = saveInfo.getRequiredIds();
- for (int i = 0; i < requiredIds.length; i++) {
- final AutofillId id = requiredIds[i];
+ for (AutofillId id : requiredIds) {
createOrUpdateViewStateLocked(id, state, null);
}
final AutofillId[] optionalIds = saveInfo.getOptionalIds();
if (optionalIds != null) {
- for (int i = 0; i < optionalIds.length; i++) {
- final AutofillId id = optionalIds[i];
+ for (AutofillId id : optionalIds) {
createOrUpdateViewStateLocked(id, state, null);
}
}
}
+
+ final AutofillId[] authIds = response.getAuthenticationIds();
+ if (authIds != null) {
+ for (AutofillId id : authIds) {
+ createOrUpdateViewStateLocked(id, state, null);
+ }
+ }
+
}
/**
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 7ca9435..561c603 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -17,6 +17,7 @@
package com.android.server.autofill;
import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.Nullable;
import android.graphics.Rect;
@@ -46,23 +47,25 @@
private static final String TAG = "ViewState";
// NOTE: state constants must be public because of flagstoString().
- public static final int STATE_UNKNOWN = 0x00;
+ public static final int STATE_UNKNOWN = 0x000;
/** Initial state. */
- public static final int STATE_INITIAL = 0x01;
+ public static final int STATE_INITIAL = 0x001;
/** View id is present in a dataset returned by the service. */
- public static final int STATE_FILLABLE = 0x02;
+ public static final int STATE_FILLABLE = 0x002;
/** View was autofilled after user selected a dataset. */
- public static final int STATE_AUTOFILLED = 0x04;
+ public static final int STATE_AUTOFILLED = 0x004;
/** View value was changed, but not by the service. */
- public static final int STATE_CHANGED = 0x08;
+ public static final int STATE_CHANGED = 0x008;
/** Set only in the View that started a session. */
- public static final int STATE_STARTED_SESSION = 0x10;
+ public static final int STATE_STARTED_SESSION = 0x010;
/** View that started a new partition when focused on. */
- public static final int STATE_STARTED_PARTITION = 0x20;
+ public static final int STATE_STARTED_PARTITION = 0x020;
/** User select a dataset in this view, but service must authenticate first. */
- public static final int STATE_WAITING_DATASET_AUTH = 0x40;
- // TODO(b/37424539): temporary workaround until partitioning supports auth
- public static final int STATE_WAITING_RESPONSE_AUTH = 0x80;
+ public static final int STATE_WAITING_DATASET_AUTH = 0x040;
+ /** Service does not care about this view. */
+ public static final int STATE_IGNORED = 0x080;
+ /** User manually request autofill in this view, after it was already autofilled. */
+ public static final int STATE_RESTARTED_SESSION = 0x100;
public final AutofillId id;
@@ -199,7 +202,16 @@
void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("id:" ); pw.println(this.id);
pw.print(prefix); pw.print("state:" ); pw.println(getStateAsString());
- pw.print(prefix); pw.print("has response:" ); pw.println(mResponse != null);
+ pw.print(prefix); pw.print("response:");
+ if (mResponse == null) {
+ pw.println("N/A");
+ } else {
+ if (sVerbose) {
+ pw.println(mResponse);
+ } else {
+ pw.println(mResponse.getRequestId());
+ }
+ }
pw.print(prefix); pw.print("initialValue:" ); pw.println(mInitialValue);
pw.print(prefix); pw.print("currentValue:" ); pw.println(mCurrentValue);
pw.print(prefix); pw.print("autofilledValue:" ); pw.println(mAutofilledValue);
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index fa95e03..dd297a6 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -23,10 +23,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.graphics.Point;
import android.graphics.Rect;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.util.Slog;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -52,6 +54,8 @@
private static final int VISIBLE_OPTIONS_MAX_COUNT = 3;
+ private static final TypedValue sTempTypedValue = new TypedValue();
+
interface Callback {
void onResponsePicked(@NonNull FillResponse response);
void onDatasetPicked(@NonNull Dataset dataset);
@@ -63,9 +67,13 @@
void startIntentSender(IntentSender intentSender);
}
+ private final @NonNull Point mTempPoint = new Point();
+
private final @NonNull AutofillWindowPresenter mWindowPresenter =
new AutofillWindowPresenter();
+ private final @NonNull Context mContext;
+
private final @NonNull AnchoredWindow mWindow;
private final @NonNull Callback mCallback;
@@ -84,6 +92,7 @@
FillUi(@NonNull Context context, @NonNull FillResponse response,
@NonNull AutofillId focusedViewId, @NonNull @Nullable String filterText,
@NonNull Callback callback) {
+ mContext = context;
mCallback = callback;
final LayoutInflater inflater = LayoutInflater.from(context);
@@ -115,13 +124,18 @@
mWindow = null;
return;
}
- final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- content.measure(widthMeasureSpec, heightMeasureSpec);
+
+ Point maxSize = mTempPoint;
+ resolveMaxWindowSize(context, maxSize);
+ final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.x,
+ MeasureSpec.AT_MOST);
+ final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
+ MeasureSpec.AT_MOST);
+
+ decor.measure(widthMeasureSpec, heightMeasureSpec);
decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
- // TODO(b/37567439): temporary limiting maximum height and minimum width
- mContentWidth = Math.max(content.getMeasuredWidth(), 1000);
- mContentHeight = Math.min(content.getMeasuredHeight(), 500);
+ mContentWidth = content.getMeasuredWidth();
+ mContentHeight = content.getMeasuredHeight();
mWindow = new AnchoredWindow(decor);
mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
@@ -245,6 +259,9 @@
return changed;
}
+ Point maxSize = mTempPoint;
+ resolveMaxWindowSize(mContext, maxSize);
+
mContentWidth = 0;
mContentHeight = 0;
@@ -254,12 +271,14 @@
for (int i = 0; i < itemCount; i++) {
View view = mAdapter.getItem(i).getView();
view.measure(widthMeasureSpec, heightMeasureSpec);
- final int newContentWidth = Math.max(mContentWidth, view.getMeasuredWidth());
+ final int clampedMeasuredWidth = Math.min(view.getMeasuredWidth(), maxSize.x);
+ final int newContentWidth = Math.max(mContentWidth, clampedMeasuredWidth);
if (newContentWidth != mContentWidth) {
mContentWidth = newContentWidth;
changed = true;
}
- final int newContentHeight = mContentHeight + view.getMeasuredHeight();
+ final int clampedMeasuredHeight = Math.min(view.getMeasuredHeight(), maxSize.y);
+ final int newContentHeight = mContentHeight + clampedMeasuredHeight;
if (newContentHeight != mContentHeight) {
mContentHeight = newContentHeight;
changed = true;
@@ -274,6 +293,17 @@
}
}
+ private static void resolveMaxWindowSize(Context context, Point outPoint) {
+ context.getDisplay().getSize(outPoint);
+ TypedValue typedValue = sTempTypedValue;
+ context.getTheme().resolveAttribute(R.attr.autofillDatasetPickerMaxWidth,
+ typedValue, true);
+ outPoint.x = (int) typedValue.getFraction(outPoint.x, outPoint.x);
+ context.getTheme().resolveAttribute(R.attr.autofillDatasetPickerMaxHeight,
+ typedValue, true);
+ outPoint.y = (int) typedValue.getFraction(outPoint.y, outPoint.y);
+ }
+
private static class ViewItem {
private final String mValue;
private final Dataset mDataset;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 04a54a7..dd0b33d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2393,7 +2393,7 @@
long token = mAncestralToken;
synchronized (mQueueLock) {
- if (mEverStoredApps.contains(packageName)) {
+ if (mCurrentToken != 0 && mEverStoredApps.contains(packageName)) {
if (MORE_DEBUG) {
Slog.i(TAG, "App in ever-stored, so using current token");
}
@@ -3866,9 +3866,14 @@
writeApkToBackup(mPackage, output);
}
+ final boolean isSharedStorage =
+ mPackage.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
+ final long timeout = isSharedStorage ?
+ TIMEOUT_SHARED_BACKUP_INTERVAL : TIMEOUT_FULL_BACKUP_INTERVAL;
+
if (DEBUG) Slog.d(TAG, "Calling doFullBackup() on " + mPackage.packageName);
- prepareOperationTimeout(mToken, TIMEOUT_FULL_BACKUP_INTERVAL,
- mTimeoutMonitor /* in parent class */, OP_TYPE_BACKUP_WAIT);
+ prepareOperationTimeout(mToken, timeout, mTimeoutMonitor /* in parent class */,
+ OP_TYPE_BACKUP_WAIT);
mAgent.doFullBackup(mPipe, mQuota, mToken, mBackupManagerBinder);
} catch (IOException e) {
Slog.e(TAG, "Error running full backup for " + mPackage.packageName);
@@ -7554,9 +7559,12 @@
if (okay) {
boolean agentSuccess = true;
long toCopy = info.size;
+ final boolean isSharedStorage = pkg.equals(SHARED_BACKUP_AGENT_PACKAGE);
+ final long timeout = isSharedStorage ?
+ TIMEOUT_SHARED_BACKUP_INTERVAL : TIMEOUT_RESTORE_INTERVAL;
final int token = generateRandomIntegerToken();
try {
- prepareOperationTimeout(token, TIMEOUT_RESTORE_INTERVAL, null,
+ prepareOperationTimeout(token, timeout, null,
OP_TYPE_RESTORE_WAIT);
if (FullBackup.OBB_TREE_TOKEN.equals(info.domain)) {
if (DEBUG) Slog.d(TAG, "Restoring OBB file for " + pkg
@@ -10448,8 +10456,7 @@
final long oldId = Binder.clearCallingIdentity();
try {
String prevTransport = mTransportManager.selectTransport(transport);
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.BACKUP_TRANSPORT, transport);
+ updateStateForTransport(transport);
Slog.v(TAG, "selectBackupTransport() set " + mTransportManager.getCurrentTransportName()
+ " returning " + prevTransport);
return prevTransport;
@@ -10473,9 +10480,7 @@
@Override
public void onSuccess(String transportName) {
mTransportManager.selectTransport(transportName);
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.BACKUP_TRANSPORT,
- mTransportManager.getCurrentTransportName());
+ updateStateForTransport(mTransportManager.getCurrentTransportName());
Slog.v(TAG, "Transport successfully selected: " + transport.flattenToShortString());
try {
listener.onSuccess(transportName);
@@ -10498,6 +10503,28 @@
Binder.restoreCallingIdentity(oldId);
}
+ private void updateStateForTransport(String newTransportName) {
+ // Publish the name change
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.BACKUP_TRANSPORT, newTransportName);
+
+ // And update our current-dataset bookkeeping
+ IBackupTransport transport = mTransportManager.getTransportBinder(newTransportName);
+ if (transport != null) {
+ try {
+ mCurrentToken = transport.getCurrentRestoreSet();
+ } catch (Exception e) {
+ // Oops. We can't know the current dataset token, so reset and figure it out
+ // when we do the next k/v backup operation on this transport.
+ mCurrentToken = 0;
+ }
+ } else {
+ // The named transport isn't bound at this particular moment, so we can't
+ // know yet what its current dataset token is. Reset as above.
+ mCurrentToken = 0;
+ }
+ }
+
// Supply the configuration Intent for the given transport. If the name is not one
// of the available transports, or if the transport does not supply any configuration
// UI, the method returns null.
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index 151354b..811b741 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -18,6 +18,22 @@
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
+import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT;
+import static com.android.server.backup.internal.BackupHandler.MSG_FULL_CONFIRMATION_TIMEOUT;
+import static com.android.server.backup.internal.BackupHandler.MSG_OP_COMPLETE;
+import static com.android.server.backup.internal.BackupHandler.MSG_REQUEST_BACKUP;
+import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
+import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
+import static com.android.server.backup.internal.BackupHandler.MSG_RETRY_CLEAR;
+import static com.android.server.backup.internal.BackupHandler.MSG_RETRY_INIT;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_BACKUP;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_RESTORE;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_BACKUP;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_CLEAR;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_INITIALIZE;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
+import static com.android.server.backup.internal.BackupHandler.MSG_SCHEDULE_BACKUP_PACKAGE;
+
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AppGlobals;
@@ -189,27 +205,6 @@
public static final String RUN_BACKUP_ACTION = "android.app.backup.intent.RUN";
public static final String RUN_INITIALIZE_ACTION = "android.app.backup.intent.INIT";
- public static final int MSG_RUN_BACKUP = 1;
- public static final int MSG_RUN_ADB_BACKUP = 2;
- public static final int MSG_RUN_RESTORE = 3;
- public static final int MSG_RUN_CLEAR = 4;
- public static final int MSG_RUN_INITIALIZE = 5;
- public static final int MSG_RUN_GET_RESTORE_SETS = 6;
- public static final int MSG_RESTORE_SESSION_TIMEOUT = 8;
- public static final int MSG_FULL_CONFIRMATION_TIMEOUT = 9;
- public static final int MSG_RUN_ADB_RESTORE = 10;
- public static final int MSG_RETRY_INIT = 11;
- public static final int MSG_RETRY_CLEAR = 12;
- public static final int MSG_WIDGET_BROADCAST = 13;
- public static final int MSG_RUN_FULL_TRANSPORT_BACKUP = 14;
- public static final int MSG_REQUEST_BACKUP = 15;
- public static final int MSG_SCHEDULE_BACKUP_PACKAGE = 16;
- public static final int MSG_BACKUP_OPERATION_TIMEOUT = 17;
- public static final int MSG_RESTORE_OPERATION_TIMEOUT = 18;
-
- // backup task state machine tick
- public static final int MSG_BACKUP_RESTORE_STEP = 20;
- public static final int MSG_OP_COMPLETE = 21;
// Timeout interval for deciding that a bind or clear-data has taken too long
private static final long TIMEOUT_INTERVAL = 10 * 1000;
@@ -217,7 +212,7 @@
// Timeout intervals for agent backup & restore operations
public static final long TIMEOUT_BACKUP_INTERVAL = 30 * 1000;
public static final long TIMEOUT_FULL_BACKUP_INTERVAL = 5 * 60 * 1000;
- private static final long TIMEOUT_SHARED_BACKUP_INTERVAL = 30 * 60 * 1000;
+ public static final long TIMEOUT_SHARED_BACKUP_INTERVAL = 30 * 60 * 1000;
public static final long TIMEOUT_RESTORE_INTERVAL = 60 * 1000;
public static final long TIMEOUT_RESTORE_FINISHED_INTERVAL = 30 * 1000;
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 0fd0ea5..1e56e95 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -356,6 +356,8 @@
BackupManagerServiceInterface svc = mService;
if (svc != null) {
svc.selectBackupTransportAsync(transport, listener);
+ } else {
+ listener.onFailure(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
}
}
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 90caae8..fb2982e 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -182,13 +182,13 @@
String[] getBoundTransportNames() {
synchronized (mTransportLock) {
- return mBoundTransports.keySet().toArray(new String[0]);
+ return mBoundTransports.keySet().toArray(new String[mBoundTransports.size()]);
}
}
ComponentName[] getAllTransportCompenents() {
synchronized (mTransportLock) {
- return mValidTransports.keySet().toArray(new ComponentName[0]);
+ return mValidTransports.keySet().toArray(new ComponentName[mValidTransports.size()]);
}
}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index 72eeea0..47ae206 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -120,13 +120,20 @@
writeApkToBackup(mPackage, output);
}
+ final boolean isSharedStorage =
+ mPackage.packageName.equals(
+ RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE);
+ final long timeout = isSharedStorage ?
+ RefactoredBackupManagerService.TIMEOUT_SHARED_BACKUP_INTERVAL :
+ RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
+
if (RefactoredBackupManagerService.DEBUG) {
Slog.d(RefactoredBackupManagerService.TAG,
"Calling doFullBackup() on " + mPackage.packageName);
}
backupManagerService
.prepareOperationTimeout(mToken,
- RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+ timeout,
mTimeoutMonitor /* in parent class */,
RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
mAgent.doFullBackup(mPipe, mQuota, mToken,
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index a976146..c83041b 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -55,6 +55,27 @@
*/
public class BackupHandler extends Handler {
+ public static final int MSG_RUN_BACKUP = 1;
+ public static final int MSG_RUN_ADB_BACKUP = 2;
+ public static final int MSG_RUN_RESTORE = 3;
+ public static final int MSG_RUN_CLEAR = 4;
+ public static final int MSG_RUN_INITIALIZE = 5;
+ public static final int MSG_RUN_GET_RESTORE_SETS = 6;
+ public static final int MSG_RESTORE_SESSION_TIMEOUT = 8;
+ public static final int MSG_FULL_CONFIRMATION_TIMEOUT = 9;
+ public static final int MSG_RUN_ADB_RESTORE = 10;
+ public static final int MSG_RETRY_INIT = 11;
+ public static final int MSG_RETRY_CLEAR = 12;
+ public static final int MSG_WIDGET_BROADCAST = 13;
+ public static final int MSG_RUN_FULL_TRANSPORT_BACKUP = 14;
+ public static final int MSG_REQUEST_BACKUP = 15;
+ public static final int MSG_SCHEDULE_BACKUP_PACKAGE = 16;
+ public static final int MSG_BACKUP_OPERATION_TIMEOUT = 17;
+ public static final int MSG_RESTORE_OPERATION_TIMEOUT = 18;
+ // backup task state machine tick
+ public static final int MSG_BACKUP_RESTORE_STEP = 20;
+ public static final int MSG_OP_COMPLETE = 21;
+
private RefactoredBackupManagerService backupManagerService;
public BackupHandler(
@@ -66,7 +87,7 @@
public void handleMessage(Message msg) {
switch (msg.what) {
- case RefactoredBackupManagerService.MSG_RUN_BACKUP: {
+ case MSG_RUN_BACKUP: {
backupManagerService.setLastBackupPass(System.currentTimeMillis());
IBackupTransport transport =
@@ -117,8 +138,7 @@
backupManagerService, transport, dirName, queue,
oldJournal, null, null, Collections.<String>emptyList(), false,
false /* nonIncremental */);
- Message pbtMessage = obtainMessage(
- RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, pbt);
+ Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
sendMessage(pbtMessage);
} catch (Exception e) {
// unable to ask the transport its dir name -- transient failure, since
@@ -144,7 +164,7 @@
break;
}
- case RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP: {
+ case MSG_BACKUP_RESTORE_STEP: {
try {
BackupRestoreTask task = (BackupRestoreTask) msg.obj;
if (RefactoredBackupManagerService.MORE_DEBUG) {
@@ -159,7 +179,7 @@
break;
}
- case RefactoredBackupManagerService.MSG_OP_COMPLETE: {
+ case MSG_OP_COMPLETE: {
try {
Pair<BackupRestoreTask, Long> taskWithResult =
(Pair<BackupRestoreTask, Long>) msg.obj;
@@ -171,7 +191,7 @@
break;
}
- case RefactoredBackupManagerService.MSG_RUN_ADB_BACKUP: {
+ case MSG_RUN_ADB_BACKUP: {
// TODO: refactor full backup to be a looper-based state machine
// similar to normal backup/restore.
AdbBackupParams params = (AdbBackupParams) msg.obj;
@@ -185,13 +205,13 @@
break;
}
- case RefactoredBackupManagerService.MSG_RUN_FULL_TRANSPORT_BACKUP: {
+ case MSG_RUN_FULL_TRANSPORT_BACKUP: {
PerformFullTransportBackupTask task = (PerformFullTransportBackupTask) msg.obj;
(new Thread(task, "transport-backup")).start();
break;
}
- case RefactoredBackupManagerService.MSG_RUN_RESTORE: {
+ case MSG_RUN_RESTORE: {
RestoreParams params = (RestoreParams) msg.obj;
Slog.d(RefactoredBackupManagerService.TAG,
"MSG_RUN_RESTORE observer=" + params.observer);
@@ -215,15 +235,14 @@
Slog.d(RefactoredBackupManagerService.TAG, "Starting restore.");
}
backupManagerService.setRestoreInProgress(true);
- Message restoreMsg = obtainMessage(
- RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, task);
+ Message restoreMsg = obtainMessage(MSG_BACKUP_RESTORE_STEP, task);
sendMessage(restoreMsg);
}
}
break;
}
- case RefactoredBackupManagerService.MSG_RUN_ADB_RESTORE: {
+ case MSG_RUN_ADB_RESTORE: {
// TODO: refactor full restore to be a looper-based state machine
// similar to normal backup/restore.
AdbRestoreParams params = (AdbRestoreParams) msg.obj;
@@ -235,21 +254,21 @@
break;
}
- case RefactoredBackupManagerService.MSG_RUN_CLEAR: {
+ case MSG_RUN_CLEAR: {
ClearParams params = (ClearParams) msg.obj;
(new PerformClearTask(backupManagerService, params.transport,
params.packageInfo)).run();
break;
}
- case RefactoredBackupManagerService.MSG_RETRY_CLEAR: {
+ case MSG_RETRY_CLEAR: {
// reenqueues if the transport remains unavailable
ClearRetryParams params = (ClearRetryParams) msg.obj;
backupManagerService.clearBackupData(params.transportName, params.packageName);
break;
}
- case RefactoredBackupManagerService.MSG_RUN_INITIALIZE: {
+ case MSG_RUN_INITIALIZE: {
HashSet<String> queue;
// Snapshot the pending-init queue and work on that
@@ -262,7 +281,7 @@
break;
}
- case RefactoredBackupManagerService.MSG_RETRY_INIT: {
+ case MSG_RETRY_INIT: {
synchronized (backupManagerService.getQueueLock()) {
backupManagerService.recordInitPendingLocked(msg.arg1 != 0, (String) msg.obj);
backupManagerService.getAlarmManager().set(AlarmManager.RTC_WAKEUP,
@@ -272,7 +291,7 @@
break;
}
- case RefactoredBackupManagerService.MSG_RUN_GET_RESTORE_SETS: {
+ case MSG_RUN_GET_RESTORE_SETS: {
// Like other async operations, this is entered with the wakelock held
RestoreSet[] sets = null;
RestoreGetSetsParams params = (RestoreGetSetsParams) msg.obj;
@@ -302,9 +321,9 @@
}
// Done: reset the session timeout clock
- removeMessages(RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+ removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
sendEmptyMessageDelayed(
- RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT,
+ MSG_RESTORE_SESSION_TIMEOUT,
RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL);
backupManagerService.getWakelock().release();
@@ -312,15 +331,15 @@
break;
}
- case RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT:
- case RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT: {
+ case MSG_BACKUP_OPERATION_TIMEOUT:
+ case MSG_RESTORE_OPERATION_TIMEOUT: {
Slog.d(RefactoredBackupManagerService.TAG,
"Timeout message received for token=" + Integer.toHexString(msg.arg1));
backupManagerService.handleCancel(msg.arg1, false);
break;
}
- case RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT: {
+ case MSG_RESTORE_SESSION_TIMEOUT: {
synchronized (backupManagerService) {
if (backupManagerService.getActiveRestoreSession() != null) {
// Client app left the restore session dangling. We know that it
@@ -338,7 +357,7 @@
break;
}
- case RefactoredBackupManagerService.MSG_FULL_CONFIRMATION_TIMEOUT: {
+ case MSG_FULL_CONFIRMATION_TIMEOUT: {
synchronized (backupManagerService.getAdbBackupRestoreConfirmations()) {
AdbParams params = backupManagerService.getAdbBackupRestoreConfirmations().get(
msg.arg1);
@@ -368,13 +387,13 @@
break;
}
- case RefactoredBackupManagerService.MSG_WIDGET_BROADCAST: {
+ case MSG_WIDGET_BROADCAST: {
final Intent intent = (Intent) msg.obj;
backupManagerService.getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
break;
}
- case RefactoredBackupManagerService.MSG_REQUEST_BACKUP: {
+ case MSG_REQUEST_BACKUP: {
BackupParams params = (BackupParams) msg.obj;
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.d(RefactoredBackupManagerService.TAG,
@@ -392,13 +411,12 @@
params.transport, params.dirName,
kvQueue, null, params.observer, params.monitor, params.fullPackages, true,
params.nonIncrementalBackup);
- Message pbtMessage = obtainMessage(
- RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, pbt);
+ Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
sendMessage(pbtMessage);
break;
}
- case RefactoredBackupManagerService.MSG_SCHEDULE_BACKUP_PACKAGE: {
+ case MSG_SCHEDULE_BACKUP_PACKAGE: {
String pkgName = (String) msg.obj;
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.d(RefactoredBackupManagerService.TAG,
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index d757dbe..51c3451 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -16,6 +16,9 @@
package com.android.server.backup.internal;
+import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT;
+import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
+
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
import android.app.backup.BackupDataInput;
@@ -322,7 +325,7 @@
// backup callback and returned. Blow away the lingering (spurious)
// pending timeout message for it.
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT);
+ MSG_BACKUP_OPERATION_TIMEOUT);
}
}
@@ -846,8 +849,7 @@
BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY,
key));
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService
- .MSG_BACKUP_OPERATION_TIMEOUT);
+ MSG_BACKUP_OPERATION_TIMEOUT);
BackupObserverUtils
.sendBackupOnPackageResult(mObserver, pkgName,
BackupManager.ERROR_AGENT_FAILURE);
@@ -885,8 +887,7 @@
"operationComplete(): sending data to transport for "
+ pkgName);
}
- backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT);
+ backupManagerService.getBackupHandler().removeMessages(MSG_BACKUP_OPERATION_TIMEOUT);
clearAgentState();
backupManagerService.addBackupTrace("operation complete");
@@ -1115,7 +1116,7 @@
backupManagerService.addBackupTrace("executeNextState => " + nextState);
mCurrentState = nextState;
Message msg = backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
+ MSG_BACKUP_RESTORE_STEP, this);
backupManagerService.getBackupHandler().sendMessage(msg);
}
}
diff --git a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
index 4276b25..2372a19 100644
--- a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
@@ -16,6 +16,8 @@
package com.android.server.backup.internal;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_BACKUP;
+
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -66,7 +68,7 @@
backupManagerService.getWakelock().acquire();
Message msg = backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_RUN_BACKUP);
+ MSG_RUN_BACKUP);
backupManagerService.getBackupHandler().sendMessage(msg);
} else {
Slog.i(RefactoredBackupManagerService.TAG,
diff --git a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
index c995b09..6609900 100644
--- a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
@@ -16,6 +16,8 @@
package com.android.server.backup.internal;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_INITIALIZE;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -44,7 +46,7 @@
backupManagerService.getWakelock().acquire();
Message msg = backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_RUN_INITIALIZE);
+ MSG_RUN_INITIALIZE);
backupManagerService.getBackupHandler().sendMessage(msg);
}
}
diff --git a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
index af88792..8672721 100644
--- a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
+++ b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
@@ -16,6 +16,10 @@
package com.android.server.backup.restore;
+import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_GET_RESTORE_SETS;
+import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
+
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IRestoreObserver;
import android.app.backup.IRestoreSession;
@@ -87,13 +91,12 @@
// We know we're doing legit work now, so halt the timeout
// until we're done. It gets started again when the result
// comes in.
- backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+ backupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
// spin off the transport request to our service thread
backupManagerService.getWakelock().acquire();
Message msg = backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_RUN_GET_RESTORE_SETS,
+ MSG_RUN_GET_RESTORE_SETS,
new RestoreGetSetsParams(mRestoreTransport, this, observer,
monitor));
backupManagerService.getBackupHandler().sendMessage(msg);
@@ -150,7 +153,7 @@
if (token == mRestoreSets[i].token) {
// Real work, so stop the session timeout until we finalize the restore
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+ MSG_RESTORE_SESSION_TIMEOUT);
long oldId = Binder.clearCallingIdentity();
backupManagerService.getWakelock().acquire();
@@ -158,7 +161,7 @@
Slog.d(TAG, "restoreAll() kicking off");
}
Message msg = backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_RUN_RESTORE);
+ MSG_RUN_RESTORE);
msg.obj = new RestoreParams(mRestoreTransport, dirName,
observer, monitor, token);
backupManagerService.getBackupHandler().sendMessage(msg);
@@ -243,7 +246,7 @@
if (token == mRestoreSets[i].token) {
// Stop the session timeout until we finalize the restore
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+ MSG_RESTORE_SESSION_TIMEOUT);
long oldId = Binder.clearCallingIdentity();
backupManagerService.getWakelock().acquire();
@@ -251,7 +254,7 @@
Slog.d(TAG, "restoreSome() of " + packages.length + " packages");
}
Message msg = backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_RUN_RESTORE);
+ MSG_RUN_RESTORE);
msg.obj = new RestoreParams(mRestoreTransport, dirName, observer, monitor,
token, packages, packages.length > 1);
backupManagerService.getBackupHandler().sendMessage(msg);
@@ -341,16 +344,14 @@
}
// Stop the session timeout until we finalize the restore
- backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+ backupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
// Ready to go: enqueue the restore request and claim success
backupManagerService.getWakelock().acquire();
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.d(TAG, "restorePackage() : " + packageName);
}
- Message msg = backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_RUN_RESTORE);
+ Message msg = backupManagerService.getBackupHandler().obtainMessage(MSG_RUN_RESTORE);
msg.obj = new RestoreParams(mRestoreTransport, dirName, observer, monitor,
token, app);
backupManagerService.getBackupHandler().sendMessage(msg);
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index 5009075..1d5be28 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -16,6 +16,8 @@
package com.android.server.backup.restore;
+import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
+
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
import android.app.backup.FullBackup;
@@ -371,9 +373,14 @@
if (okay) {
boolean agentSuccess = true;
long toCopy = info.size;
+ final boolean isSharedStorage = pkg.equals(
+ RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE);
+ final long timeout = isSharedStorage ?
+ RefactoredBackupManagerService.TIMEOUT_SHARED_BACKUP_INTERVAL :
+ RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL;
try {
backupManagerService.prepareOperationTimeout(token,
- RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+ timeout,
mMonitorTask,
RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
@@ -489,7 +496,7 @@
Slog.w(RefactoredBackupManagerService.TAG,
"Agent failure restoring " + pkg + "; ending restore");
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
+ MSG_RESTORE_OPERATION_TIMEOUT);
tearDownPipes();
tearDownAgent(mTargetApp);
mAgent = null;
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 1ddaae7..6b26561 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -16,6 +16,8 @@
package com.android.server.backup.restore;
+import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
+
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
import android.app.backup.FullBackup;
@@ -722,7 +724,7 @@
"Agent failure restoring " + pkg + "; now ignoring");
}
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
+ MSG_RESTORE_OPERATION_TIMEOUT);
tearDownPipes();
tearDownAgent(mTargetApp, false);
mPackagePolicies.put(pkg, RestorePolicy.IGNORE);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index b73b096..7b025f4 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -16,6 +16,10 @@
package com.android.server.backup.restore;
+import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
+import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
+import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
+
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
import android.app.backup.BackupDataInput;
@@ -392,7 +396,7 @@
// synchronous we also know that we should cancel the pending timeout
// message.
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
+ MSG_RESTORE_OPERATION_TIMEOUT);
// Verify that the backup set includes metadata. If not, we can't do
// signature/version verification etc, so we simply do not proceed with
@@ -409,7 +413,7 @@
"Package manager restore metadata missing");
mStatus = BackupTransport.TRANSPORT_ERROR;
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
+ MSG_BACKUP_RESTORE_STEP, this);
executeNextState(UnifiedRestoreState.FINAL);
return;
}
@@ -427,7 +431,7 @@
BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
mStatus = BackupTransport.TRANSPORT_ERROR;
backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
+ MSG_BACKUP_RESTORE_STEP, this);
executeNextState(UnifiedRestoreState.FINAL);
return;
}
@@ -1072,8 +1076,7 @@
}
// Clear any ongoing session timeout.
- backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+ backupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
// If we have a PM token, we must under all circumstances be sure to
// handshake when we've finished.
@@ -1089,7 +1092,7 @@
// We were invoked via an active restore session, not by the Package
// Manager, so start up the session timeout again.
backupManagerService.getBackupHandler().sendEmptyMessageDelayed(
- RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT,
+ MSG_RESTORE_SESSION_TIMEOUT,
RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL);
}
@@ -1116,7 +1119,7 @@
PerformUnifiedRestoreTask task = backupManagerService.getPendingRestores().remove();
backupManagerService.getBackupHandler().sendMessage(
backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, task));
+ MSG_BACKUP_RESTORE_STEP, task));
} else {
backupManagerService.setRestoreInProgress(false);
@@ -1215,8 +1218,7 @@
// The caller is responsible for reestablishing the state machine; our
// responsibility here is to clear the decks for whatever comes next.
- backupManagerService.getBackupHandler().removeMessages(
- RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT, this);
+ backupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_OPERATION_TIMEOUT, this);
}
@Override
@@ -1306,7 +1308,7 @@
}
mState = nextState;
Message msg = backupManagerService.getBackupHandler().obtainMessage(
- RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
+ MSG_BACKUP_RESTORE_STEP, this);
backupManagerService.getBackupHandler().sendMessage(msg);
}
diff --git a/services/backup/java/com/android/server/backup/restore/RestoreDeleteObserver.java b/services/backup/java/com/android/server/backup/restore/RestoreDeleteObserver.java
index 5bc3eca..12be84c 100644
--- a/services/backup/java/com/android/server/backup/restore/RestoreDeleteObserver.java
+++ b/services/backup/java/com/android/server/backup/restore/RestoreDeleteObserver.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.restore;
import android.content.pm.IPackageDeleteObserver;
diff --git a/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java b/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
index 4cb0abc..6c9a222 100644
--- a/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
+++ b/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.restore;
import android.app.IBackupAgent;
diff --git a/services/backup/java/com/android/server/backup/restore/RestoreInstallObserver.java b/services/backup/java/com/android/server/backup/restore/RestoreInstallObserver.java
index eff857a..3d506f1 100644
--- a/services/backup/java/com/android/server/backup/restore/RestoreInstallObserver.java
+++ b/services/backup/java/com/android/server/backup/restore/RestoreInstallObserver.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.restore;
import android.app.PackageInstallObserver;
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index a32635e..03862c4 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
import android.content.pm.ApplicationInfo;
@@ -75,6 +91,7 @@
/**
* Old style: directly match the stored vs on device signature blocks.
*/
+ // TODO(b/37977154): Resolve questionable policies.
public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
if (target == null) {
return false;
@@ -94,7 +111,7 @@
}
// Allow unsigned apps, but not signed on one device and unsigned on the other
- // !!! TODO: is this the right policy?
+ // TODO(b/37977154): is this the right policy?
Signature[] deviceSigs = target.signatures;
if (RefactoredBackupManagerService.MORE_DEBUG) {
Slog.v(RefactoredBackupManagerService.TAG, "signaturesMatch(): stored=" + storedSigs
@@ -104,11 +121,12 @@
&& (deviceSigs == null || deviceSigs.length == 0)) {
return true;
}
+ // TODO(b/37977154): This allows empty stored signature, is this right?
if (storedSigs == null || deviceSigs == null) {
return false;
}
- // !!! TODO: this demands that every stored signature match one
+ // TODO(b/37977154): this demands that every stored signature match one
// that is present on device, and does not demand the converse.
// Is this this right policy?
int nStored = storedSigs.length;
diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
index 53addfc..3b9b692 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
@@ -54,6 +70,15 @@
return null;
}
+ /**
+ * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will
+ * be created.
+ *
+ * @param extras - bundle where to add key-value to, if null a new bundle will be created.
+ * @param key - key.
+ * @param value - value.
+ * @return extras if it was not null and new bundle otherwise.
+ */
public static Bundle putMonitoringExtra(Bundle extras, String key, String value) {
if (extras == null) {
extras = new Bundle();
@@ -62,14 +87,15 @@
return extras;
}
- private static Bundle putMonitoringExtra(Bundle extras, String key, int value) {
- if (extras == null) {
- extras = new Bundle();
- }
- extras.putInt(key, value);
- return extras;
- }
-
+ /**
+ * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will
+ * be created.
+ *
+ * @param extras - bundle where to add key-value to, if null a new bundle will be created.
+ * @param key - key.
+ * @param value - value.
+ * @return extras if it was not null and new bundle otherwise.
+ */
public static Bundle putMonitoringExtra(Bundle extras, String key, long value) {
if (extras == null) {
extras = new Bundle();
@@ -78,6 +104,15 @@
return extras;
}
+ /**
+ * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will
+ * be created.
+ *
+ * @param extras - bundle where to add key-value to, if null a new bundle will be created.
+ * @param key - key.
+ * @param value - value.
+ * @return extras if it was not null and new bundle otherwise.
+ */
public static Bundle putMonitoringExtra(Bundle extras, String key, boolean value) {
if (extras == null) {
extras = new Bundle();
diff --git a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
index b5e5e08..eb939a8 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
import android.app.backup.BackupProgress;
diff --git a/services/backup/java/com/android/server/backup/utils/BytesReadListener.java b/services/backup/java/com/android/server/backup/utils/BytesReadListener.java
index 1595153..34d85ff 100644
--- a/services/backup/java/com/android/server/backup/utils/BytesReadListener.java
+++ b/services/backup/java/com/android/server/backup/utils/BytesReadListener.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
/**
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
index 0c868af..1b51186 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
import android.app.backup.IFullBackupRestoreObserver;
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
index bfb4b25..4072a5e 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
import android.content.pm.PackageInfo;
diff --git a/services/backup/java/com/android/server/backup/utils/PasswordUtils.java b/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
index c90ec59..5ae79e2 100644
--- a/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index cdda68e..c277c03 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
import android.content.pm.ApplicationInfo;
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index 25832c9..12c1af2 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
package com.android.server.backup.utils;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 6597a5e..a86612e 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1086,6 +1086,7 @@
if (timeZoneWasChanged) {
Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
intent.putExtra("time-zone", zone.getID());
getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0748816..8555851 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2624,6 +2624,17 @@
PROMPT_UNVALIDATED_DELAY_MS);
}
+ @Override
+ public void startCaptivePortalApp(Network network) {
+ enforceConnectivityInternalPermission();
+ mHandler.post(() -> {
+ NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+ if (nai == null) return;
+ if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
+ nai.networkMonitor.sendMessage(NetworkMonitor.CMD_LAUNCH_CAPTIVE_PORTAL_APP);
+ });
+ }
+
public boolean avoidBadWifi() {
return mMultinetworkPolicyTracker.getAvoidBadWifi();
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 8945952..8be859f 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -234,6 +234,12 @@
private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
/**
+ * Package names the user has white-listed using commandline option to opt out of
+ * power save restrictions, except for device idle mode.
+ */
+ private final ArraySet<String> mPowerSaveWhitelistUserAppsExceptIdle = new ArraySet<>();
+
+ /**
* Package names the system has white-listed to opt out of power save restrictions for
* all modes.
*/
@@ -1506,6 +1512,45 @@
}
}
+ public boolean addPowerSaveWhitelistExceptIdleInternal(String name) {
+ synchronized (this) {
+ try {
+ final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
+ PackageManager.MATCH_ANY_USER);
+ if (mPowerSaveWhitelistAppsExceptIdle.put(name, UserHandle.getAppId(ai.uid))
+ == null) {
+ mPowerSaveWhitelistUserAppsExceptIdle.add(name);
+ reportPowerSaveWhitelistChangedLocked();
+ mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
+ mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
+ mPowerSaveWhitelistExceptIdleAppIds);
+ }
+ return true;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+ }
+
+ public void resetPowerSaveWhitelistExceptIdleInternal() {
+ synchronized (this) {
+ if (mPowerSaveWhitelistAppsExceptIdle.removeAll(
+ mPowerSaveWhitelistUserAppsExceptIdle)) {
+ reportPowerSaveWhitelistChangedLocked();
+ mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
+ mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
+ mPowerSaveWhitelistExceptIdleAppIds);
+ mPowerSaveWhitelistUserAppsExceptIdle.clear();
+ }
+ }
+ }
+
+ public boolean getPowerSaveWhitelistExceptIdleInternal(String name) {
+ synchronized (this) {
+ return mPowerSaveWhitelistAppsExceptIdle.containsKey(name);
+ }
+ }
+
public String[] getSystemPowerWhitelistExceptIdleInternal() {
synchronized (this) {
int size = mPowerSaveWhitelistAppsExceptIdle.size();
@@ -2556,6 +2601,12 @@
pw.println(" Print currently whitelisted apps.");
pw.println(" whitelist [package ...]");
pw.println(" Add (prefix with +) or remove (prefix with -) packages.");
+ pw.println(" except-idle-whitelist [package ...|reset]");
+ pw.println(" Prefix the package with '+' to add it to whitelist or "
+ + "'=' to check if it is already whitelisted");
+ pw.println(" [reset] will reset the whitelist to it's original state");
+ pw.println(" Note that unlike <whitelist> cmd, "
+ + "changes made using this won't be persisted across boots");
pw.println(" tempwhitelist");
pw.println(" Print packages that are temporarily whitelisted.");
pw.println(" tempwhitelist [-u USER] [-d DURATION] [package ..]");
@@ -2873,6 +2924,43 @@
} else {
dumpTempWhitelistSchedule(pw, false);
}
+ } else if ("except-idle-whitelist".equals(cmd)) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ String arg = shell.getNextArg();
+ if (arg == null) {
+ pw.println("No arguments given");
+ return -1;
+ } else if ("reset".equals(arg)) {
+ resetPowerSaveWhitelistExceptIdleInternal();
+ } else {
+ do {
+ if (arg.length() < 1 || (arg.charAt(0) != '-'
+ && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
+ pw.println("Package must be prefixed with +, -, or =: " + arg);
+ return -1;
+ }
+ char op = arg.charAt(0);
+ String pkg = arg.substring(1);
+ if (op == '+') {
+ if (addPowerSaveWhitelistExceptIdleInternal(pkg)) {
+ pw.println("Added: " + pkg);
+ } else {
+ pw.println("Unknown package: " + pkg);
+ }
+ } else if (op == '=') {
+ pw.println(getPowerSaveWhitelistExceptIdleInternal(pkg));
+ } else {
+ pw.println("Unknown argument: " + arg);
+ return -1;
+ }
+ } while ((arg = shell.getNextArg()) != null);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
} else {
return shell.handleDefaultCommands(cmd);
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 114d761..fdc0bba 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -631,6 +631,11 @@
PackageManager.PERMISSION_GRANTED;
}
+ private boolean callerCanScoreNetworks() {
+ return mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS) ==
+ PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public boolean clearScores() {
// Only the active scorer or the system should be allowed to flush all scores.
@@ -651,9 +656,9 @@
@Override
public boolean setActiveScorer(String packageName) {
// Only the system can set the active scorer
- if (!isCallerSystemProcess(getCallingUid()) && !callerCanRequestScores()) {
+ if (!isCallerSystemProcess(getCallingUid()) && !callerCanScoreNetworks()) {
throw new SecurityException(
- "Caller is neither the system process nor a score requester.");
+ "Caller is neither the system process or a network scorer.");
}
return mNetworkScorerAppManager.setActiveScorer(packageName);
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
index 8404025..42777bf 100644
--- a/services/core/java/com/android/server/NetworkScorerAppManager.java
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -208,11 +208,11 @@
*
* <p>The caller must have permission to write to {@link Settings.Global}.
*
- * @param packageName the packageName of the new scorer to use. If null, the scoring app will
- * revert back to the configured default. Otherwise, the scorer will only
- * be set if it is a valid scorer application.
- * @return true if the scorer was changed, or false if the package is not a valid scorer or
- * a valid network recommendation provider exists.
+ * @param packageName the packageName of the new scorer to use. If null, scoring will be forced
+ * off, otherwise the scorer will only be set if it is a valid scorer
+ * application.
+ * @return true if the package was a valid scorer (including <code>null</code>) and now
+ * represents the active scorer, false otherwise.
*/
@VisibleForTesting
public boolean setActiveScorer(String packageName) {
@@ -223,16 +223,19 @@
return true;
}
- if (packageName == null) {
- // revert to the default setting.
- packageName = getDefaultPackageSetting();
+ if (TextUtils.isEmpty(packageName)) {
+ Log.i(TAG, "Network scorer forced off, was: " + oldPackageName);
+ setNetworkRecommendationsPackage(null);
+ setNetworkRecommendationsEnabledSetting(
+ NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
+ return true;
}
- Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
-
// We only make the change if the new package is valid.
if (getScorer(packageName) != null) {
+ Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
setNetworkRecommendationsPackage(packageName);
+ setNetworkRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
return true;
} else {
Log.w(TAG, "Requested network scorer is not valid: " + packageName);
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index c105b12..94397d0 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -173,6 +173,9 @@
* state they maintain for running users. This is called prior to sending the SHUTDOWN
* broadcast to the user; it is a good place to stop making use of any resources of that
* user (such as binding to a service running in the user).
+ *
+ * <p>NOTE: This is the last callback where the callee may access the target user's CE storage.
+ *
* @param userHandle The identifier of the user.
*/
public void onStopUser(int userHandle) {}
@@ -181,6 +184,10 @@
* Called when an existing user is stopping, for system services to finalize any per-user
* state they maintain for running users. This is called after all application process
* teardown of the user is complete.
+ *
+ * <p>NOTE: When this callback is called, the CE storage for the target user may not be
+ * accessible already. Use {@link #onStopUser} instead if you need to access the CE storage.
+ *
* @param userHandle The identifier of the user.
*/
public void onCleanupUser(int userHandle) {}
diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/Vr2dDisplay.java
similarity index 93%
rename from services/core/java/com/android/server/vr/CompatibilityDisplay.java
rename to services/core/java/com/android/server/Vr2dDisplay.java
index d7cdf08..1116e4e 100644
--- a/services/core/java/com/android/server/vr/CompatibilityDisplay.java
+++ b/services/core/java/com/android/server/Vr2dDisplay.java
@@ -3,7 +3,7 @@
import static android.view.Display.INVALID_DISPLAY;
import android.app.ActivityManagerInternal;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -31,8 +31,8 @@
* Creates a 2D Virtual Display while VR Mode is enabled. This display will be used to run and
* render 2D app within a VR experience. For example, bringing up the 2D calculator app in VR.
*/
-class CompatibilityDisplay {
- private final static String TAG = "CompatDisplay";
+class Vr2dDisplay {
+ private final static String TAG = "Vr2dDisplay";
private final static boolean DEBUG = false;
// TODO: Go over these values and figure out what is best
@@ -42,13 +42,13 @@
private final static int STOP_VIRTUAL_DISPLAY_DELAY_MILLIS = 2000;
private final static String DEBUG_ACTION_SET_MODE =
- "com.android.server.vr.CompatibilityDisplay.SET_MODE";
+ "com.android.server.vr.Vr2dDisplay.SET_MODE";
private final static String DEBUG_EXTRA_MODE_ON =
- "com.android.server.vr.CompatibilityDisplay.EXTRA_MODE_ON";
+ "com.android.server.vr.Vr2dDisplay.EXTRA_MODE_ON";
private final static String DEBUG_ACTION_SET_SURFACE =
- "com.android.server.vr.CompatibilityDisplay.SET_SURFACE";
+ "com.android.server.vr.Vr2dDisplay.SET_SURFACE";
private final static String DEBUG_EXTRA_SURFACE =
- "com.android.server.vr.CompatibilityDisplay.EXTRA_SURFACE";
+ "com.android.server.vr.Vr2dDisplay.EXTRA_SURFACE";
/**
* The default width of the VR virtual display
@@ -99,7 +99,7 @@
private boolean mIsVrModeOverrideEnabled;
private boolean mIsVrModeEnabled;
- public CompatibilityDisplay(DisplayManager displayManager,
+ public Vr2dDisplay(DisplayManager displayManager,
ActivityManagerInternal activityManagerInternal, IVrManager vrManager) {
mDisplayManager = displayManager;
mActivityManagerInternal = activityManagerInternal;
@@ -190,7 +190,7 @@
}
/**
- * Sets the resolution and DPI of the compatibility virtual display used to display
+ * Sets the resolution and DPI of the Vr2d virtual display used to display
* 2D applications in VR mode.
*
* <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
@@ -198,7 +198,7 @@
* @param compatDisplayProperties Properties of the virtual display for 2D applications
* in VR mode.
*/
- public void setVirtualDisplayProperties(CompatibilityDisplayProperties compatDisplayProperties) {
+ public void setVirtualDisplayProperties(Vr2dDisplayProperties compatDisplayProperties) {
synchronized(mVdLock) {
if (DEBUG) {
Log.i(TAG, "VD setVirtualDisplayProperties: res = " +
@@ -273,13 +273,13 @@
null /* Surface */, 0 /* flags */);
if (mVirtualDisplay != null) {
- mActivityManagerInternal.setVrCompatibilityDisplayId(
+ mActivityManagerInternal.setVr2dDisplayId(
mVirtualDisplay.getDisplay().getDisplayId());
// Now create the ImageReader to supply a Surface to the new virtual display.
startImageReader();
} else {
Log.w(TAG, "Virtual display id is null after createVirtualDisplay");
- mActivityManagerInternal.setVrCompatibilityDisplayId(INVALID_DISPLAY);
+ mActivityManagerInternal.setVr2dDisplayId(INVALID_DISPLAY);
return;
}
}
@@ -302,7 +302,7 @@
} else {
Log.i(TAG, "Stopping Virtual Display");
synchronized (mVdLock) {
- mActivityManagerInternal.setVrCompatibilityDisplayId(INVALID_DISPLAY);
+ mActivityManagerInternal.setVr2dDisplayId(INVALID_DISPLAY);
setSurfaceLocked(null); // clean up and release the surface first.
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 5edf19a..a5615a9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -166,8 +166,11 @@
*/
static final class ActiveForegroundApp {
String mPackageName;
+ int mUid;
CharSequence mLabel;
boolean mShownWhileScreenOn;
+ boolean mAppOnTop;
+ boolean mShownWhileTop;
long mStartTime;
long mStartVisibleTime;
long mEndTime;
@@ -728,11 +731,12 @@
synchronized (mAm) {
final long now = SystemClock.elapsedRealtime();
final long nowPlusMin = now + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME;
+ long nextUpdateTime = Long.MAX_VALUE;
if (smap != null) {
for (int i = smap.mActiveForegroundApps.size()-1; i >= 0; i--) {
ActiveForegroundApp aa = smap.mActiveForegroundApps.valueAt(i);
if (aa.mEndTime != 0 && (mScreenOn || aa.mShownWhileScreenOn)) {
- if (aa.mEndTime < (aa.mStartVisibleTime
+ if (!aa.mShownWhileTop && aa.mEndTime < (aa.mStartVisibleTime
+ mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) {
// Check to see if this should still be displayed... we continue
// until it has been shown for at least the timeout duration.
@@ -741,6 +745,12 @@
smap.mActiveForegroundApps.removeAt(i);
smap.mActiveForegroundAppsChanged = true;
continue;
+ } else {
+ long hideTime = aa.mStartVisibleTime
+ + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME;
+ if (hideTime < nextUpdateTime) {
+ nextUpdateTime = hideTime;
+ }
}
} else {
// This was up for longer than the timeout, so just remove immediately.
@@ -749,10 +759,17 @@
continue;
}
}
- if (active == null) {
- active = new ArrayList<>();
+ if (!aa.mAppOnTop) {
+ if (active == null) {
+ active = new ArrayList<>();
+ }
+ active.add(aa);
}
- active.add(aa);
+ }
+ smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
+ if (nextUpdateTime < Long.MAX_VALUE) {
+ Message msg = smap.obtainMessage();
+ smap.sendMessageAtTime(msg, nextUpdateTime);
}
}
if (!smap.mActiveForegroundAppsChanged) {
@@ -842,7 +859,7 @@
active.mNumActive--;
if (active.mNumActive <= 0) {
active.mEndTime = SystemClock.elapsedRealtime();
- if (active.mEndTime >= (active.mStartVisibleTime
+ if (active.mShownWhileTop || active.mEndTime >= (active.mStartVisibleTime
+ mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) {
// Have been active for long enough that we will remove it immediately.
smap.mActiveForegroundApps.remove(r.packageName);
@@ -887,6 +904,31 @@
}
}
+ void foregroundServiceProcStateChangedLocked(UidRecord uidRec) {
+ ServiceMap smap = mServiceMap.get(UserHandle.getUserId(uidRec.uid));
+ if (smap != null) {
+ boolean changed = false;
+ for (int j = smap.mActiveForegroundApps.size()-1; j >= 0; j--) {
+ ActiveForegroundApp active = smap.mActiveForegroundApps.valueAt(j);
+ if (active.mUid == uidRec.uid) {
+ if (uidRec.curProcState <= ActivityManager.PROCESS_STATE_TOP) {
+ if (!active.mAppOnTop) {
+ active.mAppOnTop = true;
+ changed = true;
+ }
+ active.mShownWhileTop = true;
+ } else if (active.mAppOnTop) {
+ active.mAppOnTop = false;
+ changed = true;
+ }
+ }
+ }
+ if (changed) {
+ requestUpdateActiveForegroundAppsLocked(smap, 0);
+ }
+ }
+ }
+
private void setServiceForegroundInnerLocked(ServiceRecord r, int id,
Notification notification, int flags) {
if (id != 0) {
@@ -948,7 +990,13 @@
if (active == null) {
active = new ActiveForegroundApp();
active.mPackageName = r.packageName;
+ active.mUid = r.appInfo.uid;
active.mShownWhileScreenOn = mScreenOn;
+ if (r.app != null) {
+ active.mAppOnTop = active.mShownWhileTop =
+ r.app.uidRecord.curProcState
+ <= ActivityManager.PROCESS_STATE_TOP;
+ }
active.mStartTime = active.mStartVisibleTime
= SystemClock.elapsedRealtime();
smap.mActiveForegroundApps.put(r.packageName, active);
@@ -1258,6 +1306,10 @@
mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
s.appInfo.uid, s.name, s.processName);
+ // Once the apps have become associated, if one of them is caller is ephemeral
+ // the target app should now be able to see the calling app
+ mAm.grantEphemeralAccessLocked(callerApp.userId, service,
+ s.appInfo.uid, UserHandle.getAppId(callerApp.uid));
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
@@ -2786,6 +2838,9 @@
if (!doit && didSomething) {
return true;
}
+ if (doit && filterByClasses == null) {
+ forceStopPackageLocked(packageName, mServiceMap.valueAt(i).mUserId);
+ }
}
} else {
ServiceMap smap = mServiceMap.get(userId);
@@ -2794,6 +2849,9 @@
didSomething = collectPackageServicesLocked(packageName, filterByClasses,
evenPersistent, doit, killProcess, items);
}
+ if (doit && filterByClasses == null) {
+ forceStopPackageLocked(packageName, userId);
+ }
}
if (mTmpCollectionResults != null) {
@@ -2802,13 +2860,14 @@
}
mTmpCollectionResults.clear();
}
+
return didSomething;
}
- void removeUninstalledPackageLocked(String packageName, int userId) {
+ void forceStopPackageLocked(String packageName, int userId) {
ServiceMap smap = mServiceMap.get(userId);
if (smap != null && smap.mActiveForegroundApps.size() > 0) {
- for (int i = smap.mActiveForegroundApps.size(); i >= 0; i--) {
+ for (int i = smap.mActiveForegroundApps.size()-1; i >= 0; i--) {
ActiveForegroundApp aa = smap.mActiveForegroundApps.valueAt(i);
if (aa.mPackageName.equals(packageName)) {
smap.mActiveForegroundApps.removeAt(i);
@@ -3636,6 +3695,10 @@
}
pw.print(" mNumActive=");
pw.print(aa.mNumActive);
+ pw.print(" mAppOnTop=");
+ pw.print(aa.mAppOnTop);
+ pw.print(" mShownWhileTop=");
+ pw.print(aa.mShownWhileTop);
pw.print(" mShownWhileScreenOn=");
pw.println(aa.mShownWhileScreenOn);
pw.print(" mStartTime=");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ace2b55..6570963 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -120,7 +120,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROVIDER;
@@ -572,11 +571,10 @@
// Determines whether to take full screen screenshots
static final boolean TAKE_FULLSCREEN_SCREENSHOTS = true;
- // STOPSHIP: Update default to a smaller value.
/**
* Default value for {@link Settings.Global#NETWORK_ACCESS_TIMEOUT_MS}.
*/
- private static final long NETWORK_ACCESS_TIMEOUT_DEFAULT_MS = 2000; // 2 sec
+ private static final long NETWORK_ACCESS_TIMEOUT_DEFAULT_MS = 200; // 0.2 sec
/**
* State indicating that there is no need for any blocking for network.
@@ -627,8 +625,8 @@
private final VrController mVrController;
- // VR Compatibility Display Id.
- int mVrCompatibilityDisplayId = INVALID_DISPLAY;
+ // VR Vr2d Display Id.
+ int mVr2dDisplayId = INVALID_DISPLAY;
// Whether we should use SCHED_FIFO for UI and RenderThreads.
private boolean mUseFifoUiScheduling = false;
@@ -4312,6 +4310,7 @@
validateUid.idle = false;
}
validateUid.curProcState = validateUid.setProcState = item.processState;
+ validateUid.lastDispatchedProcStateSeq = item.procStateSeq;
}
}
}
@@ -18982,7 +18981,7 @@
removeTasksByPackageNameLocked(ssp, userId);
- mServices.removeUninstalledPackageLocked(ssp, userId);
+ mServices.forceStopPackageLocked(ssp, userId);
// Hide the "unsupported display" dialog if necessary.
if (mUnsupportedDisplaySizeDialog != null && ssp.equals(
@@ -19865,8 +19864,9 @@
}
/**
- * NOTE: For the pinned stack, this method is only called after the bounds animation has
- * animated the stack to the fullscreen.
+ * NOTE: For the pinned stack, this method is usually called after the bounds animation has
+ * animated the stack to the fullscreen, but can also be called if we are relaunching an
+ * activity and clearing the task at the same time.
*/
@Override
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
@@ -22252,6 +22252,9 @@
if (uidRec.curProcState > app.curProcState) {
uidRec.curProcState = app.curProcState;
}
+ if (app.foregroundServices) {
+ uidRec.foregroundServices = true;
+ }
}
}
@@ -22493,6 +22496,9 @@
uidRec.setWhitelist = uidRec.curWhitelist;
enqueueUidChangeLocked(uidRec, -1, uidChange);
noteUidProcessState(uidRec.uid, uidRec.curProcState);
+ if (uidRec.foregroundServices) {
+ mServices.foregroundServiceProcStateChangedLocked(uidRec);
+ }
}
}
if (mLocalPowerManager != null) {
@@ -23701,17 +23707,17 @@
/**
* Called after virtual display Id is updated by
- * {@link com.android.server.vr.CompatibilityDisplay} with a specific
- * {@param vrCompatibilityDisplayId}.
+ * {@link com.android.server.vr.Vr2dDisplay} with a specific
+ * {@param vrVr2dDisplayId}.
*/
@Override
- public void setVrCompatibilityDisplayId(int vrCompatibilityDisplayId) {
+ public void setVr2dDisplayId(int vr2dDisplayId) {
if (DEBUG_STACK) {
- Slog.d(TAG, "setVrCompatibilityDisplayId called for: " +
- vrCompatibilityDisplayId);
+ Slog.d(TAG, "setVr2dDisplayId called for: " +
+ vr2dDisplayId);
}
synchronized (ActivityManagerService.this) {
- mVrCompatibilityDisplayId = vrCompatibilityDisplayId;
+ mVr2dDisplayId = vr2dDisplayId;
}
}
}
@@ -23775,11 +23781,8 @@
if (totalTime >= mWaitForNetworkTimeoutMs) {
Slog.wtf(TAG_NETWORK, "Total time waited for network rules to get updated: "
+ totalTime + ". Uid: " + callingUid + " procStateSeq: "
- + procStateSeq);
- } else if (DEBUG_NETWORK || totalTime >= mWaitForNetworkTimeoutMs / 2) {
- Slog.d(TAG_NETWORK, "Total time waited for network rules to get updated: "
- + totalTime + ". Uid: " + callingUid + " procStateSeq: "
- + procStateSeq);
+ + procStateSeq + " UidRec: " + record
+ + " validateUidRec: " + mValidateUids.get(callingUid));
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 2dd3b74..d4de521 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -11,12 +11,12 @@
import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
@@ -194,6 +194,11 @@
final int stackId = launchedActivity != null && launchedActivity.getStack() != null
? launchedActivity.getStack().mStackId
: INVALID_STACK_ID;
+
+ if (mCurrentTransitionStartTime == INVALID_START_TIME) {
+ return;
+ }
+
final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
if (launchedActivity != null && info != null) {
info.launchedActivity = launchedActivity;
@@ -272,6 +277,25 @@
}
}
+ /**
+ * Notifies the tracker that the visibility of an app is changing.
+ *
+ * @param activityRecord the app that is changing its visibility
+ * @param visible whether it's going to be visible or not
+ */
+ void notifyVisibilityChanged(ActivityRecord activityRecord, boolean visible) {
+ final StackTransitionInfo info = mStackTransitionInfo.get(activityRecord.getStackId());
+
+ // If we have an active transition that's waiting on a certain activity that will be
+ // invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary.
+ if (info != null && !visible && info.launchedActivity == activityRecord) {
+ mStackTransitionInfo.remove(activityRecord.getStackId());
+ if (mStackTransitionInfo.size() == 0) {
+ reset(true /* abort */);
+ }
+ }
+ }
+
private boolean allStacksWindowsDrawn() {
for (int index = mStackTransitionInfo.size() - 1; index >= 0; index--) {
if (!mStackTransitionInfo.valueAt(index).loggedWindowsDrawn) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 158175f..18c8b32 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -61,6 +61,8 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
+import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -1052,7 +1054,7 @@
return task != null ? (T) task.getStack() : null;
}
- private int getStackId() {
+ int getStackId() {
return getStack() != null ? getStack().mStackId : INVALID_STACK_ID;
}
@@ -1579,6 +1581,7 @@
void setVisibility(boolean visible) {
mWindowContainerController.setVisibility(visible, mDeferHidingClient);
+ mStackSupervisor.mActivityMetricsLogger.notifyVisibilityChanged(this, visible);
}
// TODO: Look into merging with #setVisibility()
@@ -2222,15 +2225,19 @@
}
@Override
- void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
- super.onOverrideConfigurationChanged(overrideConfiguration);
- if (mWindowContainerController != null) {
- mWindowContainerController.onOverrideConfigurationChanged(
- overrideConfiguration, mBounds);
- // TODO(b/36505427): Can we consolidate the call points of onOverrideConfigurationSent()
- // to just use this method instead?
- onOverrideConfigurationSent();
+ void onOverrideConfigurationChanged(Configuration newConfig) {
+ final Configuration currentConfig = getOverrideConfiguration();
+ if (currentConfig.equals(newConfig)) {
+ return;
}
+ super.onOverrideConfigurationChanged(newConfig);
+ if (mWindowContainerController == null) {
+ return;
+ }
+ mWindowContainerController.onOverrideConfigurationChanged(newConfig, mBounds);
+ // TODO(b/36505427): Can we consolidate the call points of onOverrideConfigurationSent()
+ // to just use this method instead?
+ onOverrideConfigurationSent();
}
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
@@ -2238,6 +2245,26 @@
mTmpConfig.unset();
computeBounds(mTmpBounds);
if (mTmpBounds.equals(mBounds)) {
+ final ActivityStack stack = getStack();
+ if (!mBounds.isEmpty() || task == null || stack == null || !task.mFullscreen) {
+ // We don't want to influence the override configuration here if our task is in
+ // multi-window mode or there is a bounds specified to calculate the override
+ // config. In both of this cases the app should be compatible with whatever the
+ // current configuration is or will be.
+ return;
+ }
+
+ // Currently limited to the top activity for now to avoid situations where non-top
+ // visible activity and top might have conflicting requests putting the non-top activity
+ // windows in an odd state.
+ final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+ final Configuration parentConfig = getParent().getConfiguration();
+ if (top != this || isConfigurationCompatible(parentConfig)) {
+ onOverrideConfigurationChanged(mTmpConfig);
+ } else if (isConfigurationCompatible(
+ mLastReportedConfiguration.getMergedConfiguration())) {
+ onOverrideConfigurationChanged(mLastReportedConfiguration.getMergedConfiguration());
+ }
return;
}
@@ -2250,6 +2277,21 @@
onOverrideConfigurationChanged(mTmpConfig);
}
+ /** Returns true if the configuration is compatible with this activity. */
+ boolean isConfigurationCompatible(Configuration config) {
+ final int orientation = mWindowContainerController != null
+ ? mWindowContainerController.getOrientation() : info.screenOrientation;
+ if (isFixedOrientationPortrait(orientation)
+ && config.orientation != ORIENTATION_PORTRAIT) {
+ return false;
+ }
+ if (isFixedOrientationLandscape(orientation)
+ && config.orientation != ORIENTATION_LANDSCAPE) {
+ return false;
+ }
+ return true;
+ }
+
/**
* Computes the bounds to fit the Activity within the bounds of the {@link Configuration}.
*/
@@ -2328,6 +2370,9 @@
return true;
}
+ // TODO: We should add ActivityRecord.shouldBeVisible() that checks if the activity should
+ // be visible based on the stack, task, and lockscreen state and use that here instead. The
+ // method should be based on the logic in ActivityStack.ensureActivitiesVisibleLocked().
// Skip updating configuration for activity is a stack that shouldn't be visible.
if (stack.shouldBeVisible(null /* starting */) == STACK_INVISIBLE) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 57dfd05..4ad0663 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -655,11 +655,11 @@
}
}
- final ActivityRecord topRunningActivityLocked() {
+ ActivityRecord topRunningActivityLocked() {
return topRunningActivityLocked(false /* focusableOnly */);
}
- final ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
+ private ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
if (r != null && (!focusableOnly || r.isFocusable())) {
@@ -669,7 +669,21 @@
return null;
}
- final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
+ ActivityRecord topRunningNonOverlayTaskActivity() {
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = mTaskHistory.get(taskNdx);
+ final ArrayList<ActivityRecord> activities = task.mActivities;
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (!r.finishing && !r.mTaskOverlay) {
+ return r;
+ }
+ }
+ }
+ return null;
+ }
+
+ ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -987,7 +1001,7 @@
result.matchedByRootAffinity = false;
break;
} else if (!isDocument && !taskIsDocument
- && result.r == null && task.canMatchRootAffinity()) {
+ && result.r == null && task.rootAffinity != null) {
if (task.rootAffinity.equals(target.taskAffinity)) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
// It is possible for multiple tasks to have the same root affinity especially
@@ -1645,21 +1659,13 @@
}
if (mStackId == DOCKED_STACK_ID) {
- final ActivityRecord r = topStack.topRunningActivityLocked();
-
// If the assistant stack is focused and translucent, then the docked stack is always
// visible
if (topStack.isAssistantStack()) {
return (topStack.isStackTranslucent(starting, DOCKED_STACK_ID)) ? STACK_VISIBLE
: STACK_INVISIBLE;
}
-
- // Otherwise, the docked stack is always visible, except in the case where the top
- // running activity task in the focus stack doesn't support any form of resizing but we
- // show it for the home task even though it's not resizable.
- final TaskRecord task = r != null ? r.getTask() : null;
- return task == null || task.supportsSplitScreen() || task.isHomeTask() ? STACK_VISIBLE
- : STACK_INVISIBLE;
+ return STACK_VISIBLE;
}
// Set home stack to invisible when it is below but not immediately below the docked stack
@@ -1678,14 +1684,17 @@
mStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
stackBehindTopIndex--;
}
- if ((topStackId == DOCKED_STACK_ID || topStackId == PINNED_STACK_ID)
- && stackIndex == stackBehindTopIndex) {
- // Stacks directly behind the docked or pinned stack are always visible.
- return STACK_VISIBLE;
- }
-
final int stackBehindTopId = (stackBehindTopIndex >= 0)
? mStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID;
+ if ((topStackId == DOCKED_STACK_ID || topStackId == PINNED_STACK_ID)
+ && (stackIndex == stackBehindTopIndex
+ || (stackBehindTopId == DOCKED_STACK_ID
+ && stackIndex == stackBehindTopIndex - 1))) {
+ // Stacks directly behind the docked or pinned stack are always visible.
+ // Also this stack is visible if behind docked stack and the docked stack is behind the
+ // top-most pinned stack
+ return STACK_VISIBLE;
+ }
if (StackId.isBackdropToTranslucentActivity(topStackId)
&& topStack.isStackTranslucent(starting, stackBehindTopId)) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 01e86e2..23b0607 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2503,7 +2503,7 @@
tempRect /* outStackBounds */,
otherTaskRect /* outTempTaskBounds */, true /* ignoreVisibility */);
- resizeStackLocked(i, tempRect,
+ resizeStackLocked(i, !tempRect.isEmpty() ? tempRect : null,
!otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds,
tempOtherTaskInsetBounds, preserveWindows,
true /* allowResizeInDockedMode */, deferResume);
@@ -3043,11 +3043,15 @@
if (!mTmpFindTaskResult.matchedByRootAffinity) {
return mTmpFindTaskResult.r;
} else if (mTmpFindTaskResult.r.getDisplayId() == displayId) {
+ // Note: since the traversing through the stacks is top down, the floating
+ // tasks should always have lower priority than any affinity-matching tasks
+ // in the fullscreen stacks
affinityMatch = mTmpFindTaskResult.r;
}
}
}
}
+
if (DEBUG_TASKS && affinityMatch == null) Slog.d(TAG_TASKS, "No task found");
return affinityMatch;
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index ca842d55..1f1aa8e 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -186,7 +186,7 @@
private IVoiceInteractionSession mVoiceSession;
private IVoiceInteractor mVoiceInteractor;
- private boolean mUsingVrCompatibilityDisplay;
+ private boolean mUsingVr2dDisplay;
private void reset() {
mStartActivity = null;
@@ -226,14 +226,14 @@
mVoiceSession = null;
mVoiceInteractor = null;
- mUsingVrCompatibilityDisplay = false;
+ mUsingVr2dDisplay = false;
}
ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
mService = service;
mSupervisor = supervisor;
mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
- mUsingVrCompatibilityDisplay = false;
+ mUsingVr2dDisplay = false;
}
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
@@ -575,12 +575,15 @@
return;
}
- if (startedActivityStackId == PINNED_STACK_ID
- && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
+ boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
+ == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+ if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
+ || result == START_DELIVERED_TO_TOP || clearedTask)) {
// The activity was already running in the pinned stack so it wasn't started, but either
// brought to the front or the new intent was delivered to it since it was already in
// front. Notify anyone interested in this piece of information.
- mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
+ mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
+ clearedTask);
return;
}
}
@@ -953,7 +956,7 @@
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
- if (result != START_SUCCESS && mStartActivity.getTask() != null) {
+ if (result < START_SUCCESS && mStartActivity.getTask() != null) {
mStartActivity.getTask().removeActivity(mStartActivity);
}
mService.mWindowManager.continueSurfaceLayout();
@@ -1045,9 +1048,6 @@
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
- if (outActivity != null && outActivity.length > 0) {
- outActivity[0] = reusedActivity;
- }
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do anything
@@ -1062,6 +1062,9 @@
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
+ if (outActivity != null && outActivity.length > 0) {
+ outActivity[0] = reusedActivity;
+ }
return START_TASK_TO_FRONT;
}
}
@@ -1476,12 +1479,12 @@
}
// Get the virtual display id from ActivityManagerService.
- int displayId = mService.mVrCompatibilityDisplayId;
+ int displayId = mService.mVr2dDisplayId;
if (displayId != INVALID_DISPLAY) {
if (DEBUG_STACK) {
Slog.d(TAG, "getSourceDisplayId :" + displayId);
}
- mUsingVrCompatibilityDisplay = true;
+ mUsingVr2dDisplay = true;
return displayId;
}
@@ -2105,8 +2108,8 @@
return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
}
- // If we are using Vr compatibility display, find the virtual display stack.
- if (mUsingVrCompatibilityDisplay) {
+ // If we are using Vr2d display, find the virtual display stack.
+ if (mUsingVr2dDisplay) {
ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
if (DEBUG_STACK) {
Slog.v(TAG, "Launch stack for app: " + r.toString() +
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index a580d4b..7ba67c5 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -271,10 +271,15 @@
resolvedType = key.requestResolvedType;
}
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+
+ final long origId = Binder.clearCallingIdentity();
+
if (whitelistDuration > 0) {
StringBuilder tag = new StringBuilder(64);
tag.append("pendingintent:");
- UserHandle.formatUid(tag, Binder.getCallingUid());
+ UserHandle.formatUid(tag, callingUid);
tag.append(":");
if (finalIntent.getAction() != null) {
tag.append(finalIntent.getAction());
@@ -283,12 +288,10 @@
} else if (finalIntent.getData() != null) {
tag.append(finalIntent.getData());
}
- owner.tempWhitelistForPendingIntentLocked(Binder.getCallingPid(),
- Binder.getCallingUid(), uid, whitelistDuration, tag.toString());
+ owner.tempWhitelistForPendingIntentLocked(callingPid,
+ callingUid, uid, whitelistDuration, tag.toString());
}
- final long origId = Binder.clearCallingIdentity();
-
boolean sendFinish = finishedReceiver != null;
int userId = key.userId;
if (userId == UserHandle.USER_CURRENT) {
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 672f563..34cdb54 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.app.RemoteAction;
+import android.content.res.Configuration;
import android.graphics.Rect;
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
@@ -50,8 +51,21 @@
void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
boolean schedulePipModeChangedOnAnimationEnd) {
- getWindowContainerController().animateResizePinnedStack(toBounds, sourceHintBounds,
- animationDuration, schedulePipModeChangedOnAnimationEnd);
+ if (skipResizeAnimation(toBounds == null /* toFullscreen */)) {
+ mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
+ } else {
+ getWindowContainerController().animateResizePinnedStack(toBounds, sourceHintBounds,
+ animationDuration, schedulePipModeChangedOnAnimationEnd);
+ }
+ }
+
+ private boolean skipResizeAnimation(boolean toFullscreen) {
+ if (!toFullscreen) {
+ return false;
+ }
+ final Configuration parentConfig = getParent().getConfiguration();
+ final ActivityRecord top = topRunningNonOverlayTaskActivity();
+ return top != null && !top.isConfigurationCompatible(parentConfig);
}
void setPictureInPictureAspectRatio(float aspectRatio) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index b025385..fbc2bd2 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -103,7 +103,6 @@
int renderThreadTid; // TID for RenderThread
boolean serviceb; // Process currently is on the service B list
boolean serviceHighRam; // We are forcing to service B list due to its RAM use
- boolean setIsForeground; // Running foreground UI when last set?
boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle?
boolean hasClientActivities; // Are there any client services with activities?
boolean hasStartedServices; // Are there any started services running in this process?
@@ -303,9 +302,8 @@
pw.print(" hasAboveClient="); pw.print(hasAboveClient);
pw.print(" treatLikeActivity="); pw.println(treatLikeActivity);
}
- if (setIsForeground || foregroundServices || forcingToForeground != null) {
- pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);
- pw.print(" foregroundServices="); pw.print(foregroundServices);
+ if (foregroundServices || forcingToForeground != null) {
+ pw.print(prefix); pw.print("foregroundServices="); pw.print(foregroundServices);
pw.print(" forcingToForeground="); pw.println(forcingToForeground);
}
if (reportedInteraction || fgInteractionTime != 0) {
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index 7d2bc5b..f5d7b68 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -104,7 +104,7 @@
};
private final TaskStackConsumer mNotifyPinnedActivityRestartAttempt = (l, m) -> {
- l.onPinnedActivityRestartAttempt();
+ l.onPinnedActivityRestartAttempt(m.arg1 != 0);
};
private final TaskStackConsumer mNotifyPinnedStackAnimationStarted = (l, m) -> {
@@ -300,10 +300,11 @@
* running in the pinned stack and the activity was not actually started, but the task is
* either brought to the front or a new Intent is delivered to it.
*/
- void notifyPinnedActivityRestartAttempt() {
+ void notifyPinnedActivityRestartAttempt(boolean clearedTask) {
mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
final Message msg =
- mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
+ mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG,
+ clearedTask ? 1 : 0, 0);
forAllLocalListeners(mNotifyPinnedActivityRestartAttempt, msg);
msg.sendToTarget();
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 22d1bd1..37d3cd4 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -550,15 +550,11 @@
boolean kept = true;
if (updatedConfig) {
final ActivityRecord r = topRunningActivityLocked();
- if (r != null) {
+ if (r != null && !deferResume) {
kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow);
-
- if (!deferResume) {
- // All other activities must be made visible with their correct configuration.
- mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
- if (!kept) {
- mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
- }
+ mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
+ if (!kept) {
+ mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
}
}
@@ -2236,12 +2232,6 @@
return mLastNonFullscreenBounds;
}
- boolean canMatchRootAffinity() {
- // We don't allow root affinity matching on the pinned stack as no other task should
- // be launching in it based on affinity.
- return rootAffinity != null && getStackId() != PINNED_STACK_ID;
- }
-
void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index c0fb77f..c411bce 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -35,6 +35,7 @@
int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
long lastBackgroundTime;
boolean ephemeral;
+ boolean foregroundServices;
boolean curWhitelist;
boolean setWhitelist;
boolean idle;
@@ -102,6 +103,7 @@
public void reset() {
curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+ foregroundServices = false;
}
public void updateHasInternetPermission() {
@@ -131,6 +133,9 @@
if (ephemeral) {
sb.append(" ephemeral");
}
+ if (foregroundServices) {
+ sb.append(" fgServices");
+ }
if (curWhitelist) {
sb.append(" whitelist");
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e2b838f..e9555f7 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3251,9 +3251,10 @@
if (deviceList.size() > 0) {
btDevice = deviceList.get(0);
int state = mA2dp.getConnectionState(btDevice);
+ int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
int delay = checkSendBecomingNoisyIntent(
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
+ AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
+ AudioSystem.DEVICE_NONE);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_A2DP_SINK_CONNECTION_STATE,
state,
@@ -3381,9 +3382,8 @@
}
}
if (toRemove != null) {
- int delay = checkSendBecomingNoisyIntent(
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- 0);
+ int delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ 0, AudioSystem.DEVICE_NONE);
for (int i = 0; i < toRemove.size(); i++) {
makeA2dpDeviceUnavailableLater(toRemove.valueAt(i), delay);
}
@@ -3919,7 +3919,7 @@
Slog.i(TAG, "setWiredDeviceConnectionState(" + state + " nm: " + name + " addr:"
+ address + ")");
}
- int delay = checkSendBecomingNoisyIntent(type, state);
+ int delay = checkSendBecomingNoisyIntent(type, state, AudioSystem.DEVICE_NONE);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
0 /* arg1 unused */,
@@ -3931,14 +3931,25 @@
public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
{
+ if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE)) {
+ return 0;
+ }
+ return setBluetoothA2dpDeviceConnectionStateInt(
+ device, state, profile, AudioSystem.DEVICE_NONE);
+ }
+
+ public int setBluetoothA2dpDeviceConnectionStateInt(
+ BluetoothDevice device, int state, int profile, int musicDevice)
+ {
int delay;
if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
throw new IllegalArgumentException("invalid profile " + profile);
}
synchronized (mConnectedDevices) {
if (profile == BluetoothProfile.A2DP) {
+ int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
+ intState, musicDevice);
} else {
delay = 0;
}
@@ -5162,16 +5173,21 @@
int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
synchronized (mConnectedDevices) {
+ if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE)) {
+ return;
+ }
final String key = makeDeviceListKey(device, address);
final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
if (deviceSpec != null) {
// Device is connected
+ int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
if (AudioSystem.handleDeviceConfigChange(device, address,
btDevice.getName()) != AudioSystem.AUDIO_STATUS_OK) {
// force A2DP device disconnection in case of error so that AudioService state is
// consistent with audio policy manager state
- setBluetoothA2dpDeviceConnectionState(
- btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP_SINK);
+ setBluetoothA2dpDeviceConnectionStateInt(
+ btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
+ musicDevice);
}
}
}
@@ -5242,7 +5258,9 @@
// must be called before removing the device from mConnectedDevices
// Called synchronized on mConnectedDevices
- private int checkSendBecomingNoisyIntent(int device, int state) {
+ // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
+ // from AudioSystem
+ private int checkSendBecomingNoisyIntent(int device, int state, int musicDevice) {
int delay = 0;
if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
int devices = 0;
@@ -5253,8 +5271,13 @@
devices |= dev;
}
}
- int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
- if ((device == musicDevice) && (device == devices)) {
+ if (musicDevice == AudioSystem.DEVICE_NONE) {
+ musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
+ }
+ // ignore condition on device being actually used for music when in communication
+ // because music routing is altered in this case.
+ if (((device == musicDevice) || isInCommunication()) && (device == devices)) {
+ mAudioHandler.removeMessages(MSG_BROADCAST_AUDIO_BECOMING_NOISY);
sendMsg(mAudioHandler,
MSG_BROADCAST_AUDIO_BECOMING_NOISY,
SENDMSG_REPLACE,
@@ -5338,6 +5361,11 @@
}
}
+ private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
+ AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
+ AudioSystem.DEVICE_OUT_LINE |
+ AudioSystem.DEVICE_OUT_ALL_USB;
+
private void onSetWiredDeviceConnectionState(int device, int state, String address,
String deviceName, String caller) {
if (DEBUG_DEVICES) {
@@ -5349,9 +5377,7 @@
}
synchronized (mConnectedDevices) {
- if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
- (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
- (device == AudioSystem.DEVICE_OUT_LINE))) {
+ if ((state == 0) && ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
setBluetoothA2dpOnInt(true);
}
boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) ||
@@ -5362,9 +5388,7 @@
return;
}
if (state != 0) {
- if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
- (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
- (device == AudioSystem.DEVICE_OUT_LINE)) {
+ if ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
setBluetoothA2dpOnInt(false);
}
if ((device & mSafeMediaVolumeDevices) != 0) {
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index 3bc603f..93a22494 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -342,6 +342,7 @@
mFocusLossWasNotified = false;
// before dispatching a focus loss, check if the following conditions are met:
// 1/ the framework is not supposed to notify the focus loser on a DUCK loss
+ // (i.e. it has a focus controller that implements a ducking policy)
// 2/ it is a DUCK loss
// 3/ the focus loser isn't flagged as pausing in a DUCK loss
// if they are, do not notify the focus loser
@@ -365,7 +366,14 @@
&& fr != null) {
// candidate for enforcement by the framework
if (fr.mCallingUid != this.mCallingUid) {
- handled = mFocusController.duckPlayers(fr, this);
+ if ((mGrantFlags
+ & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) {
+ // the focus loser declared it would pause instead of duck, let it
+ // handle it (the framework doesn't pause for apps)
+ handled = false;
+ } else {
+ handled = mFocusController.duckPlayers(fr, this);
+ }
} // else: the focus change is within the same app, so let the dispatching
// happen as if the framework was not involved.
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index b3d2e30..3677905 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -197,11 +197,13 @@
public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 10;
/**
- * Message to self indicating sign-in app should be launched.
+ * Message indicating sign-in app should be launched.
* Sent by mLaunchCaptivePortalAppBroadcastReceiver when the
- * user touches the sign in notification.
+ * user touches the sign in notification, or sent by
+ * ConnectivityService when the user touches the "sign into
+ * network" button in the wifi access point detail page.
*/
- private static final int CMD_LAUNCH_CAPTIVE_PORTAL_APP = BASE + 11;
+ public static final int CMD_LAUNCH_CAPTIVE_PORTAL_APP = BASE + 11;
/**
* Retest network to see if captive portal is still in place.
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index d1275bb..7849896 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -47,7 +47,6 @@
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
-import com.android.server.vr.VrManagerService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Calendar;
@@ -62,7 +61,6 @@
implements NightDisplayController.Callback {
private static final String TAG = "NightDisplayService";
- private static final boolean DEBUG = false;
/**
* The transition time, in milliseconds, for Night Display to turn on/off.
@@ -151,8 +149,9 @@
@Override
public void onBootPhase(int phase) {
- if (phase == PHASE_SYSTEM_SERVICES_READY) {
- IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
+ if (phase >= PHASE_SYSTEM_SERVICES_READY) {
+ final IVrManager vrManager = IVrManager.Stub.asInterface(
+ getBinderService(Context.VR_SERVICE));
if (vrManager != null) {
try {
vrManager.registerListener(mVrStateCallbacks);
@@ -160,7 +159,9 @@
Slog.e(TAG, "Failed to register VR mode state listener: " + e);
}
}
- } else if (phase == PHASE_BOOT_COMPLETED) {
+ }
+
+ if (phase >= PHASE_BOOT_COMPLETED) {
mBootCompleted = true;
// Register listeners now that boot is complete.
@@ -284,12 +285,18 @@
if (mIsActivated == null || mIsActivated != activated) {
Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
- if (mAutoMode != null) {
- mAutoMode.onActivated(activated);
+ if (mIsActivated != null) {
+ Secure.putLongForUser(getContext().getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
+ mCurrentUser);
}
mIsActivated = activated;
+ if (mAutoMode != null) {
+ mAutoMode.onActivated(activated);
+ }
+
applyTint(false);
}
}
@@ -401,7 +408,7 @@
* Set the color transformation {@code MATRIX_NIGHT} to the given color temperature.
*
* @param colorTemperature color temperature in Kelvin
- * @param outTemp the 4x4 display transformation matrix for that color temperature
+ * @param outTemp the 4x4 display transformation matrix for that color temperature
*/
private void setMatrix(int colorTemperature, float[] outTemp) {
if (outTemp.length != 16) {
@@ -423,8 +430,22 @@
outTemp[10] = blue;
}
+ private Calendar getLastActivatedTime() {
+ final ContentResolver cr = getContext().getContentResolver();
+ final long lastActivatedTimeMillis = Secure.getLongForUser(
+ cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mCurrentUser);
+ if (lastActivatedTimeMillis < 0) {
+ return null;
+ }
+
+ final Calendar lastActivatedTime = Calendar.getInstance();
+ lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
+ return lastActivatedTime;
+ }
+
private abstract class AutoMode implements NightDisplayController.Callback {
public abstract void onStart();
+
public abstract void onStop();
}
@@ -438,7 +459,7 @@
private Calendar mLastActivatedTime;
- public CustomAutoMode() {
+ CustomAutoMode() {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mTimeChangedReceiver = new BroadcastReceiver() {
@Override
@@ -452,10 +473,10 @@
final Calendar now = Calendar.getInstance();
final Calendar startTime = mStartTime.getDateTimeBefore(now);
final Calendar endTime = mEndTime.getDateTimeAfter(startTime);
- final boolean activated = now.before(endTime);
- boolean setActivated = mIsActivated == null || mLastActivatedTime == null;
- if (!setActivated && mIsActivated != activated) {
+ boolean activate = now.before(endTime);
+ if (mLastActivatedTime != null) {
+ // Convert mLastActivatedTime to the current timezone if needed.
final TimeZone currentTimeZone = now.getTimeZone();
if (!currentTimeZone.equals(mLastActivatedTime.getTimeZone())) {
final int year = mLastActivatedTime.get(Calendar.YEAR);
@@ -470,17 +491,16 @@
mLastActivatedTime.set(Calendar.MINUTE, minute);
}
- if (mIsActivated) {
- setActivated = now.before(mStartTime.getDateTimeBefore(mLastActivatedTime))
- || now.after(mEndTime.getDateTimeAfter(mLastActivatedTime));
- } else {
- setActivated = now.before(mEndTime.getDateTimeBefore(mLastActivatedTime))
- || now.after(mStartTime.getDateTimeAfter(mLastActivatedTime));
+ // Maintain the existing activated state if within the current period.
+ if (mLastActivatedTime.before(now)
+ && mLastActivatedTime.after(startTime)
+ && (mLastActivatedTime.after(endTime) || now.before(endTime))) {
+ activate = mController.isActivated();
}
}
- if (setActivated) {
- mController.setActivated(activated);
+ if (mIsActivated == null || mIsActivated != activate) {
+ mController.setActivated(activate);
}
updateNextAlarm(mIsActivated, now);
}
@@ -502,6 +522,8 @@
mStartTime = mController.getCustomStartTime();
mEndTime = mController.getCustomEndTime();
+ mLastActivatedTime = getLastActivatedTime();
+
// Force an update to initialize state.
updateActivated();
}
@@ -516,11 +538,8 @@
@Override
public void onActivated(boolean activated) {
- final Calendar now = Calendar.getInstance();
- if (mIsActivated != null) {
- mLastActivatedTime = now;
- }
- updateNextAlarm(activated, now);
+ mLastActivatedTime = getLastActivatedTime();
+ updateNextAlarm(activated, Calendar.getInstance());
}
@Override
@@ -550,33 +569,33 @@
private Calendar mLastActivatedTime;
- public TwilightAutoMode() {
+ TwilightAutoMode() {
mTwilightManager = getLocalService(TwilightManager.class);
}
private void updateActivated(TwilightState state) {
- final boolean isNight = state != null && state.isNight();
- boolean setActivated = mIsActivated == null || mIsActivated != isNight;
- if (setActivated && state != null && mLastActivatedTime != null) {
+ boolean activate = state != null && state.isNight();
+ if (state != null && mLastActivatedTime != null) {
+ final Calendar now = Calendar.getInstance();
final Calendar sunrise = state.sunrise();
final Calendar sunset = state.sunset();
- if (sunrise.before(sunset)) {
- setActivated = mLastActivatedTime.before(sunrise)
- || mLastActivatedTime.after(sunset);
- } else {
- setActivated = mLastActivatedTime.before(sunset)
- || mLastActivatedTime.after(sunrise);
+
+ // Maintain the existing activated state if within the current period.
+ if (mLastActivatedTime.before(now)
+ && (mLastActivatedTime.after(sunrise) ^ mLastActivatedTime.after(sunset))) {
+ activate = mController.isActivated();
}
}
- if (setActivated) {
- mController.setActivated(isNight);
+ if (mIsActivated == null || mIsActivated != activate) {
+ mController.setActivated(activate);
}
}
@Override
public void onStart() {
mTwilightManager.registerListener(this, mHandler);
+ mLastActivatedTime = getLastActivatedTime();
// Force an update to initialize state.
updateActivated(mTwilightManager.getLastTwilightState());
@@ -591,7 +610,7 @@
@Override
public void onActivated(boolean activated) {
if (mIsActivated != null) {
- mLastActivatedTime = Calendar.getInstance();
+ mLastActivatedTime = getLastActivatedTime();
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index aafc9a8..0e52871 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -230,6 +230,9 @@
private static native void nativeReloadDeviceAliases(long ptr);
private static native String nativeDump(long ptr);
private static native void nativeMonitor(long ptr);
+ private static native boolean nativeIsInputDeviceEnabled(long ptr, int deviceId);
+ private static native void nativeEnableInputDevice(long ptr, int deviceId);
+ private static native void nativeDisableInputDevice(long ptr, int deviceId);
private static native void nativeSetPointerIconType(long ptr, int iconId);
private static native void nativeReloadPointerIcons(long ptr);
private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
@@ -639,6 +642,32 @@
return null;
}
+ // Binder call
+ @Override
+ public boolean isInputDeviceEnabled(int deviceId) {
+ return nativeIsInputDeviceEnabled(mPtr, deviceId);
+ }
+
+ // Binder call
+ @Override
+ public void enableInputDevice(int deviceId) {
+ if (!checkCallingPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE,
+ "enableInputDevice()")) {
+ throw new SecurityException("Requires DISABLE_INPUT_DEVICE permission");
+ }
+ nativeEnableInputDevice(mPtr, deviceId);
+ }
+
+ // Binder call
+ @Override
+ public void disableInputDevice(int deviceId) {
+ if (!checkCallingPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE,
+ "disableInputDevice()")) {
+ throw new SecurityException("Requires DISABLE_INPUT_DEVICE permission");
+ }
+ nativeDisableInputDevice(mPtr, deviceId);
+ }
+
/**
* Gets the ids of all input devices in the system.
* @return The input device ids.
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 73beecf..bdcf642 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -184,8 +184,7 @@
scheduleOpTimeOutLocked();
final Intent intent = new Intent().setComponent(job.getServiceComponent());
boolean binding = mContext.bindServiceAsUser(intent, this,
- Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
- | Context.BIND_IMPORTANT_BACKGROUND,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
new UserHandle(job.getUserId()));
if (!binding) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index e07156e..a94ed60 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -129,10 +129,11 @@
brightnessMode = mLastBrightnessMode;
}
- if ((color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
- mBrightnessMode != brightnessMode)) {
+ if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS ||
+ offMS != mOffMS || mBrightnessMode != brightnessMode) {
if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
+ Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
+ mInitialized = true;
mLastColor = mColor;
mColor = color;
mMode = mode;
@@ -164,6 +165,7 @@
private int mLastColor;
private boolean mVrModeEnabled;
private boolean mUseLowPersistenceForVR;
+ private boolean mInitialized;
}
public LightsService(Context context) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 9620544..4b632fe 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -384,6 +384,8 @@
// Wakelocks
private final static String WAKELOCK_KEY = "GnssLocationProvider";
private final PowerManager.WakeLock mWakeLock;
+ private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderXtraDownload";
+ private final PowerManager.WakeLock mDownloadXtraWakeLock;
// Alarms
private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
@@ -691,6 +693,11 @@
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
mWakeLock.setReferenceCounted(true);
+ // Create a separate wake lock for xtra downloader as it may be released due to timeout.
+ mDownloadXtraWakeLock = mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY);
+ mDownloadXtraWakeLock.setReferenceCounted(true);
+
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
@@ -995,7 +1002,7 @@
mDownloadXtraDataPending = STATE_DOWNLOADING;
// hold wake lock while task runs
- mWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
+ mDownloadXtraWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
@@ -1017,13 +1024,17 @@
mXtraBackOff.nextBackoffMillis());
}
- // release wake lock held by task
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- } else {
- Log.e(TAG, "WakeLock expired before release in handleDownloadXtraData()");
+ // Release wake lock held by task, synchronize on mLock in case multiple
+ // download tasks overrun.
+ synchronized (mLock) {
+ if (mDownloadXtraWakeLock.isHeld()) {
+ mDownloadXtraWakeLock.release();
+ if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadXtraData()");
+ } else {
+ Log.e(TAG, "WakeLock expired before release in "
+ + "handleDownloadXtraData()");
+ }
}
- Log.i(TAG, "WakeLock released by handleDownloadXtraData()");
}
});
}
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 63647ff..8caaaa1 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -73,11 +73,13 @@
// Next: sufficiently import person to person communication
boolean leftPeople = isImportantPeople(left);
boolean rightPeople = isImportantPeople(right);
+ final int contactAffinityComparison =
+ Float.compare(left.getContactAffinity(), right.getContactAffinity());
if (leftPeople && rightPeople){
// by contact proximity, close to far. if same proximity, check further fields.
- if (Float.compare(left.getContactAffinity(), right.getContactAffinity()) != 0) {
- return -1 * Float.compare(left.getContactAffinity(), right.getContactAffinity());
+ if (contactAffinityComparison != 0) {
+ return -1 * contactAffinityComparison;
}
} else if (leftPeople != rightPeople) {
// People, messaging higher than non-messaging
@@ -91,6 +93,11 @@
return -1 * Integer.compare(leftImportance, rightImportance);
}
+ // by contact proximity, close to far. if same proximity, check further fields.
+ if (contactAffinityComparison != 0) {
+ return -1 * contactAffinityComparison;
+ }
+
// Whether or not the notification can bypass DND.
final int leftPackagePriority = left.getPackagePriority();
final int rightPackagePriority = right.getPackagePriority();
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index 31ed350..4981d5c 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -19,6 +19,7 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
+import android.net.Uri;
import android.service.notification.NotificationListenerService;
import android.util.Log;
import android.util.Slog;
@@ -46,12 +47,13 @@
}
if (record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT) {
- final Notification notification = record.getNotification();
- if ((notification.defaults & Notification.DEFAULT_VIBRATE) != 0 ||
- notification.vibrate != null ||
- (notification.defaults & Notification.DEFAULT_SOUND) != 0 ||
- notification.sound != null ||
- notification.fullScreenIntent != null) {
+ if (record.getSound() != null && record.getSound() != Uri.EMPTY) {
+ record.setRecentlyIntrusive(true);
+ }
+ if (record.getVibration() != null) {
+ record.setRecentlyIntrusive(true);
+ }
+ if (record.getNotification().fullScreenIntent != null) {
record.setRecentlyIntrusive(true);
}
}
@@ -64,7 +66,11 @@
@Override
public void applyChangesLocked(NotificationRecord record) {
- record.setRecentlyIntrusive(false);
+ // there will be another reconsideration in the message queue HANG_TIME_MS
+ // from each time this record alerts, which can finally clear this flag.
+ if ((System.currentTimeMillis() - record.getLastIntrusive()) >= HANG_TIME_MS) {
+ record.setRecentlyIntrusive(false);
+ }
}
};
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8b84205..1d843c1 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -884,6 +884,8 @@
} else if (action.equals(Intent.ACTION_USER_REMOVED)) {
final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
mZenModeHelper.onUserRemoved(user);
+ mRankingHelper.onUserRemoved(user);
+ savePolicyFile();
} else if (action.equals(Intent.ACTION_USER_UNLOCKED)) {
final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
mConditionProviders.onUserUnlocked(user);
@@ -1477,7 +1479,7 @@
return ;
}
- final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg));
+ final boolean isSystemToast = isCallerSystemOrPhone() || ("android".equals(pkg));
final boolean isPackageSuspended =
isPackageSuspendedForUser(pkg, Binder.getCallingUid());
@@ -1581,12 +1583,10 @@
Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg);
// Don't allow client applications to cancel foreground service notis or autobundled
// summaries.
+ final int mustNotHaveFlags = isCallingUidSystem() ? 0 :
+ (Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_AUTOGROUP_SUMMARY);
cancelNotification(Binder.getCallingUid(), Binder.getCallingPid(), pkg, tag, id, 0,
- (Binder.getCallingUid() == Process.SYSTEM_UID
- ? 0 : Notification.FLAG_FOREGROUND_SERVICE)
- | (Binder.getCallingUid() == Process.SYSTEM_UID
- ? 0 : Notification.FLAG_AUTOGROUP_SUMMARY), false, userId,
- REASON_APP_CANCEL, null);
+ mustNotHaveFlags, false, userId, REASON_APP_CANCEL, null);
}
@Override
@@ -2452,7 +2452,7 @@
}
private void enforceSystemOrSystemUI(String message) {
- if (isCallerSystem()) return;
+ if (isCallerSystemOrPhone()) return;
getContext().enforceCallingPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
message);
}
@@ -2871,7 +2871,8 @@
adjustedSbn.getUser(), GroupHelper.AUTOGROUP_KEY,
System.currentTimeMillis());
summaryRecord = new NotificationRecord(getContext(), summarySbn,
- notificationRecord.getChannel());
+ notificationRecord.getChannel(), mRankingHelper.supportsChannels(
+ summarySbn.getPackageName(), summarySbn.getUid()));
summaries.put(pkg, summarySbn.getKey());
}
}
@@ -3191,12 +3192,6 @@
final NotificationChannel channel = mRankingHelper.getNotificationChannel(pkg,
notificationUid, channelId, false /* includeDeleted */);
if (channel == null) {
- // STOPSHIP TODO: remove before release - should always throw without a valid channel.
- if (channelId == null) {
- Log.e(TAG, "Cannot post notification without channel ID when targeting O "
- + " - notification=" + notification);
- return;
- }
final String noChannelStr = "No Channel found for "
+ "pkg=" + pkg
+ ", channelId=" + channelId
@@ -3206,25 +3201,18 @@
+ ", incomingUserId=" + incomingUserId
+ ", notificationUid=" + notificationUid
+ ", notification=" + notification;
- // STOPSHIP TODO: should throw instead of logging or toasting.
- // throw new IllegalArgumentException(noChannelStr);
Log.e(TAG, noChannelStr);
- doDebugOnlyToast("Developer warning for package \"" + pkg + "\"\n" +
+ doChannelWarningToast("Developer warning for package \"" + pkg + "\"\n" +
"Failed to post notification on channel \"" + channelId + "\"\n" +
"See log for more details");
return;
- } else if (channelId == null && shouldWarnUseChannels(pkg, notificationUid)) {
- // STOPSHIP TODO: remove once default channel is removed for all apps that target O.
- Log.e(TAG, "Developer Warning for package " + pkg
- + ", no channel specified for posted notification: " + notification);
- doDebugOnlyToast("Developer warning for package \"" + pkg + "\"\n" +
- "Posted notification should specify a channel");
}
final StatusBarNotification n = new StatusBarNotification(
pkg, opPkg, id, tag, notificationUid, callingPid, notification,
user, null, System.currentTimeMillis());
- final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
+ final NotificationRecord r = new NotificationRecord(getContext(), n, channel,
+ mRankingHelper.supportsChannels(pkg, notificationUid));
if (!checkDisqualifyingFeatures(userId, notificationUid, id,tag, r)) {
return;
@@ -3250,8 +3238,10 @@
mHandler.post(new EnqueueNotificationRunnable(userId, r));
}
- private void doDebugOnlyToast(CharSequence toastText) {
- if (Build.IS_DEBUGGABLE) {
+ private void doChannelWarningToast(CharSequence toastText) {
+ final boolean warningEnabled = Settings.System.getInt(getContext().getContentResolver(),
+ Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, 0) != 0;
+ if (warningEnabled || Build.IS_DEBUGGABLE) {
try {
Toast toast = Toast.makeText(getContext(), toastText, Toast.LENGTH_LONG);
toast.show();
@@ -3261,22 +3251,9 @@
}
}
- // STOPSHIP - Remove once RankingHelper deletes default channel for all apps targeting O.
- private boolean shouldWarnUseChannels(String pkg, int uid) {
- try {
- final int userId = UserHandle.getUserId(uid);
- final ApplicationInfo applicationInfo =
- mPackageManagerClient.getApplicationInfoAsUser(pkg, 0, userId);
- return applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1;
- } catch (NameNotFoundException e) {
- Slog.e(TAG, e.toString());
- return false;
- }
- }
-
private int resolveNotificationUid(String opPackageName, int callingUid, int userId) {
// The system can post notifications on behalf of any package it wants
- if (isCallerSystem() && opPackageName != null && !"android".equals(opPackageName)) {
+ if (isCallerSystemOrPhone() && opPackageName != null && !"android".equals(opPackageName)) {
try {
return getContext().getPackageManager()
.getPackageUidAsUser(opPackageName, userId);
@@ -3295,7 +3272,8 @@
private boolean checkDisqualifyingFeatures(int userId, int callingUid, int id, String tag,
NotificationRecord r) {
final String pkg = r.sbn.getPackageName();
- final boolean isSystemNotification = isUidSystem(callingUid) || ("android".equals(pkg));
+ final boolean isSystemNotification =
+ isUidSystemOrPhone(callingUid) || ("android".equals(pkg));
final boolean isNotificationFromListener = mListeners.isListenerPackage(pkg);
// Limit the number of notifications that any given package except the android
@@ -4192,7 +4170,7 @@
mNotificationsByKey.remove(recordInList.sbn.getKey());
wasPosted = true;
}
- if ((recordInList = findNotificationByListLocked(mEnqueuedNotifications, r.getKey()))
+ while ((recordInList = findNotificationByListLocked(mEnqueuedNotifications, r.getKey()))
!= null) {
mEnqueuedNotifications.remove(recordInList);
}
@@ -4217,7 +4195,9 @@
if (wasPosted) {
// status bar
if (r.getNotification().getSmallIcon() != null) {
- r.isCanceled = true;
+ if (reason != REASON_SNOOZED) {
+ r.isCanceled = true;
+ }
mListeners.notifyRemovedLocked(r.sbn, reason);
mHandler.post(new Runnable() {
@Override
@@ -4340,9 +4320,11 @@
updateLightsLocked();
} else {
// No notification was found, assume that it is snoozed and cancel it.
- final boolean wasSnoozed = mSnoozeHelper.cancel(userId, pkg, tag, id);
- if (wasSnoozed) {
- savePolicyFile();
+ if (reason != REASON_SNOOZED) {
+ final boolean wasSnoozed = mSnoozeHelper.cancel(userId, pkg, tag, id);
+ if (wasSnoozed) {
+ savePolicyFile();
+ }
}
}
}
@@ -4472,7 +4454,7 @@
void snoozeNotificationInt(String key, long duration, String snoozeCriterionId,
ManagedServiceInfo listener) {
String listenerName = listener == null ? null : listener.component.toShortString();
- if (duration <= 0 && snoozeCriterionId == null) {
+ if (duration <= 0 && snoozeCriterionId == null || key == null) {
return;
}
@@ -4686,24 +4668,30 @@
}
}
- protected boolean isUidSystem(int uid) {
+ protected boolean isCallingUidSystem() {
+ final int uid = Binder.getCallingUid();
+ return uid == Process.SYSTEM_UID;
+ }
+
+ protected boolean isUidSystemOrPhone(int uid) {
final int appid = UserHandle.getAppId(uid);
return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID || uid == 0);
}
- protected boolean isCallerSystem() {
- return isUidSystem(Binder.getCallingUid());
+ // TODO: Most calls should probably move to isCallerSystem.
+ protected boolean isCallerSystemOrPhone() {
+ return isUidSystemOrPhone(Binder.getCallingUid());
}
private void checkCallerIsSystem() {
- if (isCallerSystem()) {
+ if (isCallerSystemOrPhone()) {
return;
}
throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid());
}
private void checkCallerIsSystemOrSameApp(String pkg) {
- if (isCallerSystem()) {
+ if (isCallerSystemOrPhone()) {
return;
}
checkCallerIsSameApp(pkg);
@@ -4711,7 +4699,7 @@
private boolean isCallerInstantApp(String pkg) {
// System is always allowed to act for ephemeral apps.
- if (isCallerSystem()) {
+ if (isCallerSystemOrPhone()) {
return false;
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index b51a4d1..f019a5c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -85,6 +85,7 @@
// to communicate with the ranking module.
private float mContactAffinity;
private boolean mRecentlyIntrusive;
+ private long mLastIntrusive;
// is this notification currently being intercepted by Zen Mode?
private boolean mIntercept;
@@ -115,7 +116,7 @@
private int mSuppressedVisualEffects = 0;
private String mUserExplanation;
private String mPeopleExplanation;
- private boolean mPreChannelsNotification = true;
+ private boolean mSupportsChannels = false;
private Uri mSound;
private long[] mVibration;
private AudioAttributes mAttributes;
@@ -128,7 +129,7 @@
@VisibleForTesting
public NotificationRecord(Context context, StatusBarNotification sbn,
- NotificationChannel channel)
+ NotificationChannel channel, boolean supportsChannels)
{
this.sbn = sbn;
mOriginalFlags = sbn.getNotification().flags;
@@ -138,7 +139,7 @@
mContext = context;
stats = new NotificationUsageStats.SingleNotificationStats();
mChannel = channel;
- mPreChannelsNotification = isPreChannelsNotification();
+ mSupportsChannels = supportsChannels;
mSound = calculateSound();
mVibration = calculateVibration();
mAttributes = calculateAttributes();
@@ -146,27 +147,11 @@
mLight = calculateLights();
}
- private boolean isPreChannelsNotification() {
- try {
- if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(getChannel().getId())) {
- final ApplicationInfo applicationInfo =
- mContext.getPackageManager().getApplicationInfoAsUser(sbn.getPackageName(),
- 0, UserHandle.getUserId(sbn.getUid()));
- if (applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
- return true;
- }
- }
- } catch (NameNotFoundException e) {
- Slog.e(TAG, "Can't find package", e);
- }
- return false;
- }
-
private Uri calculateSound() {
final Notification n = sbn.getNotification();
Uri sound = mChannel.getSound();
- if (mPreChannelsNotification && (getChannel().getUserLockedFields()
+ if (!mSupportsChannels && (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_SOUND) == 0) {
final boolean useDefaultSound = (n.defaults & Notification.DEFAULT_SOUND) != 0;
@@ -191,7 +176,7 @@
: defaultLightColor;
Light light = getChannel().shouldShowLights() ? new Light(channelLightColor,
defaultLightOn, defaultLightOff) : null;
- if (mPreChannelsNotification
+ if (!mSupportsChannels
&& (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_LIGHTS) == 0) {
final Notification notification = sbn.getNotification();
@@ -222,7 +207,7 @@
} else {
vibration = null;
}
- if (mPreChannelsNotification
+ if (!mSupportsChannels
&& (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_VIBRATION) == 0) {
final Notification notification = sbn.getNotification();
@@ -244,7 +229,7 @@
attributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
}
- if (mPreChannelsNotification
+ if (!mSupportsChannels
&& (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_SOUND) == 0) {
if (n.audioAttributes != null) {
@@ -293,7 +278,7 @@
stats.requestedImportance = requestedImportance;
stats.isNoisy = mSound != null || mVibration != null;
- if (mPreChannelsNotification
+ if (!mSupportsChannels
&& (importance == IMPORTANCE_UNSPECIFIED
|| (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_IMPORTANCE) == 0)) {
@@ -460,7 +445,7 @@
pw.println(prefix + "mVisibleSinceMs=" + mVisibleSinceMs);
pw.println(prefix + "mUpdateTimeMs=" + mUpdateTimeMs);
pw.println(prefix + "mSuppressedVisualEffects= " + mSuppressedVisualEffects);
- if (mPreChannelsNotification) {
+ if (!mSupportsChannels) {
pw.println(prefix + String.format("defaults=0x%08x flags=0x%08x",
notification.defaults, notification.flags));
pw.println(prefix + "n.sound=" + notification.sound);
@@ -531,12 +516,19 @@
public void setRecentlyIntrusive(boolean recentlyIntrusive) {
mRecentlyIntrusive = recentlyIntrusive;
+ if (recentlyIntrusive) {
+ mLastIntrusive = System.currentTimeMillis();
+ }
}
public boolean isRecentlyIntrusive() {
return mRecentlyIntrusive;
}
+ public long getLastIntrusive() {
+ return mLastIntrusive;
+ }
+
public void setPackagePriority(int packagePriority) {
mPackagePriority = packagePriority;
}
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 4d19b52..14d796f 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -42,4 +42,6 @@
void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId);
void permanentlyDeleteNotificationChannels(String pkg, int uid);
ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid, boolean includeDeleted);
+
+ boolean supportsChannels(String pkg, int uid);
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 6d18c83..1e741de 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -273,31 +273,21 @@
}
private boolean shouldHaveDefaultChannel(Record r) throws NameNotFoundException {
+ if (supportsChannels(r)) {
+ return false;
+ }
+
final int userId = UserHandle.getUserId(r.uid);
- final ApplicationInfo applicationInfo = mPm.getApplicationInfoAsUser(r.pkg, 0, userId);
- if (applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
- // Pre-O apps should have it.
- return true;
+ final ApplicationInfo applicationInfo = mPm.getApplicationInfoAsUser(r.pkg,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ userId);
+ if (applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+ // O apps should not have the default channel.
+ return false;
}
- // STOPSHIP TODO: remove before release - O+ apps should never have a default channel.
- // But for now, leave the default channel until an app has created its first channel.
- boolean hasCreatedAChannel = false;
- final int size = r.channels.size();
- for (int i = 0; i < size; i++) {
- final NotificationChannel notificationChannel = r.channels.valueAt(i);
- if (notificationChannel != null &&
- !notificationChannel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
- hasCreatedAChannel = true;
- break;
- }
- }
- if (!hasCreatedAChannel) {
- return true;
- }
-
- // Otherwise, should not have the default channel.
- return false;
+ // Otherwise, this app should have the default channel.
+ return true;
}
private void deleteDefaultChannelIfNeeded(Record r) throws NameNotFoundException {
@@ -516,6 +506,31 @@
}
@Override
+ public boolean supportsChannels(String pkg, int uid) {
+ Record r = getOrCreateRecord(pkg, uid);
+
+ if (r == null) {
+ return false;
+ }
+
+ if (r.channels.size() == 1
+ && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean supportsChannels(Record r) {
+ if (r.channels.size() == 1
+ && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ return false;
+ }
+
+ return (r.channels.size() > 0);
+ }
+
+ @Override
public void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromTargetApp) {
Preconditions.checkNotNull(pkg);
@@ -587,6 +602,10 @@
r.channels.put(channel.getId(), channel);
MetricsLogger.action(getChannelLog(channel, pkg).setType(
MetricsProto.MetricsEvent.TYPE_OPEN));
+
+ // Remove Default Channel.
+ r.channels.remove(NotificationChannel.DEFAULT_CHANNEL_ID);
+
updateConfig();
}
@@ -683,13 +702,7 @@
if (r == null) {
return;
}
- int N = r.channels.size() - 1;
- for (int i = N; i >= 0; i--) {
- String key = r.channels.keyAt(i);
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(key)) {
- r.channels.remove(key);
- }
- }
+ r.channels.clear();
updateConfig();
}
@@ -1027,6 +1040,18 @@
return packageChannels;
}
+ public void onUserRemoved(int userId) {
+ synchronized (mRecords) {
+ int N = mRecords.size();
+ for (int i = N - 1; i >= 0 ; i--) {
+ Record record = mRecords.valueAt(i);
+ if (UserHandle.getUserId(record.uid) == userId) {
+ mRecords.removeAt(i);
+ }
+ }
+ }
+ }
+
public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList,
int[] uidList) {
if (pkgList == null || pkgList.length == 0) {
@@ -1041,6 +1066,8 @@
final int uid = uidList[i];
synchronized (mRecords) {
mRecords.remove(recordKey(pkg, uid));
+ // reset to default settings and re-add misc channel for pre-O apps
+ getOrCreateRecord(pkg, uid);
}
mRestoredWithoutUids.remove(pkg);
updated = true;
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 42b4f57..a178a52 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -167,16 +167,10 @@
for (Map.Entry<String, NotificationRecord> record : records) {
final StatusBarNotification sbn = record.getValue().sbn;
if (Objects.equals(sbn.getTag(), tag) && sbn.getId() == id) {
- key = record.getKey();
+ record.getValue().isCanceled = true;
+ return true;
}
}
- if (key != null) {
- recordsForPkg.remove(key);
- cancelAlarm(userId, pkg, key);
- mPackages.remove(key);
- mUsers.remove(key);
- return true;
- }
}
}
return false;
@@ -190,7 +184,7 @@
final int N = userIds.length;
for (int i = 0; i < N; i++) {
final ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs =
- mSnoozedNotifications.remove(userIds[i]);
+ mSnoozedNotifications.get(userIds[i]);
if (snoozedPkgs != null) {
final int M = snoozedPkgs.size();
for (int j = 0; j < M; j++) {
@@ -198,10 +192,7 @@
if (records != null) {
int P = records.size();
for (int k = 0; k < P; k++) {
- final String key = records.keyAt(k);
- cancelAlarm(userId, snoozedPkgs.keyAt(j), key);
- mPackages.remove(key);
- mUsers.remove(key);
+ records.valueAt(k).isCanceled = true;
}
}
}
@@ -215,13 +206,10 @@
if (mSnoozedNotifications.containsKey(userId)) {
if (mSnoozedNotifications.get(userId).containsKey(pkg)) {
ArrayMap<String, NotificationRecord> records =
- mSnoozedNotifications.get(userId).remove(pkg);
+ mSnoozedNotifications.get(userId).get(pkg);
int N = records.size();
for (int i = 0; i < N; i++) {
- final String key = records.keyAt(i);
- cancelAlarm(userId, pkg, key);
- mPackages.remove(key);
- mUsers.remove(key);
+ records.valueAt(i).isCanceled = true;
}
return true;
}
@@ -229,16 +217,6 @@
return false;
}
- private void cancelAlarm(int userId, String pkg, String key) {
- long identity = Binder.clearCallingIdentity();
- try {
- final PendingIntent pi = createPendingIntent(pkg, key, userId);
- mAm.cancel(pi);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
/**
* Updates the notification record so the most up to date information is shown on re-post.
*/
@@ -252,6 +230,10 @@
if (pkgRecords == null) {
return;
}
+ NotificationRecord existing = pkgRecords.get(record.getKey());
+ if (existing != null && existing.isCanceled) {
+ return;
+ }
pkgRecords.put(record.getKey(), record);
}
@@ -274,8 +256,10 @@
return;
}
final NotificationRecord record = pkgRecords.remove(key);
+ mPackages.remove(key);
+ mUsers.remove(key);
- if (record != null) {
+ if (record != null && !record.isCanceled) {
MetricsLogger.action(record.getLogMaker()
.setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
.setType(MetricsProto.MetricsEvent.TYPE_OPEN));
@@ -309,10 +293,12 @@
mPackages.remove(groupSummaryKey);
mUsers.remove(groupSummaryKey);
- MetricsLogger.action(record.getLogMaker()
- .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
- .setType(MetricsProto.MetricsEvent.TYPE_OPEN));
- mCallback.repost(userId, record);
+ if (record != null && !record.isCanceled) {
+ MetricsLogger.action(record.getLogMaker()
+ .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
+ .setType(MetricsProto.MetricsEvent.TYPE_OPEN));
+ mCallback.repost(userId, record);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index 9d08004..09e9433 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -43,6 +43,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.NoSuchElementException;
import java.util.concurrent.TimeoutException;
/**
@@ -206,7 +207,9 @@
private void handleBinderDiedLocked() {
if (mRemoteInstance != null) {
- mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
+ try {
+ mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
+ } catch (NoSuchElementException ignore) { }
}
mRemoteInstance = null;
}
diff --git a/services/core/java/com/android/server/pm/InstructionSets.java b/services/core/java/com/android/server/pm/InstructionSets.java
index 5092ebf..f326f1d 100644
--- a/services/core/java/com/android/server/pm/InstructionSets.java
+++ b/services/core/java/com/android/server/pm/InstructionSets.java
@@ -34,7 +34,7 @@
*/
public class InstructionSets {
private static final String PREFERRED_INSTRUCTION_SET =
- VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);;
+ VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
public static String[] getAppDexInstructionSets(ApplicationInfo info) {
if (info.primaryCpuAbi != null) {
if (info.secondaryCpuAbi != null) {
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 4c0d9da..59bce8f 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -24,6 +24,7 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.util.Log;
@@ -54,6 +55,7 @@
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
+import static com.android.server.pm.PackageManagerService.WATCHDOG_TIMEOUT;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter;
import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;
@@ -67,13 +69,17 @@
public static final int DEX_OPT_SKIPPED = 0;
public static final int DEX_OPT_PERFORMED = 1;
public static final int DEX_OPT_FAILED = -1;
+ // One minute over PM WATCHDOG_TIMEOUT
+ private static final long WAKELOCK_TIMEOUT_MS = WATCHDOG_TIMEOUT + 1000 * 60;
/** Special library name that skips shared libraries check during compilation. */
public static final String SKIP_SHARED_LIBRARY_CHECK = "&";
+ @GuardedBy("mInstallLock")
private final Installer mInstaller;
private final Object mInstallLock;
+ @GuardedBy("mInstallLock")
private final PowerManager.WakeLock mDexoptWakeLock;
private volatile boolean mSystemReady;
@@ -111,21 +117,12 @@
return DEX_OPT_SKIPPED;
}
synchronized (mInstallLock) {
- // During boot the system doesn't need to instantiate and obtain a wake lock.
- // PowerManager might not be ready, but that doesn't mean that we can't proceed with
- // dexopt.
- final boolean useLock = mSystemReady;
- if (useLock) {
- mDexoptWakeLock.setWorkSource(new WorkSource(pkg.applicationInfo.uid));
- mDexoptWakeLock.acquire();
- }
+ final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid);
try {
return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles,
targetCompilationFilter, packageStats, isUsedByOtherApps);
} finally {
- if (useLock) {
- mDexoptWakeLock.release();
- }
+ releaseWakeLockLI(acquireTime);
}
}
}
@@ -250,26 +247,50 @@
public int dexOptSecondaryDexPath(ApplicationInfo info, String path, Set<String> isas,
String compilerFilter, boolean isUsedByOtherApps) {
synchronized (mInstallLock) {
- // During boot the system doesn't need to instantiate and obtain a wake lock.
- // PowerManager might not be ready, but that doesn't mean that we can't proceed with
- // dexopt.
- final boolean useLock = mSystemReady;
- if (useLock) {
- mDexoptWakeLock.setWorkSource(new WorkSource(info.uid));
- mDexoptWakeLock.acquire();
- }
+ final long acquireTime = acquireWakeLockLI(info.uid);
try {
return dexOptSecondaryDexPathLI(info, path, isas, compilerFilter,
isUsedByOtherApps);
} finally {
- if (useLock) {
- mDexoptWakeLock.release();
- }
+ releaseWakeLockLI(acquireTime);
}
}
}
@GuardedBy("mInstallLock")
+ private long acquireWakeLockLI(final int uid) {
+ // During boot the system doesn't need to instantiate and obtain a wake lock.
+ // PowerManager might not be ready, but that doesn't mean that we can't proceed with
+ // dexopt.
+ if (!mSystemReady) {
+ return -1;
+ }
+ mDexoptWakeLock.setWorkSource(new WorkSource(uid));
+ mDexoptWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
+ return SystemClock.elapsedRealtime();
+ }
+
+ @GuardedBy("mInstallLock")
+ private void releaseWakeLockLI(final long acquireTime) {
+ if (acquireTime < 0) {
+ return;
+ }
+ try {
+ if (mDexoptWakeLock.isHeld()) {
+ mDexoptWakeLock.release();
+ }
+ final long duration = SystemClock.elapsedRealtime() - acquireTime;
+ if (duration >= WAKELOCK_TIMEOUT_MS) {
+ Slog.wtf(TAG, "WakeLock " + mDexoptWakeLock.getTag()
+ + " time out. Operation took " + duration + " ms. Thread: "
+ + Thread.currentThread().getName());
+ }
+ } catch (Exception e) {
+ Slog.wtf(TAG, "Error while releasing " + mDexoptWakeLock.getTag() + " lock", e);
+ }
+ }
+
+ @GuardedBy("mInstallLock")
private int dexOptSecondaryDexPathLI(ApplicationInfo info, String path, Set<String> isas,
String compilerFilter, boolean isUsedByOtherApps) {
compilerFilter = getRealCompilerFilter(info, compilerFilter, isUsedByOtherApps);
@@ -613,9 +634,13 @@
@Override
protected int adjustDexoptNeeded(int dexoptNeeded) {
- // Ensure compilation, no matter the current state.
- // TODO: The return value is wrong when patchoat is needed.
- return DexFile.DEX2OAT_FROM_SCRATCH;
+ if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
+ // Ensure compilation by pretending a compiler filter change on the
+ // apk/odex location (the reason for the '-'. A positive value means
+ // the 'oat' location).
+ return -DexFile.DEX2OAT_FOR_FILTER;
+ }
+ return dexoptNeeded;
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e21a2b9..d61a43b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -127,6 +127,7 @@
import android.content.pm.AppsQueryHelper;
import android.content.pm.ChangedPackages;
import android.content.pm.ComponentInfo;
+import android.content.pm.IDexModuleRegisterCallback;
import android.content.pm.InstantAppRequest;
import android.content.pm.AuxiliaryResolveInfo;
import android.content.pm.FallbackCategoryProvider;
@@ -444,7 +445,7 @@
* minute but we sometimes do very lengthy I/O operations on this thread,
* such as installing multi-gigabyte applications, so ours needs to be longer.
*/
- private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes
+ static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes
/**
* Wall-clock timeout (in milliseconds) after which we *require* that an fstrim
@@ -4360,8 +4361,7 @@
}
SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getName(),
- // TODO: Remove cast for lib version once internally we support longs.
- (int) libInfo.getVersion(), libInfo.getType(),
+ libInfo.getVersion(), libInfo.getType(),
libInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr(libInfo,
flags, userId));
@@ -5871,10 +5871,9 @@
return mEphemeralAppsDisabled;
}
- private boolean isEphemeralAllowed(
+ private boolean isInstantAppAllowed(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
boolean skipPackageCheck) {
- final int callingUser = UserHandle.getCallingUserId();
if (mInstantAppResolverConnection == null) {
return false;
}
@@ -5974,7 +5973,13 @@
for (int i = 0; i < N; i++) {
ri = query.get(i);
if (ri.activityInfo.applicationInfo.isInstantApp()) {
- return ri;
+ final String packageName = ri.activityInfo.packageName;
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final long packedStatus = getDomainVerificationStatusLPr(ps, userId);
+ final int status = (int)(packedStatus >> 32);
+ if (status != INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
+ return ri;
+ }
}
}
ri = new ResolveInfo(mResolveInfo);
@@ -6418,7 +6423,7 @@
result = filterIfNotSystemUser(mActivities.queryIntent(
intent, resolvedType, flags, userId), userId);
addEphemeral = !ephemeralDisabled
- && isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/);
+ && isInstantAppAllowed(intent, result, userId, false /*skipPackageCheck*/);
// Check for cross profile results.
boolean hasNonNegativePriorityResult = hasNonNegativePriority(result);
xpResolveInfo = queryCrossProfileIntents(
@@ -6475,45 +6480,14 @@
// the caller wants to resolve for a particular package; however, there
// were no installed results, so, try to find an ephemeral result
addEphemeral = !ephemeralDisabled
- && isEphemeralAllowed(
+ && isInstantAppAllowed(
intent, null /*result*/, userId, true /*skipPackageCheck*/);
result = new ArrayList<ResolveInfo>();
}
}
}
if (addEphemeral) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
- final InstantAppRequest requestObject = new InstantAppRequest(
- null /*responseObj*/, intent /*origIntent*/, resolvedType,
- null /*callingPackage*/, userId, null /*verificationBundle*/);
- final AuxiliaryResolveInfo auxiliaryResponse =
- InstantAppResolver.doInstantAppResolutionPhaseOne(
- mContext, mInstantAppResolverConnection, requestObject);
- if (auxiliaryResponse != null) {
- if (DEBUG_EPHEMERAL) {
- Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
- }
- final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo);
- final PackageSetting ps =
- mSettings.mPackages.get(mInstantAppInstallerActivity.packageName);
- if (ps != null) {
- ephemeralInstaller.activityInfo = PackageParser.generateActivityInfo(
- mInstantAppInstallerActivity, 0, ps.readUserState(userId), userId);
- ephemeralInstaller.activityInfo.launchToken = auxiliaryResponse.token;
- ephemeralInstaller.auxiliaryInfo = auxiliaryResponse;
- // make sure this resolver is the default
- ephemeralInstaller.isDefault = true;
- ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
- | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
- // add a non-generic filter
- ephemeralInstaller.filter = new IntentFilter(intent.getAction());
- ephemeralInstaller.filter.addDataPath(
- intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL);
- ephemeralInstaller.instantAppAvailable = true;
- result.add(ephemeralInstaller);
- }
- }
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ result = maybeAddInstantAppInstaller(result, intent, resolvedType, flags, userId);
}
if (sortResult) {
Collections.sort(result, mResolvePrioritySorter);
@@ -6521,6 +6495,86 @@
return applyPostResolutionFilter(result, instantAppPkgName);
}
+ private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
+ String resolvedType, int flags, int userId) {
+ // first, check to see if we've got an instant app already installed
+ final boolean alreadyResolvedLocally = (flags & PackageManager.MATCH_INSTANT) != 0;
+ boolean localInstantAppAvailable = false;
+ boolean blockResolution = false;
+ if (!alreadyResolvedLocally) {
+ final List<ResolveInfo> instantApps = mActivities.queryIntent(intent, resolvedType,
+ flags
+ | PackageManager.MATCH_INSTANT
+ | PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY,
+ userId);
+ for (int i = instantApps.size() - 1; i >= 0; --i) {
+ final ResolveInfo info = instantApps.get(i);
+ final String packageName = info.activityInfo.packageName;
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps.getInstantApp(userId)) {
+ final long packedStatus = getDomainVerificationStatusLPr(ps, userId);
+ final int status = (int)(packedStatus >> 32);
+ final int linkGeneration = (int)(packedStatus & 0xFFFFFFFF);
+ if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
+ // there's a local instant application installed, but, the user has
+ // chosen to never use it; skip resolution and don't acknowledge
+ // an instant application is even available
+ if (DEBUG_EPHEMERAL) {
+ Slog.v(TAG, "Instant app marked to never run; pkg: " + packageName);
+ }
+ blockResolution = true;
+ break;
+ } else {
+ // we have a locally installed instant application; skip resolution
+ // but acknowledge there's an instant application available
+ if (DEBUG_EPHEMERAL) {
+ Slog.v(TAG, "Found installed instant app; pkg: " + packageName);
+ }
+ localInstantAppAvailable = true;
+ break;
+ }
+ }
+ }
+ }
+ // no app installed, let's see if one's available
+ AuxiliaryResolveInfo auxiliaryResponse = null;
+ if (!localInstantAppAvailable && !blockResolution) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
+ final InstantAppRequest requestObject = new InstantAppRequest(
+ null /*responseObj*/, intent /*origIntent*/, resolvedType,
+ null /*callingPackage*/, userId, null /*verificationBundle*/);
+ auxiliaryResponse =
+ InstantAppResolver.doInstantAppResolutionPhaseOne(
+ mContext, mInstantAppResolverConnection, requestObject);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ if (localInstantAppAvailable || auxiliaryResponse != null) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
+ }
+ final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo);
+ final PackageSetting ps =
+ mSettings.mPackages.get(mInstantAppInstallerActivity.packageName);
+ if (ps != null) {
+ ephemeralInstaller.activityInfo = PackageParser.generateActivityInfo(
+ mInstantAppInstallerActivity, 0, ps.readUserState(userId), userId);
+ ephemeralInstaller.activityInfo.launchToken = auxiliaryResponse.token;
+ ephemeralInstaller.auxiliaryInfo = auxiliaryResponse;
+ // make sure this resolver is the default
+ ephemeralInstaller.isDefault = true;
+ ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
+ // add a non-generic filter
+ ephemeralInstaller.filter = new IntentFilter(intent.getAction());
+ ephemeralInstaller.filter.addDataPath(
+ intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL);
+ ephemeralInstaller.instantAppAvailable = true;
+ result.add(ephemeralInstaller);
+ }
+ }
+ return result;
+ }
+
private static class CrossProfileDomainInfo {
/* ResolveInfo for IntentForwarderActivity to send the intent to the other profile */
ResolveInfo resolveInfo;
@@ -8729,6 +8783,31 @@
}
@Override
+ public void registerDexModule(String packageName, String dexModulePath, boolean isSharedModule,
+ IDexModuleRegisterCallback callback) {
+ int userId = UserHandle.getCallingUserId();
+ ApplicationInfo ai = getApplicationInfo(packageName, /*flags*/ 0, userId);
+ DexManager.RegisterDexModuleResult result;
+ if (ai == null) {
+ Slog.w(TAG, "Registering a dex module for a package that does not exist for the" +
+ " calling user. package=" + packageName + ", user=" + userId);
+ result = new DexManager.RegisterDexModuleResult(false, "Package not installed");
+ } else {
+ result = mDexManager.registerDexModule(ai, dexModulePath, isSharedModule, userId);
+ }
+
+ if (callback != null) {
+ mHandler.post(() -> {
+ try {
+ callback.onDexModuleRegistered(dexModulePath, result.success, result.message);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to callback after module registration " + dexModulePath, e);
+ }
+ });
+ }
+ }
+
+ @Override
public boolean performDexOpt(String packageName,
boolean checkProfiles, int compileReason, boolean force) {
int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
@@ -12611,7 +12690,7 @@
}
res.iconResourceId = info.icon;
res.system = res.activityInfo.applicationInfo.isSystemApp();
- res.instantAppAvailable = userState.instantApp;
+ res.isInstantAppAvailable = userState.instantApp;
return res;
}
@@ -17750,8 +17829,7 @@
for (int i = 0; i < versionCount; i++) {
SharedLibraryEntry libEntry = versionedLib.valueAt(i);
if (versionsCallerCanSee != null && versionsCallerCanSee.indexOfKey(
- // TODO: Remove cast for lib version once internally we support longs.
- (int) libEntry.info.getVersion()) < 0) {
+ libEntry.info.getVersion()) < 0) {
continue;
}
// TODO: We will change version code to long, so in the new API it is long
@@ -18463,11 +18541,6 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
synchronized (mPackages) {
- PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps == null) {
- Log.i(TAG, "Package doesn't exist in set block uninstall " + packageName);
- return false;
- }
// Cannot block uninstall of static shared libs as they are
// considered a part of the using app (emulating static linking).
// Also static libs are installed always on internal storage.
@@ -18477,12 +18550,7 @@
+ " providing static shared library: " + pkg.staticSharedLibName);
return false;
}
- if (!ps.getInstalled(userId)) {
- // Can't block uninstall for an app that is not installed or enabled.
- Log.i(TAG, "Package not installed in set block uninstall " + packageName);
- return false;
- }
- ps.setBlockUninstall(blockUninstall, userId);
+ mSettings.setBlockUninstallLPw(userId, packageName, blockUninstall);
mSettings.writePackageRestrictionsLPr(userId);
}
return true;
@@ -18491,12 +18559,7 @@
@Override
public boolean getBlockUninstallForUser(String packageName, int userId) {
synchronized (mPackages) {
- PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps == null) {
- Log.i(TAG, "Package doesn't exist in get block uninstall " + packageName);
- return false;
- }
- return ps.getBlockUninstall(userId);
+ return mSettings.getBlockUninstallLPr(userId, packageName);
}
}
@@ -18703,7 +18766,6 @@
null /*lastDisableAppCaller*/,
null /*enabledComponents*/,
null /*disabledComponents*/,
- false /*blockUninstall*/,
ps.readUserState(nextUserId).domainVerificationStatus,
0, PackageManager.INSTALL_REASON_UNKNOWN);
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index dfed72f..14f65eb 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -402,14 +402,6 @@
modifyUserState(userId).suspended = suspended;
}
- boolean getBlockUninstall(int userId) {
- return readUserState(userId).blockUninstall;
- }
-
- void setBlockUninstall(boolean blockUninstall, int userId) {
- modifyUserState(userId).blockUninstall = blockUninstall;
- }
-
boolean getInstantApp(int userId) {
return readUserState(userId).instantApp;
}
@@ -421,8 +413,8 @@
void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
boolean notLaunched, boolean hidden, boolean suspended, boolean instantApp,
String lastDisableAppCaller, ArraySet<String> enabledComponents,
- ArraySet<String> disabledComponents, boolean blockUninstall,
- int domainVerifState, int linkGeneration, int installReason) {
+ ArraySet<String> disabledComponents, int domainVerifState,
+ int linkGeneration, int installReason) {
PackageUserState state = modifyUserState(userId);
state.ceDataInode = ceDataInode;
state.enabled = enabled;
@@ -434,7 +426,6 @@
state.lastDisableAppCaller = lastDisableAppCaller;
state.enabledComponents = enabledComponents;
state.disabledComponents = disabledComponents;
- state.blockUninstall = blockUninstall;
state.domainVerificationStatus = domainVerifState;
state.appLinkGeneration = linkGeneration;
state.installReason = installReason;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index cea031e..44bcff2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -186,6 +186,8 @@
private static final String TAG_PERMISSIONS = "perms";
private static final String TAG_CHILD_PACKAGE = "child-package";
private static final String TAG_USES_STATIC_LIB = "uses-static-lib";
+ private static final String TAG_BLOCK_UNINSTALL_PACKAGES = "block-uninstall-packages";
+ private static final String TAG_BLOCK_UNINSTALL = "block-uninstall";
private static final String TAG_PERSISTENT_PREFERRED_ACTIVITIES =
"persistent-preferred-activities";
@@ -215,6 +217,8 @@
// New name for the above attribute.
private static final String ATTR_HIDDEN = "hidden";
private static final String ATTR_SUSPENDED = "suspended";
+ // Legacy, uninstall blocks are stored separately.
+ @Deprecated
private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
private static final String ATTR_ENABLED = "enabled";
private static final String ATTR_ENABLED_CALLER = "enabledCaller";
@@ -271,6 +275,9 @@
private final ArrayMap<String, PackageSetting> mDisabledSysPackages =
new ArrayMap<String, PackageSetting>();
+ /** List of packages that are blocked for uninstall for specific users */
+ private final SparseArray<ArraySet<String>> mBlockUninstallPackages = new SparseArray<>();
+
// Set of restored intent-filter verification states
private final ArrayMap<String, IntentFilterVerificationInfo> mRestoredIntentFilterVerifications =
new ArrayMap<String, IntentFilterVerificationInfo>();
@@ -756,7 +763,6 @@
null /*lastDisableAppCaller*/,
null /*enabledComponents*/,
null /*disabledComponents*/,
- false /*blockUninstall*/,
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
0, PackageManager.INSTALL_REASON_UNKNOWN);
}
@@ -1614,6 +1620,34 @@
}
}
+ void readBlockUninstallPackagesLPw(XmlPullParser parser, int userId)
+ throws XmlPullParserException, IOException {
+ int outerDepth = parser.getDepth();
+ int type;
+ ArraySet<String> packages = new ArraySet<>();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ String tagName = parser.getName();
+ if (tagName.equals(TAG_BLOCK_UNINSTALL)) {
+ String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
+ packages.add(packageName);
+ } else {
+ String msg = "Unknown element under " + TAG_BLOCK_UNINSTALL_PACKAGES + ": " +
+ parser.getName();
+ PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ if (packages.isEmpty()) {
+ mBlockUninstallPackages.remove(userId);
+ } else {
+ mBlockUninstallPackages.put(userId, packages);
+ }
+ }
+
void readPackageRestrictionsLPr(int userId) {
if (DEBUG_MU) {
Log.i(TAG, "Reading package restrictions for user=" + userId);
@@ -1662,7 +1696,6 @@
null /*lastDisableAppCaller*/,
null /*enabledComponents*/,
null /*disabledComponents*/,
- false /*blockUninstall*/,
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
0, PackageManager.INSTALL_REASON_UNKNOWN);
}
@@ -1768,9 +1801,12 @@
}
}
+ if (blockUninstall) {
+ setBlockUninstallLPw(userId, name, true);
+ }
ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
hidden, suspended, instantApp, enabledCaller, enabledComponents,
- disabledComponents, blockUninstall, verifState, linkGeneration,
+ disabledComponents, verifState, linkGeneration,
installReason);
} else if (tagName.equals("preferred-activities")) {
readPreferredActivitiesLPw(parser, userId);
@@ -1780,6 +1816,8 @@
readCrossProfileIntentFiltersLPw(parser, userId);
} else if (tagName.equals(TAG_DEFAULT_APPS)) {
readDefaultAppsLPw(parser, userId);
+ } else if (tagName.equals(TAG_BLOCK_UNINSTALL_PACKAGES)) {
+ readBlockUninstallPackagesLPw(parser, userId);
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
+ parser.getName());
@@ -1806,6 +1844,30 @@
}
}
+ void setBlockUninstallLPw(int userId, String packageName, boolean blockUninstall) {
+ ArraySet<String> packages = mBlockUninstallPackages.get(userId);
+ if (blockUninstall) {
+ if (packages == null) {
+ packages = new ArraySet<String>();
+ mBlockUninstallPackages.put(userId, packages);
+ }
+ packages.add(packageName);
+ } else if (packages != null) {
+ packages.remove(packageName);
+ if (packages.isEmpty()) {
+ mBlockUninstallPackages.remove(userId);
+ }
+ }
+ }
+
+ boolean getBlockUninstallLPr(int userId, String packageName) {
+ ArraySet<String> packages = mBlockUninstallPackages.get(userId);
+ if (packages == null) {
+ return false;
+ }
+ return packages.contains(packageName);
+ }
+
private ArraySet<String> readComponentsLPr(XmlPullParser parser)
throws IOException, XmlPullParserException {
ArraySet<String> components = null;
@@ -1976,6 +2038,20 @@
serializer.endTag(null, TAG_DEFAULT_APPS);
}
+ void writeBlockUninstallPackagesLPr(XmlSerializer serializer, int userId)
+ throws IOException {
+ ArraySet<String> packages = mBlockUninstallPackages.get(userId);
+ if (packages != null) {
+ serializer.startTag(null, TAG_BLOCK_UNINSTALL_PACKAGES);
+ for (int i = 0; i < packages.size(); i++) {
+ serializer.startTag(null, TAG_BLOCK_UNINSTALL);
+ serializer.attribute(null, ATTR_PACKAGE_NAME, packages.valueAt(i));
+ serializer.endTag(null, TAG_BLOCK_UNINSTALL);
+ }
+ serializer.endTag(null, TAG_BLOCK_UNINSTALL_PACKAGES);
+ }
+ }
+
void writePackageRestrictionsLPr(int userId) {
if (DEBUG_MU) {
Log.i(TAG, "Writing package restrictions for user=" + userId);
@@ -2038,9 +2114,6 @@
if (ustate.suspended) {
serializer.attribute(null, ATTR_SUSPENDED, "true");
}
- if (ustate.blockUninstall) {
- serializer.attribute(null, ATTR_BLOCK_UNINSTALL, "true");
- }
if (ustate.instantApp) {
serializer.attribute(null, ATTR_INSTANT_APP, "true");
}
@@ -2091,6 +2164,7 @@
writePersistentPreferredActivitiesLPr(serializer, userId);
writeCrossProfileIntentFiltersLPr(serializer, userId);
writeDefaultAppsLPr(serializer, userId);
+ writeBlockUninstallPackagesLPr(serializer, userId);
serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 7c89e1c..bed8f1a 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -555,8 +555,8 @@
}
@Override
- public void onCleanupUser(int userHandle) {
- mService.handleCleanupUser(userHandle);
+ public void onStopUser(int userHandle) {
+ mService.handleStopUser(userHandle);
}
@Override
@@ -606,9 +606,9 @@
}
/** lifecycle event */
- void handleCleanupUser(int userId) {
+ void handleStopUser(int userId) {
if (DEBUG) {
- Slog.d(TAG, "handleCleanupUser: user=" + userId);
+ Slog.d(TAG, "handleStopUser: user=" + userId);
}
synchronized (mLock) {
unloadUserLocked(userId);
@@ -3777,7 +3777,7 @@
Slog.i(TAG, "cmd: handleUnloadUser: user=" + mUserId);
- ShortcutService.this.handleCleanupUser(mUserId);
+ ShortcutService.this.handleStopUser(mUserId);
}
}
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 3d7cedc..be50eee 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -30,6 +30,7 @@
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageDexOptimizer;
+import com.android.server.pm.PackageManagerService;
import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.PackageManagerServiceCompilerMapping;
@@ -41,6 +42,7 @@
import java.util.Map;
import java.util.Set;
+import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
@@ -60,6 +62,7 @@
// Maps package name to code locations.
// It caches the code locations for the installed packages. This allows for
// faster lookups (no locks) when finding what package owns the dex file.
+ @GuardedBy("mPackageCodeLocationsCache")
private final Map<String, PackageCodeLocations> mPackageCodeLocationsCache;
// PackageDexUsage handles the actual I/O operations. It is responsible to
@@ -204,7 +207,7 @@
// In case there was an update, write the package use info to disk async.
// Note that we do the writing here and not in PackageDexUsage in order to be
// consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs
- // multiple updates in PackaeDexUsage before writing it).
+ // multiple updates in PackageDexUsage before writing it).
if (mPackageDexUsage.clearUsedByOtherApps(packageName)) {
mPackageDexUsage.maybeWriteAsync();
}
@@ -224,7 +227,7 @@
// In case there was an update, write the package use info to disk async.
// Note that we do the writing here and not in PackageDexUsage in order to be
// consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs
- // multiple updates in PackaeDexUsage before writing it).
+ // multiple updates in PackageDexUsage before writing it).
if (updated) {
mPackageDexUsage.maybeWriteAsync();
}
@@ -243,17 +246,22 @@
private void cachePackageCodeLocation(String packageName, String baseCodePath,
String[] splitCodePaths, String[] dataDirs, int userId) {
- PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName,
- new PackageCodeLocations(packageName, baseCodePath, splitCodePaths));
- pcl.updateCodeLocation(baseCodePath, splitCodePaths);
- if (dataDirs != null) {
- for (String dataDir : dataDirs) {
- // The set of data dirs includes deviceProtectedDataDir and
- // credentialProtectedDataDir which might be null for shared
- // libraries. Currently we don't track these but be lenient
- // and check in case we ever decide to store their usage data.
- if (dataDir != null) {
- pcl.mergeAppDataDirs(dataDir, userId);
+ synchronized (mPackageCodeLocationsCache) {
+ PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName,
+ new PackageCodeLocations(packageName, baseCodePath, splitCodePaths));
+ // TODO(calin): We are forced to extend the scope of this synchronization because
+ // the values of the cache (PackageCodeLocations) are updated in place.
+ // Make PackageCodeLocations immutable to simplify the synchronization reasoning.
+ pcl.updateCodeLocation(baseCodePath, splitCodePaths);
+ if (dataDirs != null) {
+ for (String dataDir : dataDirs) {
+ // The set of data dirs includes deviceProtectedDataDir and
+ // credentialProtectedDataDir which might be null for shared
+ // libraries. Currently we don't track these but be lenient
+ // and check in case we ever decide to store their usage data.
+ if (dataDir != null) {
+ pcl.mergeAppDataDirs(dataDir, userId);
+ }
}
}
}
@@ -431,6 +439,52 @@
}
}
+ public RegisterDexModuleResult registerDexModule(ApplicationInfo info, String dexPath,
+ boolean isUsedByOtherApps, int userId) {
+ // Find the owning package record.
+ DexSearchResult searchResult = getDexPackage(info, dexPath, userId);
+
+ if (searchResult.mOutcome == DEX_SEARCH_NOT_FOUND) {
+ return new RegisterDexModuleResult(false, "Package not found");
+ }
+ if (!info.packageName.equals(searchResult.mOwningPackageName)) {
+ return new RegisterDexModuleResult(false, "Dex path does not belong to package");
+ }
+ if (searchResult.mOutcome == DEX_SEARCH_FOUND_PRIMARY ||
+ searchResult.mOutcome == DEX_SEARCH_FOUND_SPLIT) {
+ return new RegisterDexModuleResult(false, "Main apks cannot be registered");
+ }
+
+ // We found the package. Now record the usage for all declared ISAs.
+ boolean update = false;
+ Set<String> isas = new HashSet<>();
+ for (String isa : getAppDexInstructionSets(info)) {
+ isas.add(isa);
+ boolean newUpdate = mPackageDexUsage.record(searchResult.mOwningPackageName,
+ dexPath, userId, isa, isUsedByOtherApps, /*primaryOrSplit*/ false);
+ update |= newUpdate;
+ }
+ if (update) {
+ mPackageDexUsage.maybeWriteAsync();
+ }
+
+ // Try to optimize the package according to the install reason.
+ String compilerFilter = PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
+ PackageManagerService.REASON_INSTALL);
+ int result = mPackageDexOptimizer.dexOptSecondaryDexPath(info, dexPath, isas,
+ compilerFilter, isUsedByOtherApps);
+
+ // If we fail to optimize the package log an error but don't propagate the error
+ // back to the app. The app cannot do much about it and the background job
+ // will rety again when it executes.
+ // TODO(calin): there might be some value to return the error here but it may
+ // cause red herrings since that doesn't mean the app cannot use the module.
+ if (result != PackageDexOptimizer.DEX_OPT_FAILED) {
+ Slog.e(TAG, "Failed to optimize dex module " + dexPath);
+ }
+ return new RegisterDexModuleResult(true, "Dex module registered successfully");
+ }
+
/**
* Return all packages that contain records of secondary dex files.
*/
@@ -479,10 +533,12 @@
// The loadingPackage does not own the dex file.
// Perform a reverse look-up in the cache to detect if any package has ownership.
// Note that we can have false negatives if the cache falls out of date.
- for (PackageCodeLocations pcl : mPackageCodeLocationsCache.values()) {
- outcome = pcl.searchDex(dexPath, userId);
- if (outcome != DEX_SEARCH_NOT_FOUND) {
- return new DexSearchResult(pcl.mPackageName, outcome);
+ synchronized (mPackageCodeLocationsCache) {
+ for (PackageCodeLocations pcl : mPackageCodeLocationsCache.values()) {
+ outcome = pcl.searchDex(dexPath, userId);
+ if (outcome != DEX_SEARCH_NOT_FOUND) {
+ return new DexSearchResult(pcl.mPackageName, outcome);
+ }
}
}
@@ -510,6 +566,20 @@
return existingValue == null ? newValue : existingValue;
}
+ public static class RegisterDexModuleResult {
+ public RegisterDexModuleResult() {
+ this(false, null);
+ }
+
+ public RegisterDexModuleResult(boolean success, String message) {
+ this.success = success;
+ this.message = message;
+ }
+
+ public final boolean success;
+ public final String message;
+ }
+
/**
* Convenience class to store the different locations where a package might
* own code.
@@ -589,6 +659,4 @@
return mOwningPackageName + "-" + mOutcome;
}
}
-
-
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 91a163a..6120ff4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -184,6 +184,7 @@
import android.service.dreams.DreamManagerInternal;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
+import android.service.vr.IPersistentVrStateCallbacks;
import android.speech.RecognizerIntent;
import android.telecom.TelecomManager;
import android.util.DisplayMetrics;
@@ -512,6 +513,8 @@
volatile boolean mGoingToSleep;
volatile boolean mRecentsVisible;
volatile boolean mPictureInPictureVisible;
+ // Written by vr manager thread, only read in this class.
+ volatile private boolean mPersistentVrModeEnabled;
volatile private boolean mDismissImeOnBackKeyPressed;
// Used to hold the last user key used to wake the device. This helps us prevent up events
@@ -581,6 +584,8 @@
boolean mTranslucentDecorEnabled = true;
boolean mUseTvRouting;
+ private boolean mHandleVolumeKeysInWM;
+
int mPointerLocationMode = 0; // guarded by mLock
// The last window we were told about in focusChanged.
@@ -777,6 +782,10 @@
private boolean mBugreportTvKey2Pressed;
private boolean mBugreportTvScheduled;
+ private boolean mAccessibilityTvKey1Pressed;
+ private boolean mAccessibilityTvKey2Pressed;
+ private boolean mAccessibilityTvScheduled;
+
/* The number of steps between min and max brightness */
private static final int BRIGHTNESS_STEPS = 10;
@@ -821,6 +830,7 @@
private static final int MSG_BACK_DELAYED_PRESS = 20;
private static final int MSG_ACCESSIBILITY_SHORTCUT = 21;
private static final int MSG_BUGREPORT_TV = 22;
+ private static final int MSG_ACCESSIBILITY_TV = 23;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -902,6 +912,11 @@
case MSG_BUGREPORT_TV:
takeBugreport();
break;
+ case MSG_ACCESSIBILITY_TV:
+ if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) {
+ accessibilityShortcutActivated();
+ }
+ break;
}
}
}
@@ -1002,6 +1017,14 @@
}
MyOrientationListener mOrientationListener;
+ final IPersistentVrStateCallbacks mPersistentVrModeListener =
+ new IPersistentVrStateCallbacks.Stub() {
+ @Override
+ public void onPersistentVrStateChanged(boolean enabled) {
+ mPersistentVrModeEnabled = enabled;
+ }
+ };
+
private final StatusBarController mStatusBarController = new StatusBarController();
private final BarController mNavigationBarController = new BarController("NavigationBar",
@@ -1917,6 +1940,9 @@
mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
+ mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_handleVolumeKeysInWindowManager);
+
readConfigurationDependentBehaviors();
mAccessibilityManager = (AccessibilityManager) context.getSystemService(
@@ -3308,6 +3334,11 @@
if (!down) {
cancelPreloadRecentApps();
+ if (mHasFeatureLeanback) {
+ // Clear flags
+ mAccessibilityTvKey2Pressed = down;
+ }
+
mHomePressed = false;
if (mHomeConsumed) {
mHomeConsumed = false;
@@ -3362,6 +3393,13 @@
preloadRecentApps();
}
} else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
+ if (mHasFeatureLeanback) {
+ mAccessibilityTvKey2Pressed = down;
+ if (interceptAccessibilityGestureTv()) {
+ return -1;
+ }
+ }
+
if (!keyguardOn) {
handleLongPressOnHome(event.getDeviceId());
}
@@ -3511,16 +3549,28 @@
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
|| keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
- if (mUseTvRouting) {
- // On TVs volume keys never go to the foreground app.
+ if (mUseTvRouting || mHandleVolumeKeysInWM) {
+ // On TVs or when the configuration is enabled, volume keys never
+ // go to the foreground app.
dispatchDirectAudioEvent(event);
return -1;
}
+
+ // If the device is in Vr mode, drop the volume keys and don't
+ // forward it to the application/dispatch the audio event.
+ if (mPersistentVrModeEnabled) {
+ return -1;
+ }
} else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
// Pass through keyboard navigation keys.
return 0;
} else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
return -1;
+ } else if (mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ mAccessibilityTvKey1Pressed = down;
+ if (interceptAccessibilityGestureTv()) {
+ return -1;
+ }
}
// Toggle Caps Lock on META-ALT.
@@ -3739,6 +3789,25 @@
return mBugreportTvScheduled;
}
+ /**
+ * TV only: recognizes a remote control gesture as Accessibility shortcut.
+ * Shortcut: Long press (HOME + DPAD_CENTER)
+ */
+ private boolean interceptAccessibilityGestureTv() {
+ if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) {
+ if (!mAccessibilityTvScheduled) {
+ mAccessibilityTvScheduled = true;
+ Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ }
+ } else if (mAccessibilityTvScheduled) {
+ mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
+ mAccessibilityTvScheduled = false;
+ }
+ return mAccessibilityTvScheduled;
+ }
+
private void takeBugreport() {
if ("1".equals(SystemProperties.get("ro.debuggable"))
|| Settings.Global.getInt(mContext.getContentResolver(),
@@ -5900,8 +5969,8 @@
}
}
}
- if (mUseTvRouting) {
- // On TVs, defer special key handlings to
+ if (mUseTvRouting || mHandleVolumeKeysInWM) {
+ // Defer special key handlings to
// {@link interceptKeyBeforeDispatching()}.
result |= ACTION_PASS_TO_USER;
} else if ((result & ACTION_PASS_TO_USER) == 0) {
@@ -6909,7 +6978,13 @@
|| mAllowAllRotations == 1
|| orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|| orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
- preferredRotation = sensorRotation;
+ // In VrMode, we report the sensor as always being in default orientation so:
+ // 1) The orientation doesn't change as the user moves their head.
+ // 2) 2D apps within VR show in the device's default orientation.
+ // This only overwrites the sensor-provided orientation and does not affect any
+ // explicit orientation preferences specified by any activities.
+ preferredRotation =
+ mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation;
} else {
preferredRotation = lastRotation;
}
@@ -7083,6 +7158,9 @@
mKeyguardDelegate.onSystemReady();
mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
+ if (mVrManagerInternal != null) {
+ mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
+ }
readCameraLensCoverState();
updateUiMode();
@@ -8215,6 +8293,14 @@
pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
+ if (mHasFeatureLeanback) {
+ pw.print(prefix);
+ pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
+ pw.print(prefix);
+ pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
+ pw.print(prefix);
+ pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
+ }
mGlobalKeyManager.dump(prefix, pw);
mStatusBarController.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 8c3d80f..423bc0c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -4632,12 +4632,6 @@
}
@Override
- public void setButtonBrightnessOverrideFromWindowManager(int screenBrightness) {
- // Do nothing.
- // Button lights are not currently supported in the new implementation.
- }
-
- @Override
public void setDozeOverrideFromDreamManager(int screenState, int screenBrightness) {
switch (screenState) {
case Display.STATE_UNKNOWN:
diff --git a/services/core/java/com/android/server/radio/Tuner.java b/services/core/java/com/android/server/radio/Tuner.java
index 248a139..a06d8c6 100644
--- a/services/core/java/com/android/server/radio/Tuner.java
+++ b/services/core/java/com/android/server/radio/Tuner.java
@@ -31,7 +31,8 @@
*/
private final long mNativeContext;
- private int mRegion;
+ private final Object mLock = new Object();
+ private int mRegion; // TODO(b/36863239): find better solution to manage regions
Tuner(@NonNull ITunerCallback clientCallback, int region) {
mRegion = region;
@@ -44,17 +45,44 @@
super.finalize();
}
- private native long nativeInit(ITunerCallback clientCallback);
+ private native long nativeInit(@NonNull ITunerCallback clientCallback);
private native void nativeFinalize(long nativeContext);
private native void nativeClose(long nativeContext);
+ private native void nativeSetConfiguration(long nativeContext,
+ @NonNull RadioManager.BandConfig config);
+ private native RadioManager.BandConfig nativeGetConfiguration(long nativeContext, int region);
+
@Override
public void close() {
- nativeClose(mNativeContext);
+ synchronized (mLock) {
+ nativeClose(mNativeContext);
+ }
+ }
+
+ @Override
+ public void setConfiguration(RadioManager.BandConfig config) {
+ if (config == null) {
+ throw new IllegalArgumentException("The argument must not be a null pointer");
+ }
+ synchronized (mLock) {
+ nativeSetConfiguration(mNativeContext, config);
+ mRegion = config.getRegion();
+ }
+ }
+
+ @Override
+ public RadioManager.BandConfig getConfiguration() {
+ synchronized (mLock) {
+ return nativeGetConfiguration(mNativeContext, mRegion);
+ }
}
@Override
public int getProgramInformation(RadioManager.ProgramInfo[] infoOut) {
+ if (infoOut == null || infoOut.length != 1) {
+ throw new IllegalArgumentException("The argument must be an array of length 1");
+ }
Slog.d(TAG, "getProgramInformation()");
return RadioManager.STATUS_INVALID_OPERATION;
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index cc4c23d..c6393e7 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -67,6 +67,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -326,8 +327,6 @@
agentInfo.label = resolveInfo.loadLabel(pm);
agentInfo.icon = resolveInfo.loadIcon(pm);
agentInfo.settings = getSettingsAttrs(pm, resolveInfo);
- agentInfo.agent = new TrustAgentWrapper(mContext, this,
- new Intent().setComponent(name), userInfo.getUserHandle());
} else {
int index = mActiveAgents.indexOf(agentInfo);
agentInfo = mActiveAgents.valueAt(index);
@@ -364,6 +363,11 @@
}
}
+ if (agentInfo.agent == null) {
+ agentInfo.agent = new TrustAgentWrapper(mContext, this,
+ new Intent().setComponent(name), userInfo.getUserHandle());
+ }
+
if (!mActiveAgents.contains(agentInfo)) {
mActiveAgents.add(agentInfo);
} else {
@@ -575,20 +579,22 @@
}
private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
- if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
- return;
- }
- PackageManager pm = mContext.getPackageManager();
- List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
ComponentName defaultAgent = getDefaultFactoryTrustAgent(mContext);
boolean shouldUseDefaultAgent = defaultAgent != null;
- ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
if (shouldUseDefaultAgent) {
- discoveredAgents.add(defaultAgent);
Log.i(TAG, "Enabling " + defaultAgent + " because it is a default agent.");
+ utils.setEnabledTrustAgents(Collections.singleton(defaultAgent), userId);
} else { // A default agent is not set; perform regular trust agent discovery
+ if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
+ return;
+ }
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
+
+ ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
+
for (ResolveInfo resolveInfo : resolveInfos) {
ComponentName componentName = getComponentName(resolveInfo);
int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
@@ -599,13 +605,13 @@
}
discoveredAgents.add(componentName);
}
- }
- List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
- if (previouslyEnabledAgents != null) {
- discoveredAgents.addAll(previouslyEnabledAgents);
+ List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
+ if (previouslyEnabledAgents != null) {
+ discoveredAgents.addAll(previouslyEnabledAgents);
+ }
+ utils.setEnabledTrustAgents(discoveredAgents, userId);
}
- utils.setEnabledTrustAgents(discoveredAgents, userId);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
}
diff --git a/services/core/java/com/android/server/twilight/TwilightState.java b/services/core/java/com/android/server/twilight/TwilightState.java
index a12965d..30a8ccc 100644
--- a/services/core/java/com/android/server/twilight/TwilightState.java
+++ b/services/core/java/com/android/server/twilight/TwilightState.java
@@ -31,7 +31,7 @@
private final long mSunriseTimeMillis;
private final long mSunsetTimeMillis;
- TwilightState(long sunriseTimeMillis, long sunsetTimeMillis) {
+ public TwilightState(long sunriseTimeMillis, long sunsetTimeMillis) {
mSunriseTimeMillis = sunriseTimeMillis;
mSunsetTimeMillis = sunsetTimeMillis;
}
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 63c6195..1f75640 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -16,7 +16,7 @@
package com.android.server.vr;
import android.annotation.NonNull;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.content.ComponentName;
import android.service.vr.IPersistentVrStateCallbacks;
@@ -83,16 +83,16 @@
public abstract int hasVrPackage(@NonNull ComponentName packageName, int userId);
/**
- * Sets the resolution and DPI of the compatibility virtual display used to display
+ * Sets the resolution and DPI of the vr2d virtual display used to display
* 2D applications in VR mode.
*
* <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
*
- * @param compatDisplayProp Properties of the virtual display for 2D applications
+ * @param vr2dDisplayProp Properties of the virtual display for 2D applications
* in VR mode.
*/
- public abstract void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp);
+ public abstract void setVr2dDisplayProperties(
+ Vr2dDisplayProperties vr2dDisplayProp);
/**
* Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
@@ -110,7 +110,7 @@
* @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display
* currently, else return the display id of the virtual display
*/
- public abstract int getCompatibilityDisplayId();
+ public abstract int getVr2dDisplayId();
/**
* Adds listener that reports state changes to persistent VR mode.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 860b241..0e183f0 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -21,7 +21,7 @@
import android.app.ActivityManagerInternal;
import android.app.ActivityManager;
import android.app.AppOpsManager;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.app.NotificationManager;
import android.annotation.NonNull;
import android.content.ComponentName;
@@ -141,7 +141,7 @@
private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
/** Tracks the state of the screen and keyguard UI.*/
private int mSystemSleepFlags = FLAG_AWAKE;
- private CompatibilityDisplay mCompatibilityDisplay;
+ private Vr2dDisplay mVr2dDisplay;
private static final int MSG_VR_STATE_CHANGE = 0;
private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
@@ -428,15 +428,15 @@
}
@Override
- public void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp) {
+ public void setVr2dDisplayProperties(
+ Vr2dDisplayProperties vr2dDisplayProp) {
enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
- VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp);
+ VrManagerService.this.setVr2dDisplayProperties(vr2dDisplayProp);
}
@Override
- public int getCompatibilityDisplayId() {
- return VrManagerService.this.getCompatibilityDisplayId();
+ public int getVr2dDisplayId() {
+ return VrManagerService.this.getVr2dDisplayId();
}
@Override
@@ -549,14 +549,14 @@
}
@Override
- public void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp) {
- VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp);
+ public void setVr2dDisplayProperties(
+ Vr2dDisplayProperties compatDisplayProp) {
+ VrManagerService.this.setVr2dDisplayProperties(compatDisplayProp);
}
@Override
- public int getCompatibilityDisplayId() {
- return VrManagerService.this.getCompatibilityDisplayId();
+ public int getVr2dDisplayId() {
+ return VrManagerService.this.getVr2dDisplayId();
}
@Override
@@ -608,8 +608,8 @@
DisplayManager dm =
(DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
- mCompatibilityDisplay = new CompatibilityDisplay(dm, ami, mVrManager);
- mCompatibilityDisplay.init(getContext());
+ mVr2dDisplay = new Vr2dDisplay(dm, ami, mVrManager);
+ mVr2dDisplay.init(getContext());
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
mVrModeAllowed = true;
@@ -1116,20 +1116,20 @@
}
}
- public void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp) {
- if (mCompatibilityDisplay != null) {
- mCompatibilityDisplay.setVirtualDisplayProperties(compatDisplayProp);
+ public void setVr2dDisplayProperties(
+ Vr2dDisplayProperties compatDisplayProp) {
+ if (mVr2dDisplay != null) {
+ mVr2dDisplay.setVirtualDisplayProperties(compatDisplayProp);
return;
}
- Slog.w(TAG, "CompatibilityDisplay is null!");
+ Slog.w(TAG, "Vr2dDisplay is null!");
}
- private int getCompatibilityDisplayId() {
- if (mCompatibilityDisplay != null) {
- return mCompatibilityDisplay.getVirtualDisplayId();
+ private int getVr2dDisplayId() {
+ if (mVr2dDisplay != null) {
+ return mVr2dDisplay.getVirtualDisplayId();
}
- Slog.w(TAG, "CompatibilityDisplay is null!");
+ Slog.w(TAG, "Vr2dDisplay is null!");
return INVALID_DISPLAY;
}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index c625cbe..b5e194b 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -36,7 +36,6 @@
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Trace;
import android.util.Slog;
import android.view.IApplicationToken;
@@ -319,7 +318,7 @@
+ " token: " + mToken);
return;
}
- mContainer.setDisablePreviewSnapshots(disable);
+ mContainer.setDisablePreviewScreenshots(disable);
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 36418be..640bac2 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -23,6 +23,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -48,6 +49,7 @@
import static com.android.server.wm.WindowManagerService.logWithStack;
import android.annotation.NonNull;
+import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
@@ -1528,12 +1530,24 @@
return candidate;
}
- void setDisablePreviewSnapshots(boolean disable) {
+ /**
+ * See {@link Activity#setDisablePreviewScreenshots}.
+ */
+ void setDisablePreviewScreenshots(boolean disable) {
mDisbalePreviewScreenshots = disable;
}
- boolean shouldDisablePreviewScreenshots() {
- return mDisbalePreviewScreenshots;
+ /**
+ * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
+ * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
+ * we can't take a snapshot for other reasons, for example, if we have a secure window.
+ *
+ * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
+ * screenshot.
+ */
+ boolean shouldUseAppThemeSnapshot() {
+ return mDisbalePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
+ true /* topToBottom */);
}
@Override
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 4100446..d44cd13 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -188,6 +188,7 @@
boolean animateDimLayers() {
int fullScreen = -1;
int fullScreenAndDimming = -1;
+ int topFullScreenUserLayer = 0;
boolean result = false;
for (int i = mState.size() - 1; i >= 0; i--) {
@@ -213,8 +214,18 @@
// and we have to make sure we always animate the layer.
if (user.dimFullscreen() && state.dimLayer == mSharedFullScreenDimLayer) {
fullScreen = i;
- if (mState.valueAt(i).continueDimming) {
+ if (!state.continueDimming) {
+ continue;
+ }
+
+ // When choosing which user to assign the shared fullscreen layer to
+ // we need to look at Z-order.
+ if (topFullScreenUserLayer == 0 ||
+ (state.animator != null && state.animator.mAnimLayer > topFullScreenUserLayer)) {
fullScreenAndDimming = i;
+ if (state.animator != null) {
+ topFullScreenUserLayer = state.animator.mAnimLayer;
+ }
}
} else {
// We always want to animate the non fullscreen windows, they don't share their
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 05b95e2..be242b6 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1503,8 +1503,16 @@
return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
}
- @Override
- int getOrientation() {
+ /**
+ * Returns the orientation that this display should be in factoring in its children containers.
+ *
+ * @param includeAppContainers True if then app containers (stacks, tasks, ...) should be
+ * factored in when determining the orientation. If false only
+ * non-app/system containers will be used to determine the returned
+ * orientation.
+ * @return The orientation the display should be in.
+ */
+ int getOrientation(boolean includeAppContainers) {
final WindowManagerPolicy policy = mService.mPolicy;
if (mService.mDisplayFrozen) {
@@ -1533,8 +1541,14 @@
}
}
- // Top system windows are not requesting an orientation. Start searching from apps.
- return mTaskStackContainers.getOrientation();
+ // Top system windows are not requesting an orientation. Get orientation from app containers
+ // if allowed. Otherwise, return the last orientation.
+ return includeAppContainers ? mTaskStackContainers.getOrientation() : mLastOrientation;
+ }
+
+ @Override
+ int getOrientation() {
+ return getOrientation(true /* includeAppContainers */);
}
void updateDisplayInfo() {
@@ -1793,7 +1807,13 @@
// events to be intercepted and used to change focus. This would likely cause a
// disappearance of the input method.
inputMethod.getTouchableRegion(mTmpRegion);
- mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
+ if (inputMethod.getDisplayId() == mDisplayId) {
+ mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
+ } else {
+ // IME is on a different display, so we need to update its tap detector.
+ // TODO(multidisplay): Remove when IME will always appear on same display.
+ inputMethod.getDisplayContent().setTouchExcludeRegion(null /* focusedTask */);
+ }
}
for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
WindowState win = mTapExcludedWindows.get(i);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 60b136f..be3558b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -21,7 +21,10 @@
import android.hardware.power.V1_0.PowerHint;
import android.os.Binder;
import android.os.Debug;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.RemoteException;
@@ -34,6 +37,8 @@
import android.view.Display;
import android.view.DisplayInfo;
import android.view.WindowManager;
+
+import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.server.EventLogTags;
@@ -87,13 +92,15 @@
class RootWindowContainer extends WindowContainer<DisplayContent> {
private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
+ private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
+ private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
+
WindowManagerService mService;
private boolean mWallpaperForceHidingChanged = false;
private Object mLastWindowFreezeSource = null;
private Session mHoldScreen = null;
private float mScreenBrightness = -1;
- private float mButtonBrightness = -1;
private long mUserActivityTimeout = -1;
private boolean mUpdateRotation = false;
// Following variables are for debugging screen wakelock only.
@@ -128,6 +135,8 @@
private final WindowLayersController mLayersController;
final WallpaperController mWallpaperController;
+ private final Handler mHandler;
+
private String mCloseSystemDialogsReason;
private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
if (w.mHasSurface) {
@@ -147,6 +156,7 @@
RootWindowContainer(WindowManagerService service) {
mService = service;
+ mHandler = new MyHandler(service.mH.getLooper());
mLayersController = new WindowLayersController(mService);
mWallpaperController = new WallpaperController(mService);
}
@@ -552,7 +562,6 @@
mHoldScreen = null;
mScreenBrightness = -1;
- mButtonBrightness = -1;
mUserActivityTimeout = -1;
mObscureApplicationContentOnSecondaryDisplays = false;
mSustainedPerformanceModeCurrent = false;
@@ -702,20 +711,13 @@
mService.setHoldScreenLocked(mHoldScreen);
if (!mService.mDisplayFrozen) {
- if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
- mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
- } else {
- mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
- toBrightnessOverride(mScreenBrightness));
- }
- if (mButtonBrightness < 0 || mButtonBrightness > 1.0f) {
- mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
- } else {
- mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
- toBrightnessOverride(mButtonBrightness));
- }
- mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
- mUserActivityTimeout);
+ final int brightness = mScreenBrightness < 0 || mScreenBrightness > 1.0f
+ ? -1 : toBrightnessOverride(mScreenBrightness);
+
+ // Post these on a handler such that we don't call into power manager service while
+ // holding the window manager lock to avoid lock contention with power manager lock.
+ mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightness, 0).sendToTarget();
+ mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
}
if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
@@ -863,9 +865,6 @@
if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
mScreenBrightness = w.mAttrs.screenBrightness;
}
- if (!syswin && w.mAttrs.buttonBrightness >= 0 && mButtonBrightness < 0) {
- mButtonBrightness = w.mAttrs.buttonBrightness;
- }
if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
mUserActivityTimeout = w.mAttrs.userActivityTimeout;
}
@@ -935,6 +934,29 @@
return (int)(value * PowerManager.BRIGHTNESS_ON);
}
+ private final class MyHandler extends Handler {
+
+ public MyHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case SET_SCREEN_BRIGHTNESS_OVERRIDE:
+ mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
+ msg.arg1);
+ break;
+ case SET_USER_ACTIVITY_TIMEOUT:
+ mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
+ (Long) msg.obj);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
void enableSurfaceTrace(ParcelFileDescriptor pfd) {
final FileDescriptor fd = pfd.getFileDescriptor();
if (mSurfaceTraceEnabled) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index fbb826d..b79173c 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -31,11 +31,13 @@
import android.graphics.Rect;
import android.os.Environment;
import android.util.ArraySet;
+import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerPolicy.StartingSurface;
import com.google.android.collect.Sets;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wm.TaskSnapshotSurface.SystemBarBackgroundPainter;
import java.io.PrintWriter;
@@ -206,7 +208,7 @@
final AppWindowToken topChild = task.getTopChild();
if (StackId.isHomeOrRecentsStack(task.mStack.mStackId)) {
return SNAPSHOT_MODE_NONE;
- } else if (topChild != null && topChild.shouldDisablePreviewScreenshots()) {
+ } else if (topChild != null && topChild.shouldUseAppThemeSnapshot()) {
return SNAPSHOT_MODE_APP_THEME;
} else {
return SNAPSHOT_MODE_REAL;
@@ -227,6 +229,8 @@
return null;
}
final int color = task.getTaskDescription().getBackgroundColor();
+ final int statusBarColor = task.getTaskDescription().getStatusBarColor();
+ final int navigationBarColor = task.getTaskDescription().getNavigationBarColor();
final GraphicBuffer buffer = GraphicBuffer.create(mainWindow.getFrameLw().width(),
mainWindow.getFrameLw().height(),
RGBA_8888, USAGE_HW_TEXTURE | USAGE_SW_WRITE_RARELY | USAGE_SW_READ_NEVER);
@@ -235,6 +239,11 @@
}
final Canvas c = buffer.lockCanvas();
c.drawColor(color);
+ final LayoutParams attrs = mainWindow.getAttrs();
+ final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
+ attrs.privateFlags, attrs.systemUiVisibility, statusBarColor, navigationBarColor);
+ decorPainter.setInsets(mainWindow.mContentInsets, mainWindow.mStableInsets);
+ decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
buffer.unlockCanvasAndPost(c);
return new TaskSnapshot(buffer, topChild.getConfiguration().orientation,
mainWindow.mStableInsets, false /* reduced */, 1.0f /* scale */);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index f2a92df..e5c7a72 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -24,6 +24,7 @@
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Bitmap.Config;
import android.os.Process;
import android.os.SystemClock;
import android.util.ArraySet;
@@ -266,12 +267,13 @@
final File file = getBitmapFile(mTaskId, mUserId);
final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId);
final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot());
- final Bitmap reduced = Bitmap.createScaledBitmap(bitmap,
+ final Bitmap swBitmap = bitmap.copy(Config.ARGB_8888, false /* isMutable */);
+ final Bitmap reduced = Bitmap.createScaledBitmap(swBitmap,
(int) (bitmap.getWidth() * REDUCED_SCALE),
(int) (bitmap.getHeight() * REDUCED_SCALE), true /* filter */);
try {
FileOutputStream fos = new FileOutputStream(file);
- bitmap.compress(JPEG, QUALITY, fos);
+ swBitmap.compress(JPEG, QUALITY, fos);
fos.close();
FileOutputStream reducedFos = new FileOutputStream(reducedFile);
reduced.compress(JPEG, QUALITY, reducedFos);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index c816ba3..2b9e800 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -42,8 +42,11 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.Nullable;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityManager.TaskSnapshot;
+import android.app.ActivityThread;
+import android.content.Context;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
import android.graphics.Paint;
@@ -118,13 +121,8 @@
private final Handler mHandler;
private boolean mSizeMismatch;
private final Paint mBackgroundPaint = new Paint();
- private final Paint mStatusBarPaint = new Paint();
- private final Paint mNavigationBarPaint = new Paint();
private final int mStatusBarColor;
- private final int mNavigationBarColor;
- private final int mSysUiVis;
- private final int mWindowFlags;
- private final int mWindowPrivateFlags;
+ @VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
TaskSnapshot snapshot) {
@@ -224,15 +222,9 @@
mTitle = title;
mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
mTaskBounds = taskBounds;
- mSysUiVis = sysUiVis;
- mWindowFlags = windowFlags;
- mWindowPrivateFlags = windowPrivateFlags;
- mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
- service.mContext.getColor(R.color.system_bar_background_semi_transparent),
- statusBarColor);
- mNavigationBarColor = navigationBarColor;
- mStatusBarPaint.setColor(mStatusBarColor);
- mNavigationBarPaint.setColor(navigationBarColor);
+ mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
+ windowPrivateFlags, sysUiVis, statusBarColor, navigationBarColor);
+ mStatusBarColor = statusBarColor;
}
@Override
@@ -258,6 +250,7 @@
mStableInsets.set(stableInsets);
mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth()
|| mFrame.height() != mSnapshot.getSnapshot().getHeight());
+ mSystemBarBackgroundPainter.setInsets(contentInsets, stableInsets);
}
private void drawSnapshot() {
@@ -346,7 +339,7 @@
@VisibleForTesting
void drawBackgroundAndBars(Canvas c, Rect frame) {
- final int statusBarHeight = getStatusBarColorViewHeight();
+ final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
final boolean fillHorizontally = c.getWidth() > frame.right;
final boolean fillVertically = c.getHeight() > frame.bottom;
if (fillHorizontally) {
@@ -359,44 +352,7 @@
if (fillVertically) {
c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
}
- drawStatusBarBackground(c, frame, statusBarHeight);
- drawNavigationBarBackground(c);
- }
-
- private int getStatusBarColorViewHeight() {
- final boolean forceStatusBarBackground =
- (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
- if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
- return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
- } else {
- return 0;
- }
- }
-
- private boolean isNavigationBarColorViewVisible() {
- return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
- }
-
- @VisibleForTesting
- void drawStatusBarBackground(Canvas c, Rect frame, int statusBarHeight) {
- if (statusBarHeight > 0 && c.getWidth() > frame.right) {
- final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
- mContentInsets.right);
- c.drawRect(frame.right, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
- }
- }
-
- @VisibleForTesting
- void drawNavigationBarBackground(Canvas c) {
- final Rect navigationBarRect = new Rect();
- getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
- navigationBarRect);
- final boolean visible = isNavigationBarColorViewVisible();
- if (visible && !navigationBarRect.isEmpty()) {
- c.drawRect(navigationBarRect, mNavigationBarPaint);
- }
+ mSystemBarBackgroundPainter.drawDecors(c, frame);
}
private void reportDrawn() {
@@ -450,4 +406,84 @@
}
}
}
+
+ /**
+ * Helper class to draw the background of the system bars in regions the task snapshot isn't
+ * filling the window.
+ */
+ static class SystemBarBackgroundPainter {
+
+ private final Rect mContentInsets = new Rect();
+ private final Rect mStableInsets = new Rect();
+ private final Paint mStatusBarPaint = new Paint();
+ private final Paint mNavigationBarPaint = new Paint();
+ private final int mStatusBarColor;
+ private final int mNavigationBarColor;
+ private final int mWindowFlags;
+ private final int mWindowPrivateFlags;
+ private final int mSysUiVis;
+
+ SystemBarBackgroundPainter( int windowFlags, int windowPrivateFlags, int sysUiVis,
+ int statusBarColor, int navigationBarColor) {
+ mWindowFlags = windowFlags;
+ mWindowPrivateFlags = windowPrivateFlags;
+ mSysUiVis = sysUiVis;
+ final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
+ mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
+ context.getColor(R.color.system_bar_background_semi_transparent),
+ statusBarColor);
+ mNavigationBarColor = navigationBarColor;
+ mStatusBarPaint.setColor(mStatusBarColor);
+ mNavigationBarPaint.setColor(navigationBarColor);
+ }
+
+ void setInsets(Rect contentInsets, Rect stableInsets) {
+ mContentInsets.set(contentInsets);
+ mStableInsets.set(stableInsets);
+ }
+
+ int getStatusBarColorViewHeight() {
+ final boolean forceStatusBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+ if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
+ return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
+ } else {
+ return 0;
+ }
+ }
+
+ private boolean isNavigationBarColorViewVisible() {
+ return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
+ }
+
+ void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+ drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight());
+ drawNavigationBarBackground(c);
+ }
+
+ @VisibleForTesting
+ void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame,
+ int statusBarHeight) {
+ if (statusBarHeight > 0
+ && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
+ final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
+ mContentInsets.right);
+ final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
+ c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+ }
+ }
+
+ @VisibleForTesting
+ void drawNavigationBarBackground(Canvas c) {
+ final Rect navigationBarRect = new Rect();
+ getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
+ navigationBarRect);
+ final boolean visible = isNavigationBarColorViewVisible();
+ if (visible && !navigationBarRect.isEmpty()) {
+ c.drawRect(navigationBarRect, mNavigationBarPaint);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 1367a06..067cc09 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -87,8 +87,18 @@
private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
private Choreographer mChoreographer;
- private boolean mAnimationScheduled;
+ /**
+ * Indicates whether we have an animation frame callback scheduled, which will happen at
+ * vsync-app and then schedule the animation tick at the right time (vsync-sf).
+ */
+ private boolean mAnimationFrameCallbackScheduled;
+
+ /**
+ * Indicates whether we have an animation tick scheduled. The tick is the thing that actually
+ * executes the animation step, which will happen at vsync-sf.
+ */
+ private boolean mAnimationTickScheduled;
WindowAnimator(final WindowManagerService service) {
mService = service;
@@ -104,13 +114,20 @@
mService.getDefaultDisplayContentLocked().getDisplay(), mChoreographer);
mAnimationTick = () -> {
synchronized (mService.mWindowMap) {
- mAnimationScheduled = false;
+ mAnimationTickScheduled = false;
animateLocked(mCurrentFrameTime);
}
};
mAnimationFrameCallback = frameTimeNs -> {
- mCurrentFrameTime = frameTimeNs;
- mSfChoreographer.scheduleAtSfVsync(mAnimationTick);
+ synchronized (mService.mWindowMap) {
+ mCurrentFrameTime = frameTimeNs;
+ mAnimationFrameCallbackScheduled = false;
+ if (mAnimationTickScheduled) {
+ return;
+ }
+ mAnimationTickScheduled = true;
+ mSfChoreographer.scheduleAtSfVsync(mAnimationTick);
+ }
};
}
@@ -371,8 +388,8 @@
}
void scheduleAnimation() {
- if (!mAnimationScheduled) {
- mAnimationScheduled = true;
+ if (!mAnimationFrameCallbackScheduled) {
+ mAnimationFrameCallbackScheduled = true;
mChoreographer.postFrameCallback(mAnimationFrameCallback);
}
}
@@ -386,7 +403,7 @@
}
boolean isAnimationScheduled() {
- return mAnimationScheduled;
+ return mAnimationFrameCallbackScheduled || mAnimationTickScheduled;
}
Choreographer getChoreographer() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a7f6600..a48397b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2373,7 +2373,7 @@
try {
synchronized(mWindowMap) {
config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
- displayId);
+ displayId, true /* includeAppContainers */);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2383,13 +2383,13 @@
}
private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
- IBinder freezeThisOneIfNeeded, int displayId) {
+ IBinder freezeThisOneIfNeeded, int displayId, boolean includeAppContainers) {
if (!mDisplayReady) {
return null;
}
Configuration config = null;
- if (updateOrientationFromAppTokensLocked(false, displayId)) {
+ if (updateOrientationFromAppTokensLocked(false, displayId, includeAppContainers)) {
// If we changed the orientation but mOrientationChangeComplete is already true,
// we used seamless rotation, and we don't need to freeze the screen.
if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
@@ -2427,6 +2427,11 @@
return config;
}
+ boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
+ return updateOrientationFromAppTokensLocked(inTransaction, displayId,
+ false /* includeAppContainers */);
+ }
+
/**
* Determine the new desired orientation of the display, returning a non-null new Configuration
* if it has changed from the current orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
@@ -2437,13 +2442,25 @@
* The orientation is computed from non-application windows first. If none of the
* non-application windows specify orientation, the orientation is computed from application
* tokens.
+ *
+ * @param inTransaction True if we are currently in a surface transaction.
+ * @param displayId Id of the display to update orientation for.
+ * @param includeAppContainers True if then app containers (stacks, tasks, ...) should be
+ * factored in when determining the orientation. If false only
+ * non-app/system containers will be used to determine the returned
+ * orientation.
+ * NOTE: Only call originating from activity manager are expected to
+ * set this to true as it needs to synchronize several app states
+ * like visibility with the update of display orientation.
+ * @return True if the display orientation was updated.
* @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
*/
- boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
- long ident = Binder.clearCallingIdentity();
+ private boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId,
+ boolean includeAppContainers) {
+ final long ident = Binder.clearCallingIdentity();
try {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
- final int req = dc.getOrientation();
+ final int req = dc.getOrientation(includeAppContainers);
if (req != dc.getLastOrientation()) {
dc.setLastOrientation(req);
//send a message to Policy indicating orientation change to take
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 2236b59..a6b95d6 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1132,7 +1132,10 @@
// Task is non-null per shouldCropToStackBounds
final TaskStack stack = w.getTask().mStack;
stack.getDimBounds(finalClipRect);
- w.expandForSurfaceInsets(finalClipRect);
+
+ if (StackId.tasksAreFloating(stack.mStackId)) {
+ w.expandForSurfaceInsets(finalClipRect);
+ }
return true;
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 0006110..14a2381 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -36,6 +36,7 @@
#include <utils/Log.h>
#include <utils/Looper.h>
#include <utils/threads.h>
+#include <utils/SortedVector.h>
#include <input/PointerController.h>
#include <input/SpriteController.h>
@@ -206,6 +207,7 @@
void setInputDispatchMode(bool enabled, bool frozen);
void setSystemUiVisibility(int32_t visibility);
void setPointerSpeed(int32_t speed);
+ void setInputDeviceEnabled(uint32_t deviceId, bool enabled);
void setShowTouches(bool enabled);
void setInteractive(bool interactive);
void reloadCalibration();
@@ -290,6 +292,9 @@
// Pointer controller singleton, created and destroyed as needed.
wp<PointerController> pointerController;
+
+ // Input devices to be disabled
+ SortedVector<int32_t> disabledInputDevices;
} mLocked;
std::atomic<bool> mInteractive;
@@ -475,6 +480,8 @@
outConfig->setDisplayInfo(false /*external*/, mLocked.internalViewport);
outConfig->setDisplayInfo(true /*external*/, mLocked.externalViewport);
+
+ outConfig->disabledDevices = mLocked.disabledInputDevices;
} // release lock
}
@@ -764,6 +771,24 @@
InputReaderConfiguration::CHANGE_POINTER_SPEED);
}
+void NativeInputManager::setInputDeviceEnabled(uint32_t deviceId, bool enabled) {
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ ssize_t index = mLocked.disabledInputDevices.indexOf(deviceId);
+ bool currentlyEnabled = index < 0;
+ if (!enabled && currentlyEnabled) {
+ mLocked.disabledInputDevices.add(deviceId);
+ }
+ if (enabled && !currentlyEnabled) {
+ mLocked.disabledInputDevices.remove(deviceId);
+ }
+ } // release lock
+
+ mInputManager->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_ENABLED_STATE);
+}
+
void NativeInputManager::setShowTouches(bool enabled) {
{ // acquire lock
AutoMutex _l(mLock);
@@ -1335,6 +1360,7 @@
static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */,
jlong ptr, jint deviceId) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
im->getInputManager()->getReader()->toggleCapsLockState(deviceId);
}
@@ -1355,6 +1381,7 @@
static void nativeSetPointerCapture(JNIEnv* env, jclass /* clazz */, jlong ptr,
jboolean enabled) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
im->setPointerCapture(enabled);
}
@@ -1416,6 +1443,7 @@
static void nativeReloadCalibration(JNIEnv* env, jclass clazz, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
im->reloadCalibration();
}
@@ -1482,13 +1510,36 @@
im->getInputManager()->getDispatcher()->monitor();
}
+static jboolean nativeIsInputDeviceEnabled(JNIEnv* env /* env */,
+ jclass /* clazz */, jlong ptr, jint deviceId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ return im->getInputManager()->getReader()->isInputDeviceEnabled(deviceId);
+}
+
+static void nativeEnableInputDevice(JNIEnv* /* env */,
+ jclass /* clazz */, jlong ptr, jint deviceId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ im->setInputDeviceEnabled(deviceId, true);
+}
+
+static void nativeDisableInputDevice(JNIEnv* /* env */,
+ jclass /* clazz */, jlong ptr, jint deviceId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ im->setInputDeviceEnabled(deviceId, false);
+}
+
static void nativeSetPointerIconType(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint iconId) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
im->setPointerIconType(iconId);
}
static void nativeReloadPointerIcons(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
im->reloadPointerIcons();
}
@@ -1576,6 +1627,12 @@
(void*) nativeDump },
{ "nativeMonitor", "(J)V",
(void*) nativeMonitor },
+ { "nativeIsInputDeviceEnabled", "(JI)Z",
+ (void*) nativeIsInputDeviceEnabled },
+ { "nativeEnableInputDevice", "(JI)V",
+ (void*) nativeEnableInputDevice },
+ { "nativeDisableInputDevice", "(JI)V",
+ (void*) nativeDisableInputDevice },
{ "nativeSetPointerIconType", "(JI)V",
(void*) nativeSetPointerIconType },
{ "nativeReloadPointerIcons", "(J)V",
diff --git a/services/core/jni/com_android_server_radio_Tuner.cpp b/services/core/jni/com_android_server_radio_Tuner.cpp
index 3245bff..96e122d 100644
--- a/services/core/jni/com_android_server_radio_Tuner.cpp
+++ b/services/core/jni/com_android_server_radio_Tuner.cpp
@@ -19,6 +19,7 @@
#include "com_android_server_radio_Tuner.h"
+#include "com_android_server_radio_convert.h"
#include "com_android_server_radio_Tuner_TunerCallback.h"
#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
@@ -104,6 +105,13 @@
ctx.mHalTuner = halTuner;
}
+sp<ITuner> getHalTuner(jlong nativeContext) {
+ AutoMutex _l(gContextMutex);
+ auto tuner = getNativeContext(nativeContext).mHalTuner;
+ LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set");
+ return tuner;
+}
+
sp<ITunerCallback> getNativeCallback(JNIEnv *env, jobject obj) {
AutoMutex _l(gContextMutex);
auto& ctx = getNativeContext(env, obj);
@@ -114,7 +122,7 @@
return static_cast<Region>(env->GetIntField(obj, gjni.Tuner.region));
}
-static void close(JNIEnv *env, jobject obj, jlong nativeContext) {
+static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) {
AutoMutex _l(gContextMutex);
auto& ctx = getNativeContext(nativeContext);
ALOGI("Closing tuner %p", ctx.mHalTuner.get());
@@ -123,10 +131,42 @@
ctx.mNativeCallback = nullptr;
}
+static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, jobject config) {
+ ALOGV("nativeSetConfiguration()");
+ auto halTuner = getHalTuner(nativeContext);
+
+ Region region_unused;
+ BandConfig bandConfigHal = convert::BandConfigToHal(env, config, region_unused);
+
+ convert::ThrowIfFailed(env, halTuner->setConfiguration(bandConfigHal));
+}
+
+static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext,
+ Region region) {
+ ALOGV("nativeSetConfiguration()");
+ auto halTuner = getHalTuner(nativeContext);
+
+ BandConfig halConfig;
+ Result halResult;
+ auto hidlResult = halTuner->getConfiguration([&](Result result, const BandConfig& config) {
+ halResult = result;
+ halConfig = config;
+ });
+ if (convert::ThrowIfFailed(env, hidlResult)) {
+ return nullptr;
+ }
+
+ return convert::BandConfigFromHal(env, halConfig, region).release();
+}
+
static const JNINativeMethod gTunerMethods[] = {
{ "nativeInit", "(Landroid/hardware/radio/ITunerCallback;)J", (void*)nativeInit },
{ "nativeFinalize", "(J)V", (void*)nativeFinalize },
- { "nativeClose", "(J)V", (void*)close },
+ { "nativeClose", "(J)V", (void*)nativeClose },
+ { "nativeSetConfiguration", "(JLandroid/hardware/radio/RadioManager$BandConfig;)V",
+ (void*)nativeSetConfiguration },
+ { "nativeGetConfiguration", "(JI)Landroid/hardware/radio/RadioManager$BandConfig;",
+ (void*)nativeGetConfiguration },
};
} // namespace Tuner
diff --git a/services/core/jni/com_android_server_radio_convert.cpp b/services/core/jni/com_android_server_radio_convert.cpp
index afa3539..419e6d6 100644
--- a/services/core/jni/com_android_server_radio_convert.cpp
+++ b/services/core/jni/com_android_server_radio_convert.cpp
@@ -28,10 +28,12 @@
namespace radio {
namespace convert {
+using hardware::Return;
using hardware::hidl_vec;
using V1_0::Band;
using V1_0::Deemphasis;
+using V1_0::Result;
using V1_0::Rds;
static struct {
@@ -62,6 +64,47 @@
} BandDescriptor;
} gjni;
+template <typename T>
+bool ThrowIfFailedCommon(JNIEnv *env, const hardware::Return<T> &hidlResult) {
+ if (hidlResult.isOk()) return false;
+
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "HIDL call failed: %s", hidlResult.description().c_str());
+ return true;
+}
+
+bool ThrowIfFailed(JNIEnv *env, const hardware::Return<void> &hidlResult) {
+ return ThrowIfFailedCommon(env, hidlResult);
+}
+
+bool ThrowIfFailed(JNIEnv *env, const hardware::Return<V1_0::Result> &hidlResult) {
+ if (ThrowIfFailedCommon(env, hidlResult)) return true;
+
+ Result result = hidlResult;
+ switch (result) {
+ case Result::OK:
+ return false;
+ case Result::NOT_INITIALIZED:
+ jniThrowException(env, "java/lang/RuntimeException", "Result::NOT_INITIALIZED");
+ return true;
+ case Result::INVALID_ARGUMENTS:
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Result::INVALID_ARGUMENTS");
+ return true;
+ case Result::INVALID_STATE:
+ jniThrowException(env, "java/lang/IllegalStateException", "Result::INVALID_STATE");
+ return true;
+ case Result::TIMEOUT:
+ jniThrowException(env, "java/lang/RuntimeException",
+ "Result::TIMEOUT (unexpected here)");
+ return true;
+ default:
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "Unknown failure, result: %d", result);
+ return true;
+ }
+}
+
static Rds RdsForRegion(bool rds, Region region) {
if (!rds) return Rds::NONE;
@@ -95,6 +138,7 @@
}
JavaRef BandConfigFromHal(JNIEnv *env, const V1_0::BandConfig &config, Region region) {
+ ALOGV("BandConfigFromHal()");
EnvWrapper wrap(env);
jint spacing = config.spacings.size() > 0 ? config.spacings[0] : 0;
@@ -122,6 +166,7 @@
}
V1_0::BandConfig BandConfigToHal(JNIEnv *env, jobject jConfig, Region ®ion) {
+ ALOGV("BandConfigToHal()");
auto jDescriptor = env->GetObjectField(jConfig, gjni.BandConfig.descriptor);
if (jDescriptor == nullptr) {
ALOGE("Descriptor is missing");
diff --git a/services/core/jni/com_android_server_radio_convert.h b/services/core/jni/com_android_server_radio_convert.h
index b7e5b9c..dba948e 100644
--- a/services/core/jni/com_android_server_radio_convert.h
+++ b/services/core/jni/com_android_server_radio_convert.h
@@ -37,6 +37,9 @@
JavaRef BandConfigFromHal(JNIEnv *env, const V1_0::BandConfig &config, Region region);
V1_0::BandConfig BandConfigToHal(JNIEnv *env, jobject jConfig, Region ®ion);
+bool ThrowIfFailed(JNIEnv *env, const hardware::Return<V1_0::Result> &hidlResult);
+bool ThrowIfFailed(JNIEnv *env, const hardware::Return<void> &hidlResult);
+
} // namespace convert
} // namespace radio
} // namespace server
diff --git a/services/core/jni/com_android_server_radio_types.h b/services/core/jni/com_android_server_radio_types.h
index f2f253c..8430e05 100644
--- a/services/core/jni/com_android_server_radio_types.h
+++ b/services/core/jni/com_android_server_radio_types.h
@@ -27,6 +27,18 @@
* frameworks/base/core/java/android/hardware/radio/RadioManager.java.
*/
+// Keep in sync with STATUS_* constants from RadioManager.java.
+enum class Status : jint {
+ OK = 0,
+ ERROR = -0x80000000ll, // Integer.MIN_VALUE
+ PERMISSION_DENIED = -1, // -EPERM
+ NO_INIT = -19, // -ENODEV
+ BAD_VALUE = -22, // -EINVAL
+ DEAD_OBJECT = -32, // -EPIPE
+ INVALID_OPERATION = -38, // -ENOSYS
+ TIMED_OUT = -110, // -ETIMEDOUT
+};
+
// Keep in sync with REGION_* constants from RadioManager.java.
enum class Region : jint {
ITU_1 = 0,
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 100e459..51478b3 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -325,9 +325,6 @@
}
IBinder binder = server.asBinder();
try {
- if (mDeviceInfo == null) {
- mDeviceInfo = server.getDeviceInfo();
- }
binder.linkToDeath(this, 0);
mServer = server;
} catch (RemoteException e) {
diff --git a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
index 0cf4994..2e8b068 100644
--- a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
@@ -69,7 +69,7 @@
Notification n = builder.build();
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel, true);
return r;
}
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index d4904f5..5e8b3d4 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -259,7 +259,7 @@
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel, true);
mService.addNotification(r);
return r;
}
@@ -769,7 +769,7 @@
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel, true);
mService.addNotification(r);
mService.buzzBeepBlinkLocked(r);
diff --git a/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
index 24cb72e..33d2d07 100644
--- a/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
@@ -53,21 +53,21 @@
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
left.setGlobalSortKey("first");
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
right.setGlobalSortKey("second");
NotificationRecord last = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
final List<NotificationRecord> expected = new ArrayList<>();
@@ -93,13 +93,13 @@
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
right.setGlobalSortKey("not null");
final List<NotificationRecord> expected = new ArrayList<>();
@@ -124,14 +124,14 @@
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
left.setGlobalSortKey("not null");
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
final List<NotificationRecord> expected = new ArrayList<>();
expected.add(left);
diff --git a/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java b/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
index 3dbd803..7a2dbaf 100644
--- a/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
@@ -71,7 +71,7 @@
Notification n = builder.build();
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel, true);
return r;
}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
index 84945ab..ccd2db0 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
@@ -108,7 +108,7 @@
.build();
mRecordMinCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
callPkg, 1, "minCall", callUid, callUid, n1,
- new UserHandle(userId), "", 2000), getDefaultChannel());
+ new UserHandle(userId), "", 2000), getDefaultChannel(), false);
mRecordMinCall.setUserImportance(NotificationManager.IMPORTANCE_MIN);
Notification n2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -118,7 +118,7 @@
.build();
mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
callPkg, 1, "highcall", callUid, callUid, n2,
- new UserHandle(userId), "", 1999), getDefaultChannel());
+ new UserHandle(userId), "", 1999), getDefaultChannel(), false);
mRecordHighCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
Notification n3 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -128,14 +128,14 @@
.build();
mRecordDefaultMedia = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "media", uid2, uid2, n3, new UserHandle(userId),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), false);
mRecordDefaultMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
Notification n4 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
.setStyle(new Notification.MessagingStyle("sender!")).build();
mRecordInlineReply = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "inlinereply", uid2, uid2, n4, new UserHandle(userId),
- "", 1599), getDefaultChannel());
+ "", 1599), getDefaultChannel(), false);
mRecordInlineReply.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
mRecordInlineReply.setPackagePriority(Notification.PRIORITY_MAX);
@@ -143,27 +143,27 @@
.setCategory(Notification.CATEGORY_MESSAGE).build();
mRecordSms = new NotificationRecord(mContext, new StatusBarNotification(smsPkg,
smsPkg, 1, "sms", smsUid, smsUid, n5, new UserHandle(userId),
- "", 1299), getDefaultChannel());
+ "", 1299), getDefaultChannel(), false);
mRecordSms.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
Notification n6 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
mRecordStarredContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "starred", uid2, uid2, n6, new UserHandle(userId),
- "", 1259), getDefaultChannel());
+ "", 1259), getDefaultChannel(), false);
mRecordStarredContact.setContactAffinity(ValidateNotificationPeople.STARRED_CONTACT);
mRecordStarredContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
Notification n7 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
mRecordContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "contact", uid2, uid2, n7, new UserHandle(userId),
- "", 1259), getDefaultChannel());
+ "", 1259), getDefaultChannel(), false);
mRecordContact.setContactAffinity(ValidateNotificationPeople.VALID_CONTACT);
mRecordContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
Notification n8 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
mRecordUrgent = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "urgent", uid2, uid2, n8, new UserHandle(userId),
- "", 1258), getDefaultChannel());
+ "", 1258), getDefaultChannel(), false);
mRecordUrgent.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
Notification n9 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -173,7 +173,7 @@
.build();
mRecordCheater = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "cheater", uid2, uid2, n9, new UserHandle(userId),
- "", 9258), getDefaultChannel());
+ "", 9258), getDefaultChannel(), false);
mRecordCheater.setUserImportance(NotificationManager.IMPORTANCE_LOW);
mRecordCheater.setPackagePriority(Notification.PRIORITY_MAX);
@@ -181,7 +181,7 @@
.setStyle(new Notification.InboxStyle().setSummaryText("message!")).build();
mRecordEmail = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "email", uid2, uid2, n10, new UserHandle(userId),
- "", 1599), getDefaultChannel());
+ "", 1599), getDefaultChannel(), false);
mRecordEmail.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
Notification n11 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -190,7 +190,7 @@
.build();
mRecordCheaterColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "cheater", uid2, uid2, n11, new UserHandle(userId),
- "", 9258), getDefaultChannel());
+ "", 9258), getDefaultChannel(), false);
mRecordCheaterColorized.setUserImportance(NotificationManager.IMPORTANCE_LOW);
}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index f41a99f..f3eb4f8 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -104,7 +104,12 @@
public TestableNotificationManagerService(Context context) { super(context); }
@Override
- protected boolean isCallerSystem() {
+ protected boolean isCallingUidSystem() {
+ return true;
+ }
+
+ @Override
+ protected boolean isCallerSystemOrPhone() {
return true;
}
@@ -160,7 +165,7 @@
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", uid, 0,
nb.build(), new UserHandle(uid), null, 0);
- return new NotificationRecord(mContext, sbn, channel);
+ return new NotificationRecord(mContext, sbn, channel, true);
}
private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
return generateNotificationRecord(channel, null);
@@ -179,7 +184,7 @@
}
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", uid, 0,
nb.build(), new UserHandle(uid), null, 0);
- return new NotificationRecord(mContext, sbn, channel);
+ return new NotificationRecord(mContext, sbn, channel, true);
}
@Test
@@ -411,6 +416,21 @@
}
@Test
+ public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
+ final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
+ sbn.getNotification().flags =
+ Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+ sbn.getId(), sbn.getNotification(), sbn.getUserId());
+ sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+ sbn.getId(), sbn.getNotification(), sbn.getUserId());
+ mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
+ waitForIdle();
+ assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
+ }
+
+ @Test
public void testFindGroupNotificationsLocked() throws Exception {
// make sure the same notification can be found in both lists and returned
final NotificationRecord group1 = generateNotificationRecord(
@@ -449,7 +469,6 @@
}
}
-
@Test
public void testTvExtenderChannelOverride_onTv() throws Exception {
mNotificationManagerService.setIsTelevision(true);
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 1c8ca84..66f3799 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -21,7 +21,6 @@
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
@@ -61,6 +60,10 @@
private final Context mMockContext = Mockito.mock(Context.class);
@Mock PackageManager mPm;
+ // constants for targetSdk version. N is pre channels, O is post.
+ private final boolean N = false;
+ private final boolean O = true;
+
private final String pkg = "com.android.server.notification";
private final int uid = 9583;
private final String pkg2 = "pkg2";
@@ -76,7 +79,6 @@
new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "test",
NotificationManager.IMPORTANCE_UNSPECIFIED);
private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
- final ApplicationInfo legacy = new ApplicationInfo();
final ApplicationInfo upgrade = new ApplicationInfo();
private static final long[] CUSTOM_VIBRATION = new long[] {
@@ -100,17 +102,13 @@
InstrumentationRegistry.getContext().getResources());
when(mMockContext.getPackageManager()).thenReturn(mPm);
- legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
upgrade.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
- try {
- when(mPm.getApplicationInfoAsUser(eq(pkg), anyInt(), anyInt())).thenReturn(legacy);
- when(mPm.getApplicationInfoAsUser(eq(pkg2), anyInt(), anyInt())).thenReturn(upgrade);
- } catch (PackageManager.NameNotFoundException e) {}
+ when(mMockContext.getApplicationInfo()).thenReturn(upgrade);
}
- private StatusBarNotification getNotification(boolean preO, boolean noisy, boolean defaultSound,
- boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights) {
- when(mMockContext.getApplicationInfo()).thenReturn(preO ? legacy : upgrade);
+ private StatusBarNotification getNotification(boolean supportsChannels, boolean noisy,
+ boolean defaultSound, boolean buzzy, boolean defaultVibration, boolean lights,
+ boolean defaultLights) {
final Builder builder = new Builder(mMockContext)
.setContentTitle("foo")
.setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -149,13 +147,13 @@
}
builder.setDefaults(defaults);
- if (!preO) {
+ if (supportsChannels) {
builder.setChannelId(channelId);
}
Notification n = builder.build();
- if (preO) {
+ if (!supportsChannels) {
return new StatusBarNotification(pkg, pkg, id1, tag1, uid, uid, n,
mUser, null, uid);
} else {
@@ -172,11 +170,11 @@
public void testSound_default_preUpgradeUsesNotification() throws Exception {
defaultChannel.setSound(null, null);
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
}
@@ -185,11 +183,11 @@
public void testSound_custom_preUpgradeUsesNotification() throws Exception {
defaultChannel.setSound(null, null);
// pre upgrade, custom sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(CUSTOM_SOUND, record.getSound());
assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
}
@@ -199,11 +197,11 @@
defaultChannel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(CUSTOM_SOUND, record.getSound());
assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
}
@@ -211,11 +209,11 @@
@Test
public void testSound_noSound_preUpgrade() throws Exception {
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(N, false /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(null, record.getSound());
assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
}
@@ -224,11 +222,11 @@
public void testSound_default_upgradeUsesChannel() throws Exception {
channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
// post upgrade, default sound.
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(CUSTOM_SOUND, record.getSound());
assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
}
@@ -237,11 +235,11 @@
public void testVibration_default_preUpgradeUsesNotification() throws Exception {
defaultChannel.enableVibration(false);
// pre upgrade, default vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(N, false /* noisy */,
false /* defaultSound */, true /* buzzy */, true /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertNotNull(record.getVibration());
}
@@ -249,11 +247,11 @@
public void testVibration_custom_preUpgradeUsesNotification() throws Exception {
defaultChannel.enableVibration(false);
// pre upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(N, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(CUSTOM_VIBRATION, record.getVibration());
}
@@ -262,11 +260,11 @@
defaultChannel.enableVibration(true);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
// pre upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(N, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertTrue(!Objects.equals(CUSTOM_VIBRATION, record.getVibration()));
}
@@ -274,20 +272,20 @@
public void testVibration_custom_upgradeUsesChannel() throws Exception {
channel.enableVibration(true);
// post upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(O, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(CUSTOM_CHANNEL_VIBRATION, record.getVibration());
}
@Test
public void testImportance_preUpgrade() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
}
@@ -295,11 +293,11 @@
public void testImportance_locked_preUpgrade() throws Exception {
defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(NotificationManager.IMPORTANCE_LOW, record.getImportance());
}
@@ -307,39 +305,39 @@
public void testImportance_locked_unspecified_preUpgrade() throws Exception {
defaultChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
}
@Test
public void testImportance_upgrade() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(NotificationManager.IMPORTANCE_DEFAULT, record.getImportance());
}
@Test
public void testLights_preUpgrade_noLight() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertNull(record.getLight());
}
@Test
public void testLights_preUpgrade() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(CUSTOM_LIGHT, record.getLight());
}
@@ -347,11 +345,11 @@
public void testLights_locked_preUpgrade() throws Exception {
defaultChannel.enableLights(true);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertFalse(CUSTOM_LIGHT.equals(record.getLight()));
}
@@ -366,10 +364,10 @@
NotificationRecord.Light expected = new NotificationRecord.Light(
defaultLightColor, defaultLightOn, defaultLightOff);
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, true /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(expected, record.getLight());
}
@@ -382,19 +380,19 @@
NotificationRecord.Light expected = new NotificationRecord.Light(
Color.BLUE, defaultLightOn, defaultLightOff);
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(expected, record.getLight());
}
@Test
public void testLights_upgrade_noLight() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, O);
assertNull(record.getLight());
}
}
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index ce899e3..8ab6d08 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -124,7 +124,7 @@
.build();
mRecordGroupGSortA = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiGroupGSortA, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mNotiGroupGSortB = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("B")
@@ -134,7 +134,7 @@
.build();
mRecordGroupGSortB = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiGroupGSortB, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mNotiNoGroup = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("C")
@@ -142,7 +142,7 @@
.build();
mRecordNoGroup = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiNoGroup, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mNotiNoGroup2 = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("D")
@@ -150,7 +150,7 @@
.build();
mRecordNoGroup2 = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiNoGroup2, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mNotiNoGroupSortA = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("E")
@@ -159,7 +159,7 @@
.build();
mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiNoGroupSortA, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mAudioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
@@ -314,8 +314,6 @@
assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
compareChannels(channel2,
mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
- assertNotNull(mHelper.getNotificationChannel(
- PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false));
List<NotificationChannelGroup> actualGroups =
mHelper.getNotificationChannelGroups(PKG, UID, false).getList();
@@ -375,18 +373,13 @@
assertNull(mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
assertNull(mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false));
assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG, UID));
- //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID));
+ assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID));
assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
}
@Test
public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception {
- NotificationChannel channel1 =
- new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_DEFAULT);
-
- mHelper.createNotificationChannel(PKG, UID, channel1, true);
-
- ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(),
+ ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
NotificationChannel.DEFAULT_CHANNEL_ID);
loadStreamXml(baos);
@@ -401,16 +394,12 @@
@Test
public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception {
- NotificationChannel channel1 =
- new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN);
- mHelper.createNotificationChannel(PKG, UID, channel1, true);
-
final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID,
NotificationChannel.DEFAULT_CHANNEL_ID, false);
defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mHelper.updateNotificationChannel(PKG, UID, defaultChannel);
- ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(),
+ ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
NotificationChannel.DEFAULT_CHANNEL_ID);
loadStreamXml(baos);
@@ -445,12 +434,9 @@
| NotificationChannel.USER_LOCKED_VISIBILITY,
updated1.getUserLockedFields());
- // STOPSHIP - this should be reversed after the STOPSHIP is removed in the tested code.
// No Default Channel created for updated packages
- // assertEquals(null, mHelper.getNotificationChannel(UPDATED_PKG, UID2,
- // NotificationChannel.DEFAULT_CHANNEL_ID, false));
- assertTrue(mHelper.getNotificationChannel(UPDATED_PKG, UID2,
- NotificationChannel.DEFAULT_CHANNEL_ID, false) != null);
+ assertEquals(null, mHelper.getNotificationChannel(UPDATED_PKG, UID2,
+ NotificationChannel.DEFAULT_CHANNEL_ID, false));
}
@Test
@@ -466,12 +452,9 @@
when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded);
loadStreamXml(baos);
- // STOPSHIP - this should be reversed after the STOPSHIP is removed in the tested code.
// Default Channel should be gone.
- // assertEquals(null, mHelper.getNotificationChannel(PKG, UID,
- // NotificationChannel.DEFAULT_CHANNEL_ID, false));
- assertTrue(mHelper.getNotificationChannel(UPDATED_PKG, UID2,
- NotificationChannel.DEFAULT_CHANNEL_ID, false) != null);
+ assertEquals(null, mHelper.getNotificationChannel(PKG, UID,
+ NotificationChannel.DEFAULT_CHANNEL_ID, false));
}
@Test
@@ -713,20 +696,14 @@
// Returns only non-deleted channels
List<NotificationChannel> channels =
mHelper.getNotificationChannels(PKG, UID, false).getList();
- assertEquals(2, channels.size()); // Default channel + non-deleted channel
- for (NotificationChannel nc : channels) {
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
- compareChannels(channel2, nc);
- }
- }
+ assertEquals(1, channels.size());
+ compareChannels(channel2, channels.get(0));
// Returns deleted channels too
channels = mHelper.getNotificationChannels(PKG, UID, true).getList();
- assertEquals(3, channels.size()); // Includes default channel
+ assertEquals(2, channels.size());
for (NotificationChannel nc : channels) {
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
- compareChannels(channelMap.get(nc.getId()), nc);
- }
+ compareChannels(channelMap.get(nc.getId()), nc);
}
}
@@ -824,8 +801,8 @@
mHelper.permanentlyDeleteNotificationChannels(PKG, UID);
- // Only default channel remains
- assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
+ // No channels remain
+ assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
}
@Test
@@ -866,6 +843,36 @@
}
@Test
+ public void testOnUserRemoved() throws Exception {
+ int[] user0Uids = {98, 235, 16, 3782};
+ int[] user1Uids = new int[user0Uids.length];
+ for (int i = 0; i < user0Uids.length; i++) {
+ user1Uids[i] = UserHandle.PER_USER_RANGE + user0Uids[i];
+
+ final ApplicationInfo legacy = new ApplicationInfo();
+ legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+ when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy);
+
+ // create records with the default channel for all user 0 and user 1 uids
+ mHelper.getImportance(PKG, user0Uids[i]);
+ mHelper.getImportance(PKG, user1Uids[i]);
+ }
+
+ mHelper.onUserRemoved(1);
+
+ // user 0 records remain
+ for (int i = 0; i < user0Uids.length; i++) {
+ assertEquals(1,
+ mHelper.getNotificationChannels(PKG, user0Uids[i], false).getList().size());
+ }
+ // user 1 records are gone
+ for (int i = 0; i < user1Uids.length; i++) {
+ assertEquals(0,
+ mHelper.getNotificationChannels(PKG, user1Uids[i], false).getList().size());
+ }
+ }
+
+ @Test
public void testOnPackageChanged_packageRemoval() throws Exception {
// Deleted
NotificationChannel channel1 =
@@ -874,13 +881,32 @@
mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
- assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
+ // since this is a pre upgrade app, clearing data should restore the default channel
+ assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
+ assertEquals(NotificationChannel.DEFAULT_CHANNEL_ID,
+ mHelper.getNotificationChannels(PKG, UID, true).getList().get(0).getId());
// Not deleted
mHelper.createNotificationChannel(PKG, UID, channel1, true);
-
mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
- assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size());
+ assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size());
+ }
+
+ @Test
+ public void testOnPackageChanged_packageRemoval_updatedPackage() throws Exception {
+ // Deleted
+ NotificationChannel channel1 =
+ new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(UPDATED_PKG, UID2, channel1, true);
+ mHelper.onPackagesChanged(
+ true, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
+ assertEquals(0, mHelper.getNotificationChannels(UPDATED_PKG, UID2, true).getList().size());
+
+ // Not deleted
+ mHelper.createNotificationChannel(UPDATED_PKG, UID2, channel1, true);
+ mHelper.onPackagesChanged(
+ false, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
+ assertEquals(1, mHelper.getNotificationChannels(UPDATED_PKG, UID2, false).getList().size());
}
@Test
@@ -901,7 +927,23 @@
mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
- assertEquals(0, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size());
+ // default channel restored
+ assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size());
+ assertNull(mHelper.getNotificationChannelGroups(PKG, UID, true).getList().get(0).getId());
+ }
+
+ @Test
+ public void testOnPackageChanged_packageRemoval_groups_upgraded() throws Exception {
+ NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+ mHelper.createNotificationChannelGroup(UPDATED_PKG, UID2, ncg, true);
+ NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
+ mHelper.createNotificationChannelGroup(UPDATED_PKG, UID2, ncg2, true);
+
+ mHelper.onPackagesChanged(
+ true, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
+
+ assertEquals(0,
+ mHelper.getNotificationChannelGroups(UPDATED_PKG, UID2, true).getList().size());
}
@Test
@@ -975,9 +1017,8 @@
assertEquals(3, actual.size());
for (NotificationChannelGroup group : actual) {
if (group.getId() == null) {
- assertEquals(2, group.getChannels().size()); // misc channel too
- assertTrue(channel3.getId().equals(group.getChannels().get(0).getId())
- || channel3.getId().equals(group.getChannels().get(1).getId()));
+ assertEquals(1, group.getChannels().size());
+ assertTrue(channel3.getId().equals(group.getChannels().get(0).getId()));
} else if (group.getId().equals(ncg.getId())) {
assertEquals(2, group.getChannels().size());
if (group.getChannels().get(0).getId().equals(channel1.getId())) {
@@ -1011,12 +1052,8 @@
List<NotificationChannelGroup> actual =
mHelper.getNotificationChannelGroups(PKG, UID, true).getList();
- assertEquals(2, actual.size());
- for (NotificationChannelGroup group : actual) {
- if (Objects.equals(group.getId(), ncg.getId())) {
- assertEquals(1, group.getChannels().size());
- }
- }
+ assertEquals(1, actual.size());
+ assertEquals(1, actual.get(0).getChannels().size());
}
@Test
@@ -1067,7 +1104,7 @@
for (int i = 0; i < numPackages; i++) {
JSONObject object = actual.getJSONObject(i);
assertTrue(expectedChannels.containsKey(object.get("packageName")));
- assertEquals(expectedChannels.get(object.get("packageName")).intValue() + 1,
+ assertEquals(expectedChannels.get(object.get("packageName")).intValue(),
object.getInt("channelCount"));
}
}
diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
index 51ec05c..b1cb4d7 100644
--- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
@@ -107,9 +107,9 @@
UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, r.sbn.getPackageName(), "one", 1);
- // 3 = one for each snooze, above + one for cancel itself.
- verify(mAm, times(3)).cancel(any(PendingIntent.class));
- assertFalse(mSnoozeHelper.isSnoozed(
+ // 2 = one for each snooze, above, zero for the cancel.
+ verify(mAm, times(2)).cancel(any(PendingIntent.class));
+ assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
@@ -131,11 +131,11 @@
UserHandle.USER_ALL, r3.sbn.getPackageName(), r3.getKey()));
mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, false);
- // 5 = once for each snooze above (3) + once for each notification canceled (2).
- verify(mAm, times(5)).cancel(any(PendingIntent.class));
- assertFalse(mSnoozeHelper.isSnoozed(
+ // 3 = once for each snooze above (3), only.
+ verify(mAm, times(3)).cancel(any(PendingIntent.class));
+ assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
- assertFalse(mSnoozeHelper.isSnoozed(
+ assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_ALL, r3.sbn.getPackageName(), r3.getKey()));
@@ -157,17 +157,47 @@
UserHandle.USER_SYSTEM, r3.sbn.getPackageName(), r3.getKey()));
mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, "pkg2");
- // 4 = once for each snooze above (3) + once for each notification canceled (1).
- verify(mAm, times(4)).cancel(any(PendingIntent.class));
+ // 3 = once for each snooze above (3), only.
+ verify(mAm, times(3)).cancel(any(PendingIntent.class));
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
- assertFalse(mSnoozeHelper.isSnoozed(
+ assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r3.sbn.getPackageName(), r3.getKey()));
}
@Test
+ public void testCancelDoesNotUnsnooze() throws Exception {
+ NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+ mSnoozeHelper.snooze(r, 1000);
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+
+ mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, r.sbn.getPackageName(), "one", 1);
+
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+ }
+
+ @Test
+ public void testCancelDoesNotRepost() throws Exception {
+ NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+ NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
+ mSnoozeHelper.snooze(r, 1000);
+ mSnoozeHelper.snooze(r2 , 1000);
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
+
+ mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, r.sbn.getPackageName(), "one", 1);
+
+ mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM);
+ verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r);
+ }
+
+ @Test
public void testRepost() throws Exception {
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
mSnoozeHelper.snooze(r, 1000);
@@ -282,7 +312,7 @@
TEST_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_LOW);
return new NotificationRecord(getContext(), new StatusBarNotification(
pkg, pkg, id, tag, 0, 0, n, user, null,
- System.currentTimeMillis()), notificationChannel);
+ System.currentTimeMillis()), notificationChannel, true);
}
private NotificationRecord getNotificationRecord(String pkg, int id, String tag,
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index cc682c4..fa72416 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -18,6 +18,7 @@
package="com.android.frameworks.servicestests">
<uses-permission android:name="android.permission.READ_LOGS" />
+ <uses-permission android:name="android.permission.ACCESS_VR_MANAGER" />
<uses-permission android:name="android.permission.ACCOUNT_MANAGER" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index c78488f..bb7e20b 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -368,8 +368,8 @@
}
@Test
- public void testSetActiveScorer_noRequestNetworkScoresPermission() {
- when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ public void testSetActiveScorer_noScoreNetworksPermission() {
+ when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 0694eae..ceb92de 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -228,30 +228,23 @@
}
@Test
- public void testSetActiveScorer_nullPackage_validDefault() throws Exception {
- String packageName = "package";
- String defaultPackage = "defaultPackage";
- setNetworkRecoPackageSetting(packageName);
- setDefaultNetworkRecommendationPackage(defaultPackage);
- final ComponentName recoComponent = new ComponentName(defaultPackage, "class1");
- mockScoreNetworksGranted(recoComponent.getPackageName());
- mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+ public void testSetActiveScorer_nullPackage_currentIsSet() throws Exception {
+ setNetworkRecoPackageSetting("package");
assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
verify(mSettingsFacade).putString(mMockContext,
- Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, null);
+ verify(mSettingsFacade).putInt(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+ NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
}
@Test
- public void testSetActiveScorer_nullPackage_invalidDefault() throws Exception {
- String packageName = "package";
- String defaultPackage = "defaultPackage";
- setNetworkRecoPackageSetting(packageName);
- setDefaultNetworkRecommendationPackage(defaultPackage);
+ public void testSetActiveScorer_nullPackage_currentIsNull() throws Exception {
+ setNetworkRecoPackageSetting(null);
- assertFalse(mNetworkScorerAppManager.setActiveScorer(null));
- verify(mSettingsFacade, never()).putString(any(),
- eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+ assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
+ verify(mSettingsFacade, never()).putString(any(), any(), any());
}
@Test
@@ -266,6 +259,9 @@
assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
verify(mSettingsFacade).putString(mMockContext,
Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage);
+ verify(mSettingsFacade).putInt(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+ NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
}
@Test
@@ -341,6 +337,32 @@
}
@Test
+ public void testUpdateState_currentPackageNull_defaultNull() throws Exception {
+ setDefaultNetworkRecommendationPackage(null);
+ setNetworkRecoPackageSetting(null);
+
+ mNetworkScorerAppManager.updateState();
+
+ verify(mSettingsFacade, never()).putString(any(),
+ eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
+ verify(mSettingsFacade, never()).putInt(any(),
+ eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+ }
+
+ @Test
+ public void testUpdateState_currentPackageEmpty_defaultEmpty() throws Exception {
+ setDefaultNetworkRecommendationPackage("");
+ setNetworkRecoPackageSetting("");
+
+ mNetworkScorerAppManager.updateState();
+
+ verify(mSettingsFacade, never()).putString(any(),
+ eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
+ verify(mSettingsFacade, never()).putInt(any(),
+ eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+ }
+
+ @Test
public void testUpdateState_currentPackageNotValid_sameAsDefault() throws Exception {
String defaultPackage = "defaultPackage";
setDefaultNetworkRecommendationPackage(defaultPackage);
diff --git a/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java
new file mode 100644
index 0000000..9a9c243
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.internal.app.NightDisplayController.LocalTime;
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.display.DisplayTransformManager;
+import com.android.server.display.NightDisplayService;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.twilight.TwilightState;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+import java.util.Calendar;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.Mockito.doReturn;
+
+@RunWith(AndroidJUnit4.class)
+public class NightDisplayServiceTest {
+
+ private Context mContext;
+ private int mUserId;
+
+ private TwilightManager mTwilightManager;
+
+ private NightDisplayController mNightDisplayController;
+ private NightDisplayService mNightDisplayService;
+
+ @Before
+ public void setUp() {
+ mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
+ mUserId = ActivityManager.getCurrentUser();
+
+ doReturn(mContext).when(mContext).getApplicationContext();
+
+ final MockContentResolver cr = new MockContentResolver(mContext);
+ cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ doReturn(cr).when(mContext).getContentResolver();
+
+ final AlarmManager am = Mockito.mock(AlarmManager.class);
+ doReturn(am).when(mContext).getSystemService(Context.ALARM_SERVICE);
+
+ final DisplayTransformManager dtm = Mockito.mock(DisplayTransformManager.class);
+ LocalServices.addService(DisplayTransformManager.class, dtm);
+
+ mTwilightManager = Mockito.mock(TwilightManager.class);
+ LocalServices.addService(TwilightManager.class, mTwilightManager);
+
+ mNightDisplayController = new NightDisplayController(mContext, mUserId);
+ mNightDisplayService = new NightDisplayService(mContext);
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(DisplayTransformManager.class);
+ LocalServices.removeServiceForTest(TwilightManager.class);
+
+ mNightDisplayService = null;
+ mNightDisplayController = null;
+
+ mTwilightManager = null;
+
+ mUserId = UserHandle.USER_NULL;
+ mContext = null;
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ /**
+ * Convenience for making a {@link LocalTime} instance with an offset relative to now.
+ *
+ * @param offsetMinutes the offset relative to now (in minutes)
+ * @return the LocalTime instance
+ */
+ private LocalTime getLocalTimeRelativeToNow(int offsetMinutes) {
+ final Calendar c = Calendar.getInstance();
+ c.add(Calendar.MINUTE, offsetMinutes);
+ return new LocalTime(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
+ }
+
+ /**
+ * Configures Night display to use a custom schedule.
+ *
+ * @param startTimeOffset the offset relative to now to activate Night display (in minutes)
+ * @param endTimeOffset the offset relative to now to deactivate Night display (in minutes)
+ */
+ private void setAutoModeCustom(int startTimeOffset, int endTimeOffset) {
+ mNightDisplayController.setAutoMode(NightDisplayController.AUTO_MODE_CUSTOM);
+ mNightDisplayController.setCustomStartTime(getLocalTimeRelativeToNow(startTimeOffset));
+ mNightDisplayController.setCustomEndTime(getLocalTimeRelativeToNow(endTimeOffset));
+ }
+
+ /**
+ * Configures Night display to use the twilight schedule.
+ *
+ * @param sunsetOffset the offset relative to now for sunset (in minutes)
+ * @param sunriseOffset the offset relative to now for sunrise (in minutes)
+ */
+ private void setAutoModeTwilight(int sunsetOffset, int sunriseOffset) {
+ mNightDisplayController.setAutoMode(NightDisplayController.AUTO_MODE_TWILIGHT);
+
+ final LocalTime sunset = getLocalTimeRelativeToNow(sunsetOffset);
+ final LocalTime sunrise = getLocalTimeRelativeToNow(sunriseOffset);
+
+ final Calendar now = Calendar.getInstance();
+ long sunsetMillis = sunset.getDateTimeBefore(now).getTimeInMillis();
+ long sunriseMillis = sunrise.getDateTimeBefore(now).getTimeInMillis();
+ if (sunsetMillis < sunriseMillis) {
+ sunsetMillis = sunset.getDateTimeAfter(now).getTimeInMillis();
+ } else {
+ sunriseMillis = sunrise.getDateTimeAfter(now).getTimeInMillis();
+ }
+
+ final TwilightState state = new TwilightState(sunriseMillis, sunsetMillis);
+ doReturn(state).when(mTwilightManager).getLastTwilightState();
+ }
+
+ /**
+ * Configures the Night display activated state.
+ *
+ * @param activated {@code true} if Night display should be activated
+ * @param lastActivatedTimeOffset the offset relative to now to record that Night display was
+ activated (in minutes)
+ */
+ private void setActivated(boolean activated, int lastActivatedTimeOffset) {
+ mNightDisplayController.setActivated(activated);
+
+ final Calendar c = Calendar.getInstance();
+ c.add(Calendar.MINUTE, lastActivatedTimeOffset);
+ Secure.putLongForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, c.getTimeInMillis(), mUserId);
+ }
+
+ /**
+ * Convenience method to start {@link #mNightDisplayService}.
+ */
+ private void startService() {
+ Secure.putIntForUser(mContext.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, mUserId);
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mNightDisplayService.onStart();
+ mNightDisplayService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+ mNightDisplayService.onStartUser(mUserId);
+ }
+ });
+ }
+
+ /**
+ * Convenience method for asserting whether Night display should be activated.
+ *
+ * @param activated the expected activated state of Night display
+ */
+ private void assertActivated(boolean activated) {
+ assertWithMessage("Invalid Night display activated state")
+ .that(mNightDisplayController.isActivated())
+ .isEqualTo(activated);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index 1896cda..4c53915 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -18,6 +18,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@@ -31,6 +32,7 @@
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
+import android.app.backup.ISelectBackupTransportCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -54,6 +56,9 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
@SmallTest
@Presubmit
@@ -568,9 +573,30 @@
}
@Test
- public void selectBackupTransportAsync_calledBeforeInitialize_ignored() throws RemoteException {
- mTrampoline.selectBackupTransportAsync(TRANSPORT_COMPONENT_NAME, null);
+ public void selectBackupTransportAsync_calledBeforeInitialize_ignored() throws Exception {
+ LinkedBlockingQueue<Integer> q = new LinkedBlockingQueue();
+ mTrampoline.selectBackupTransportAsync(
+ TRANSPORT_COMPONENT_NAME,
+ new ISelectBackupTransportCallback() {
+ @Override
+ public void onSuccess(String transportName) throws RemoteException {
+
+ }
+
+ @Override
+ public void onFailure(int reason) throws RemoteException {
+ q.offer(reason);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+ });
verifyNoMoreInteractions(mBackupManagerServiceMock);
+ Integer errorCode = q.poll(5, TimeUnit.SECONDS);
+ assertNotNull(errorCode);
+ assertEquals(BackupManager.ERROR_BACKUP_NOT_ALLOWED, (int) errorCode);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
new file mode 100644
index 0000000..650681e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.utils;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.Signature;
+import android.os.Process;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.backup.RefactoredBackupManagerService;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class AppBackupUtilsTest {
+ private static final String CUSTOM_BACKUP_AGENT_NAME = "custom.backup.agent";
+ private static final String TEST_PACKAGE_NAME = "test_package";
+
+ private final Random mRandom = new Random(1000000009);
+
+ @Test
+ public void appIsEligibleForBackup_backupNotAllowed_returnsFalse() throws Exception {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.flags = 0;
+ applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+ applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+ applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+ boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+ assertThat(isEligible).isFalse();
+ }
+
+ @Test
+ public void appIsEligibleForBackup_systemAppWithoutCustomBackupAgent_returnsFalse()
+ throws Exception {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+ applicationInfo.uid = Process.SYSTEM_UID;
+ applicationInfo.backupAgentName = null;
+ applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+ boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+ assertThat(isEligible).isFalse();
+ }
+
+ @Test
+ public void appIsEligibleForBackup_sharedStorageBackupPackage_returnsFalse() throws Exception {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+ applicationInfo.uid = Process.SYSTEM_UID;
+ applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+ applicationInfo.packageName = RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+
+ boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+ assertThat(isEligible).isFalse();
+ }
+
+ @Test
+ public void appIsEligibleForBackup_systemAppWithCustomBackupAgent_returnsTrue()
+ throws Exception {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+ applicationInfo.uid = Process.SYSTEM_UID;
+ applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+ applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+ boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+ assertThat(isEligible).isTrue();
+ }
+
+ @Test
+ public void appIsEligibleForBackup_nonSystemAppWithoutCustomBackupAgent_returnsTrue()
+ throws Exception {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+ applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+ applicationInfo.backupAgentName = null;
+ applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+ boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+ assertThat(isEligible).isTrue();
+ }
+
+ @Test
+ public void appIsEligibleForBackup_nonSystemAppWithCustomBackupAgent_returnsTrue()
+ throws Exception {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+ applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+ applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+ applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+ boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+ assertThat(isEligible).isTrue();
+ }
+
+ @Test
+ public void appIsStopped_returnsTrue() throws Exception {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
+
+ boolean isStopped = AppBackupUtils.appIsStopped(applicationInfo);
+
+ assertThat(isStopped).isTrue();
+ }
+
+ @Test
+ public void appIsStopped_returnsFalse() throws Exception {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.flags = ~ApplicationInfo.FLAG_STOPPED;
+
+ boolean isStopped = AppBackupUtils.appIsStopped(applicationInfo);
+
+ assertThat(isStopped).isFalse();
+ }
+
+ @Test
+ public void appGetsFullBackup_noCustomBackupAgent_returnsTrue() throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.backupAgentName = null;
+
+ boolean result = AppBackupUtils.appGetsFullBackup(packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void appGetsFullBackup_withCustomBackupAgentAndFullBackupOnlyFlag_returnsTrue()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.backupAgentName = "backup.agent";
+ packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
+
+ boolean result = AppBackupUtils.appGetsFullBackup(packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void appGetsFullBackup_withCustomBackupAgentAndWithoutFullBackupOnlyFlag_returnsFalse()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.backupAgentName = "backup.agent";
+ packageInfo.applicationInfo.flags = ~ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
+
+ boolean result = AppBackupUtils.appGetsFullBackup(packageInfo);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void appIsKeyValueOnly_noCustomBackupAgent_returnsTrue() throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.backupAgentName = null;
+
+ boolean result = AppBackupUtils.appIsKeyValueOnly(packageInfo);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void appIsKeyValueOnly_withCustomBackupAgentAndFullBackupOnlyFlag_returnsTrue()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.backupAgentName = "backup.agent";
+ packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
+
+ boolean result = AppBackupUtils.appIsKeyValueOnly(packageInfo);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void appIsKeyValueOnly_withCustomBackupAgentAndWithoutFullBackupOnlyFlag_returnsFalse()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.backupAgentName = "backup.agent";
+ packageInfo.applicationInfo.flags = ~ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
+
+ boolean result = AppBackupUtils.appIsKeyValueOnly(packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void signaturesMatch_targetIsNull_returnsFalse() throws Exception {
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[0], null);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void signaturesMatch_systemApplication_returnsTrue() throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void signaturesMatch_allowsUnsignedApps_bothSignaturesNull_returnsTrue()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = null;
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void signaturesMatch_allowsUnsignedApps_bothSignaturesEmpty_returnsTrue()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[0];
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void
+ signaturesMatch_allowsUnsignedApps_storedSignatureNullTargetSignatureEmpty_returnsTrue()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[0];
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void
+ signaturesMatch_allowsUnsignedApps_storedSignatureEmptyTargetSignatureNull_returnsTrue()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = null;
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void
+ signaturesMatch_disallowsAppsUnsignedOnOnlyOneDevice_storedSignatureIsNull_returnsFalse()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[]{generateRandomSignature()};
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void
+ signaturesMatch_disallowsAppsUnsignedOnOnlyOneDevice_targetSignatureIsNull_returnsFalse()
+ throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = null;
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[]{generateRandomSignature()},
+ packageInfo);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void signaturesMatch_signaturesMatch_returnsTrue() throws Exception {
+ Signature signature1 = generateRandomSignature();
+ Signature signature2 = generateRandomSignature();
+ Signature signature3 = generateRandomSignature();
+ assertThat(signature1).isNotEqualTo(signature2);
+ assertThat(signature2).isNotEqualTo(signature3);
+ assertThat(signature1).isNotEqualTo(signature3);
+
+ Signature signature1Copy = new Signature(signature1.toByteArray());
+ Signature signature2Copy = new Signature(signature2.toByteArray());
+ Signature signature3Copy = new Signature(signature3.toByteArray());
+ assertThat(signature1Copy).isEqualTo(signature1);
+ assertThat(signature2Copy).isEqualTo(signature2);
+ assertThat(signature3Copy).isEqualTo(signature3);
+
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[]{signature1, signature2, signature3};
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(
+ new Signature[]{signature3Copy, signature1Copy, signature2Copy}, packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void signaturesMatch_extraSignatureInTarget_returnsTrue() throws Exception {
+ Signature signature1 = generateRandomSignature();
+ Signature signature2 = generateRandomSignature();
+ Signature signature3 = generateRandomSignature();
+ assertThat(signature1).isNotEqualTo(signature2);
+ assertThat(signature2).isNotEqualTo(signature3);
+ assertThat(signature1).isNotEqualTo(signature3);
+
+ Signature signature1Copy = new Signature(signature1.toByteArray());
+ Signature signature2Copy = new Signature(signature2.toByteArray());
+ assertThat(signature1Copy).isEqualTo(signature1);
+ assertThat(signature2Copy).isEqualTo(signature2);
+
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[]{signature1, signature2, signature3};
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(
+ new Signature[]{signature2Copy, signature1Copy}, packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void signaturesMatch_extraSignatureInStored_returnsFalse() throws Exception {
+ Signature signature1 = generateRandomSignature();
+ Signature signature2 = generateRandomSignature();
+ Signature signature3 = generateRandomSignature();
+ assertThat(signature1).isNotEqualTo(signature2);
+ assertThat(signature2).isNotEqualTo(signature3);
+ assertThat(signature1).isNotEqualTo(signature3);
+
+ Signature signature1Copy = new Signature(signature1.toByteArray());
+ Signature signature2Copy = new Signature(signature2.toByteArray());
+ assertThat(signature1Copy).isEqualTo(signature1);
+ assertThat(signature2Copy).isEqualTo(signature2);
+
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[]{signature1Copy, signature2Copy};
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(
+ new Signature[]{signature1, signature2, signature3}, packageInfo);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void signaturesMatch_emptyStoredSignatures_returnsTrue() throws Exception {
+ Signature signature1 = generateRandomSignature();
+ Signature signature2 = generateRandomSignature();
+ Signature signature3 = generateRandomSignature();
+ assertThat(signature1).isNotEqualTo(signature2);
+ assertThat(signature2).isNotEqualTo(signature3);
+ assertThat(signature1).isNotEqualTo(signature3);
+
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[]{signature1, signature2, signature3};
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
+
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void signaturesMatch_emptyTargetSignatures_returnsFalse() throws Exception {
+ Signature signature1 = generateRandomSignature();
+ Signature signature2 = generateRandomSignature();
+ Signature signature3 = generateRandomSignature();
+ assertThat(signature1).isNotEqualTo(signature2);
+ assertThat(signature2).isNotEqualTo(signature3);
+ assertThat(signature1).isNotEqualTo(signature3);
+
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[0];
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(
+ new Signature[]{signature1, signature2, signature3}, packageInfo);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void signaturesMatch_oneNonMatchingSignature_returnsFalse() throws Exception {
+ Signature signature1 = generateRandomSignature();
+ Signature signature2 = generateRandomSignature();
+ Signature signature3 = generateRandomSignature();
+ Signature signature4 = generateRandomSignature();
+ assertThat(signature1).isNotEqualTo(signature2);
+ assertThat(signature2).isNotEqualTo(signature3);
+ assertThat(signature1).isNotEqualTo(signature3);
+ assertThat(signature1).isNotEqualTo(signature4);
+ assertThat(signature2).isNotEqualTo(signature4);
+ assertThat(signature3).isNotEqualTo(signature4);
+
+ Signature signature1Copy = new Signature(signature1.toByteArray());
+ Signature signature2Copy = new Signature(signature2.toByteArray());
+ assertThat(signature1Copy).isEqualTo(signature1);
+ assertThat(signature2Copy).isEqualTo(signature2);
+
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.signatures = new Signature[]{signature1, signature2, signature3};
+ packageInfo.applicationInfo = new ApplicationInfo();
+
+ boolean result = AppBackupUtils.signaturesMatch(
+ new Signature[]{signature1Copy, signature2Copy, signature4}, packageInfo);
+
+ assertThat(result).isFalse();
+ }
+
+ private Signature generateRandomSignature() {
+ byte[] signatureBytes = new byte[256];
+ mRandom.nextBytes(signatureBytes);
+ return new Signature(signatureBytes);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
new file mode 100644
index 0000000..87c587a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.utils;
+
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_ID;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IBackupManagerMonitor;
+import android.content.pm.PackageInfo;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BackupManagerMonitorUtilsTest {
+ @Mock private IBackupManagerMonitor mMonitorMock;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void monitorEvent_monitorIsNull_returnsNull() throws Exception {
+ IBackupManagerMonitor result = BackupManagerMonitorUtils.monitorEvent(null, 0, null, 0,
+ null);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void monitorEvent_monitorOnEventThrows_returnsNull() throws Exception {
+ doThrow(new RemoteException()).when(mMonitorMock).onEvent(any(Bundle.class));
+
+ IBackupManagerMonitor result = BackupManagerMonitorUtils.monitorEvent(mMonitorMock, 0, null,
+ 0, null);
+
+ verify(mMonitorMock).onEvent(any(Bundle.class));
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void monitorEvent_packageAndExtrasAreNull_fillsBundleCorrectly() throws Exception {
+ IBackupManagerMonitor result = BackupManagerMonitorUtils.monitorEvent(mMonitorMock, 1, null,
+ 2, null);
+
+ assertThat(result).isEqualTo(mMonitorMock);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mMonitorMock).onEvent(bundleCaptor.capture());
+ Bundle eventBundle = bundleCaptor.getValue();
+ assertThat(eventBundle.size()).isEqualTo(2);
+ assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_ID)).isEqualTo(1);
+ assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_CATEGORY)).isEqualTo(2);
+ }
+
+ @Test
+ public void monitorEvent_packageAndExtrasAreNotNull_fillsBundleCorrectly() throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = "test.package";
+ packageInfo.versionCode = 3;
+ Bundle extras = new Bundle();
+ extras.putInt("key1", 4);
+ extras.putString("key2", "value2");
+
+ IBackupManagerMonitor result = BackupManagerMonitorUtils.monitorEvent(mMonitorMock, 1,
+ packageInfo, 2, extras);
+
+ assertThat(result).isEqualTo(mMonitorMock);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mMonitorMock).onEvent(bundleCaptor.capture());
+ Bundle eventBundle = bundleCaptor.getValue();
+ assertThat(eventBundle.size()).isEqualTo(6);
+ assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_ID)).isEqualTo(1);
+ assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_CATEGORY)).isEqualTo(2);
+ assertThat(eventBundle.getString(EXTRA_LOG_EVENT_PACKAGE_NAME)).isEqualTo("test.package");
+ assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_PACKAGE_VERSION)).isEqualTo(3);
+ assertThat(eventBundle.getInt("key1")).isEqualTo(4);
+ assertThat(eventBundle.getString("key2")).isEqualTo("value2");
+ }
+
+ @Test
+ public void putMonitoringExtraString_bundleExists_fillsBundleCorrectly() throws Exception {
+ Bundle bundle = new Bundle();
+
+ Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(bundle, "key", "value");
+
+ assertThat(result).isEqualTo(bundle);
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.getString("key")).isEqualTo("value");
+ }
+
+ @Test
+ public void putMonitoringExtraString_bundleDoesNotExist_fillsBundleCorrectly()
+ throws Exception {
+ Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(null, "key", "value");
+
+ assertThat(result).isNotNull();
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.getString("key")).isEqualTo("value");
+ }
+
+
+ @Test
+ public void putMonitoringExtraLong_bundleExists_fillsBundleCorrectly() throws Exception {
+ Bundle bundle = new Bundle();
+
+ Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(bundle, "key", 123);
+
+ assertThat(result).isEqualTo(bundle);
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.getLong("key")).isEqualTo(123);
+ }
+
+ @Test
+ public void putMonitoringExtraLong_bundleDoesNotExist_fillsBundleCorrectly() throws Exception {
+ Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(null, "key", 123);
+
+ assertThat(result).isNotNull();
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.getLong("key")).isEqualTo(123);
+ }
+
+ @Test
+ public void putMonitoringExtraBoolean_bundleExists_fillsBundleCorrectly() throws Exception {
+ Bundle bundle = new Bundle();
+
+ Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(bundle, "key", true);
+
+ assertThat(result).isEqualTo(bundle);
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.getBoolean("key")).isTrue();
+ }
+
+ @Test
+ public void putMonitoringExtraBoolean_bundleDoesNotExist_fillsBundleCorrectly()
+ throws Exception {
+ Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(null, "key", true);
+
+ assertThat(result).isNotNull();
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.getBoolean("key")).isTrue();
+ }
+
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java
new file mode 100644
index 0000000..ebe6133
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.utils;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.BackupProgress;
+import android.app.backup.IBackupObserver;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BackupObserverUtilsTest {
+ private static final String PACKAGE_NAME = "some.package";
+
+ @Mock
+ private IBackupObserver mBackupObserverMock;
+ private final BackupProgress mBackupProgress = new BackupProgress(0, 0);
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void sendBackupOnUpdate_observerIsNull_doesNotThrow() throws Exception {
+ BackupObserverUtils.sendBackupOnUpdate(null, PACKAGE_NAME, mBackupProgress);
+
+ // Should not throw.
+ }
+
+ @Test
+ public void sendBackupOnUpdate_callsObserver() throws Exception {
+ BackupObserverUtils.sendBackupOnUpdate(mBackupObserverMock, PACKAGE_NAME, mBackupProgress);
+
+ verify(mBackupObserverMock).onUpdate(PACKAGE_NAME, mBackupProgress);
+ }
+
+ @Test
+ public void sendBackupOnUpdate_handlesRemoteException() throws Exception {
+ doThrow(new RemoteException()).when(mBackupObserverMock).onUpdate(PACKAGE_NAME,
+ mBackupProgress);
+
+ BackupObserverUtils.sendBackupOnUpdate(mBackupObserverMock, PACKAGE_NAME, mBackupProgress);
+
+ verify(mBackupObserverMock).onUpdate(PACKAGE_NAME, mBackupProgress);
+ }
+
+ @Test
+ public void sendBackupOnPackageResult_observerIsNull_doesNotThrow() throws Exception {
+ BackupObserverUtils.sendBackupOnPackageResult(null, PACKAGE_NAME, 1);
+
+ // Should not throw.
+ }
+
+ @Test
+ public void sendBackupOnPackageResult_callsObserver() throws Exception {
+ BackupObserverUtils.sendBackupOnPackageResult(mBackupObserverMock, PACKAGE_NAME, 1);
+
+ verify(mBackupObserverMock).onResult(PACKAGE_NAME, 1);
+ }
+
+ @Test
+ public void sendBackupOnPackageResult_handlesRemoteException() throws Exception {
+ doThrow(new RemoteException()).when(mBackupObserverMock).onResult(PACKAGE_NAME, 1);
+
+ BackupObserverUtils.sendBackupOnPackageResult(mBackupObserverMock, PACKAGE_NAME, 1);
+
+ verify(mBackupObserverMock).onResult(PACKAGE_NAME, 1);
+ }
+
+ @Test
+ public void sendBackupFinished_observerIsNull_doesNotThrow() throws Exception {
+ BackupObserverUtils.sendBackupFinished(null, 1);
+
+ // Should not throw.
+ }
+
+ @Test
+ public void sendBackupFinished_callsObserver() throws Exception {
+ BackupObserverUtils.sendBackupFinished(mBackupObserverMock, 1);
+
+ verify(mBackupObserverMock).backupFinished(1);
+ }
+
+ @Test
+ public void sendBackupFinished_handlesRemoteException() throws Exception {
+ doThrow(new RemoteException()).when(mBackupObserverMock).onResult(PACKAGE_NAME, 1);
+
+ BackupObserverUtils.sendBackupFinished(mBackupObserverMock, 1);
+
+ verify(mBackupObserverMock).backupFinished(1);
+ }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java
new file mode 100644
index 0000000..2f56598
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.utils;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IFullBackupRestoreObserver;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class FullBackupRestoreObserverUtilsTest {
+ private static final String PACKAGE_NAME = "some.package";
+ @Mock
+ private IFullBackupRestoreObserver mFullBackupRestoreObserverMock;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void sendStartRestore_observerIsNull_returnsNull() throws Exception {
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendStartRestore(null);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void sendStartRestore_callsObserver() throws Exception {
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendStartRestore(
+ mFullBackupRestoreObserverMock);
+
+ assertThat(result).isEqualTo(mFullBackupRestoreObserverMock);
+ verify(mFullBackupRestoreObserverMock).onStartRestore();
+ }
+
+ @Test
+ public void sendStartRestore_observerThrows_returnsNull() throws Exception {
+ doThrow(new RemoteException()).when(mFullBackupRestoreObserverMock).onStartRestore();
+
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendStartRestore(
+ mFullBackupRestoreObserverMock);
+
+ assertThat(result).isNull();
+ verify(mFullBackupRestoreObserverMock).onStartRestore();
+ }
+
+ @Test
+ public void sendOnRestorePackage_observerIsNull_returnsNull() throws Exception {
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendOnRestorePackage(
+ null, PACKAGE_NAME);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void sendOnRestorePackage_callsObserver() throws Exception {
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendOnRestorePackage(
+ mFullBackupRestoreObserverMock, PACKAGE_NAME);
+
+ assertThat(result).isEqualTo(mFullBackupRestoreObserverMock);
+ verify(mFullBackupRestoreObserverMock).onRestorePackage(PACKAGE_NAME);
+ }
+
+ @Test
+ public void sendOnRestorePackage_observerThrows_returnsNull() throws Exception {
+ doThrow(new RemoteException()).when(mFullBackupRestoreObserverMock).onRestorePackage(
+ PACKAGE_NAME);
+
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendOnRestorePackage(
+ mFullBackupRestoreObserverMock, PACKAGE_NAME);
+
+ assertThat(result).isNull();
+ verify(mFullBackupRestoreObserverMock).onRestorePackage(PACKAGE_NAME);
+ }
+
+ @Test
+ public void sendEndRestore_observerIsNull_returnsNull() throws Exception {
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendEndRestore(null);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void sendEndRestore_callsObserver() throws Exception {
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendEndRestore(
+ mFullBackupRestoreObserverMock);
+
+ assertThat(result).isEqualTo(mFullBackupRestoreObserverMock);
+ verify(mFullBackupRestoreObserverMock).onEndRestore();
+ }
+
+ @Test
+ public void sendEndRestore_observerThrows_returnsNull() throws Exception {
+ doThrow(new RemoteException()).when(mFullBackupRestoreObserverMock).onEndRestore();
+
+ IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendEndRestore(
+ mFullBackupRestoreObserverMock);
+
+ assertThat(result).isNull();
+ verify(mFullBackupRestoreObserverMock).onEndRestore();
+ }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 325d99a..5e4ba7be 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -31,13 +31,10 @@
import static org.junit.Assert.fail;
import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.UserInfo;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.support.test.InstrumentationRegistry;
@@ -49,26 +46,17 @@
import android.util.LongSparseArray;
import com.android.internal.os.AtomicFile;
-import com.android.internal.util.FastPrintWriter;
import com.android.server.LocalServices;
-import org.hamcrest.core.IsNot;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.nio.charset.StandardCharsets;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.PrintStream;
import java.security.PublicKey;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
@RunWith(AndroidJUnit4.class)
@@ -547,7 +535,6 @@
private void verifyUserState(PackageUserState userState, PackageUserState oldUserState,
boolean userStateChanged, boolean notLaunched, boolean stopped, boolean installed) {
- assertThat(userState.blockUninstall, is(false));
assertThat(userState.enabled, is(0));
assertThat(userState.hidden, is(false));
assertThat(userState.installed, is(installed));
@@ -783,31 +770,14 @@
@Before
public void createUserManagerServiceRef() throws ReflectiveOperationException {
- InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- Constructor<UserManagerService> umsc;
- try {
- // unregister the user manager from the local service
- Method removeServiceForTest = LocalServices.class.getDeclaredMethod(
- "removeServiceForTest", Class.class);
- removeServiceForTest.invoke(null, UserManagerInternal.class);
-
- // now create a new user manager [which registers again with the local service]
- umsc = UserManagerService.class.getDeclaredConstructor(
- Context.class,
- PackageManagerService.class,
- Object.class,
- File.class);
- umsc.setAccessible(true);
- UserManagerService ums = umsc.newInstance(InstrumentationRegistry.getContext(),
- null /*PackageManagerService*/, new Object() /*packagesLock*/,
- new File(InstrumentationRegistry.getContext().getFilesDir(), "user"));
- } catch (SecurityException
- | ReflectiveOperationException
- | IllegalArgumentException e) {
- fail("Could not create user manager service; " + e);
- }
+ InstrumentationRegistry.getInstrumentation().runOnMainSync((Runnable) () -> {
+ try {
+ // unregister the user manager from the local service
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ new UserManagerService(InstrumentationRegistry.getContext());
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Could not create user manager service; " + e);
}
});
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index bf05f21..50be8db 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -49,10 +49,6 @@
assertThat(testUserState.equals(oldUserState), is(false));
oldUserState = new PackageUserState();
- oldUserState.blockUninstall = true;
- assertThat(testUserState.equals(oldUserState), is(false));
-
- oldUserState = new PackageUserState();
oldUserState.ceDataInode = 4000L;
assertThat(testUserState.equals(oldUserState), is(false));
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index cd39d88..4c7bf4d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -3241,7 +3241,7 @@
assertNull(mService.getShortcutsForTest().get(USER_10).getLastKnownLauncher());
// Try stopping the user
- mService.handleCleanupUser(USER_10);
+ mService.handleStopUser(USER_10);
// Now it's unloaded.
assertEquals(1, mService.getShortcutsForTest().size());
@@ -6106,7 +6106,7 @@
assertEmpty(mManager.getPinnedShortcuts());
});
// Send add broadcast, but the user is not running, so should be ignored.
- mService.handleCleanupUser(USER_10);
+ mService.handleStopUser(USER_10);
mRunningUsers.put(USER_10, false);
mUnlockedUsers.put(USER_10, false);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 9880caa..2b40c51 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -2091,7 +2091,7 @@
assertFalse(mService.isUserUnlockedL(USER_10));
// Directly call the stop lifecycle event. Goes back to the initial state.
- mService.handleCleanupUser(USER_0);
+ mService.handleStopUser(USER_0);
assertFalse(mService.isUserUnlockedL(USER_0));
assertFalse(mService.isUserUnlockedL(USER_10));
}
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 e8dc69f..f9254ad 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -26,6 +26,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -236,6 +237,7 @@
}
@Test
+ @Ignore
public void testFocusedWindowMultipleDisplays() throws Exception {
// Create a focusable window and check that focus is calcualted correctly
final WindowState window1 =
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index a23a6b22..649de4a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -20,6 +20,7 @@
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
+import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -33,8 +34,7 @@
* runtest frameworks-services -c com.android.server.wm.TaskSnapshotCacheTest
*/
@SmallTest
-// TODO(b/35196891): Add back to presubmit once the bug is fixed.
-//@Presubmit
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 2b4d9fb..f253632 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static com.android.server.wm.TaskSnapshotController.*;
import static junit.framework.Assert.assertEquals;
@@ -76,12 +77,19 @@
public void testGetSnapshotMode() throws Exception {
final WindowState disabledWindow = createWindow(null,
FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow");
- disabledWindow.mAppToken.setDisablePreviewSnapshots(true);
+ disabledWindow.mAppToken.setDisablePreviewScreenshots(true);
assertEquals(SNAPSHOT_MODE_APP_THEME,
sWm.mTaskSnapshotController.getSnapshotMode(disabledWindow.getTask()));
+
final WindowState normalWindow = createWindow(null,
FIRST_APPLICATION_WINDOW, mDisplayContent, "normalWindow");
assertEquals(SNAPSHOT_MODE_REAL,
sWm.mTaskSnapshotController.getSnapshotMode(normalWindow.getTask()));
+
+ final WindowState secureWindow = createWindow(null,
+ FIRST_APPLICATION_WINDOW, mDisplayContent, "secureWindow");
+ secureWindow.mAttrs.flags |= FLAG_SECURE;
+ assertEquals(SNAPSHOT_MODE_APP_THEME,
+ sWm.mTaskSnapshotController.getSnapshotMode(secureWindow.getTask()));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 18d0c32..8146763 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -68,7 +68,11 @@
}
private void cleanDirectory() {
- for (File file : new File(sFilesDir, "snapshots").listFiles()) {
+ final File[] files = new File(sFilesDir, "snapshots").listFiles();
+ if (files == null) {
+ return;
+ }
+ for (File file : files) {
if (!file.isDirectory()) {
file.delete();
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 717ddf2..e2868d7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -171,11 +171,25 @@
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100), 10);
+ mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
+ mockCanvas, new Rect(0, 0, 50, 100), 10);
verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
}
@Test
+ public void testDrawStatusBarBackground_nullFrame() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
+ mockCanvas, null, 10);
+ verify(mockCanvas).drawRect(eq(0.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+ }
+
+ @Test
public void testDrawStatusBarBackground_nope() {
setupSurface(100, 100);
final Rect insets = new Rect(0, 10, 10, 0);
@@ -183,7 +197,8 @@
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100), 10);
+ mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
+ mockCanvas, new Rect(0, 0, 100, 100), 10);
verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
}
@@ -196,7 +211,7 @@
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawNavigationBarBackground(mockCanvas);
+ mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
}
@@ -209,7 +224,7 @@
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawNavigationBarBackground(mockCanvas);
+ mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
}
@@ -222,7 +237,7 @@
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawNavigationBarBackground(mockCanvas);
+ mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 3b4fd04..84a2e8b 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -424,6 +424,8 @@
private boolean mSinkPower;
private boolean mConfigured;
private boolean mUsbDataUnlocked;
+ private boolean mAudioAccessoryConnected;
+ private boolean mAudioAccessorySupported;
private String mCurrentFunctions;
private boolean mCurrentFunctionsApplied;
private UsbAccessory mCurrentAccessory;
@@ -534,30 +536,13 @@
}
public void updateHostState(UsbPort port, UsbPortStatus status) {
- boolean hostConnected = status.getCurrentDataRole() == UsbPort.DATA_ROLE_HOST;
- boolean sourcePower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE;
- boolean sinkPower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SINK;
- // Ideally we want to see if PR_SWAP and DR_SWAP is supported.
- // But, this should be suffice, since, all four combinations are only supported
- // when PR_SWAP and DR_SWAP are supported.
- boolean supportsAllCombinations = status.isRoleCombinationSupported(
- UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST)
- && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_HOST)
- && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE,
- UsbPort.DATA_ROLE_DEVICE)
- && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_HOST);
-
if (DEBUG) {
Slog.i(TAG, "updateHostState " + port + " status=" + status);
}
SomeArgs args = SomeArgs.obtain();
- args.argi1 = hostConnected ? 1 : 0;
- args.argi2 = sourcePower ? 1 : 0;
- args.argi3 = sinkPower ? 1 : 0;
- args.argi4 = supportsAllCombinations ? 1 : 0;
+ args.arg1 = port;
+ args.arg2 = status;
removeMessages(MSG_UPDATE_PORT_STATE);
Message msg = obtainMessage(MSG_UPDATE_PORT_STATE, args);
@@ -931,10 +916,26 @@
case MSG_UPDATE_PORT_STATE:
SomeArgs args = (SomeArgs) msg.obj;
boolean prevHostConnected = mHostConnected;
- mHostConnected = (args.argi1 == 1);
- mSourcePower = (args.argi2 == 1);
- mSinkPower = (args.argi3 == 1);
- mSupportsAllCombinations = (args.argi4 == 1);
+ UsbPort port = (UsbPort) args.arg1;
+ UsbPortStatus status = (UsbPortStatus) args.arg2;
+ mHostConnected = status.getCurrentDataRole() == UsbPort.DATA_ROLE_HOST;
+ mSourcePower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE;
+ mSinkPower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SINK;
+ mAudioAccessoryConnected =
+ (status.getCurrentMode() == UsbPort.MODE_AUDIO_ACCESSORY);
+ mAudioAccessorySupported = port.isModeSupported(UsbPort.MODE_AUDIO_ACCESSORY);
+ // Ideally we want to see if PR_SWAP and DR_SWAP is supported.
+ // But, this should be suffice, since, all four combinations are only supported
+ // when PR_SWAP and DR_SWAP are supported.
+ mSupportsAllCombinations = status.isRoleCombinationSupported(
+ UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST)
+ && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK,
+ UsbPort.DATA_ROLE_HOST)
+ && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE,
+ UsbPort.DATA_ROLE_DEVICE)
+ && status.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK,
+ UsbPort.DATA_ROLE_HOST);
+
args.recycle();
updateUsbNotification(false);
if (mBootCompleted) {
@@ -1076,7 +1077,10 @@
int id = 0;
int titleRes = 0;
Resources r = mContext.getResources();
- if (mConnected) {
+ if (mAudioAccessoryConnected && !mAudioAccessorySupported) {
+ titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
+ id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
+ } else if (mConnected) {
if (!mUsbDataUnlocked) {
if (mSourcePower) {
titleRes = com.android.internal.R.string.usb_supplying_notification_title;
@@ -1123,18 +1127,43 @@
mUsbNotificationId = 0;
}
if (id != 0) {
- CharSequence message = r.getText(
- com.android.internal.R.string.usb_notification_message);
+ CharSequence message;
CharSequence title = r.getText(titleRes);
+ PendingIntent pi;
+ String channel;
- Intent intent = Intent.makeRestartActivityTask(
- new ComponentName("com.android.settings",
- "com.android.settings.deviceinfo.UsbModeChooserActivity"));
- PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
- intent, 0, null, UserHandle.CURRENT);
+ if (titleRes
+ != com.android.internal.R.string
+ .usb_unsupported_audio_accessory_title) {
+ Intent intent = Intent.makeRestartActivityTask(
+ new ComponentName("com.android.settings",
+ "com.android.settings.deviceinfo.UsbModeChooserActivity"));
+ pi = PendingIntent.getActivityAsUser(mContext, 0,
+ intent, 0, null, UserHandle.CURRENT);
+ channel = SystemNotificationChannels.USB;
+ message = r.getText(
+ com.android.internal.R.string.usb_notification_message);
+ } else {
+ final Intent intent = new Intent();
+ intent.setClassName("com.android.settings",
+ "com.android.settings.HelpTrampoline");
+ intent.putExtra(Intent.EXTRA_TEXT,
+ "help_url_audio_accessory_not_supported");
+
+ if (mContext.getPackageManager().resolveActivity(intent, 0) != null) {
+ pi = PendingIntent.getActivity(mContext, 0, intent, 0);
+ } else {
+ pi = null;
+ }
+
+ channel = SystemNotificationChannels.ALERTS;
+ message = r.getText(
+ com.android.internal.R.string
+ .usb_unsupported_audio_accessory_message);
+ }
Notification notification =
- new Notification.Builder(mContext, SystemNotificationChannels.USB)
+ new Notification.Builder(mContext, channel)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setWhen(0)
.setOngoing(true)
@@ -1148,6 +1177,7 @@
.setContentIntent(pi)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.build();
+
mNotificationManager.notifyAsUser(null, id, notification,
UserHandle.ALL);
mUsbNotificationId = id;
@@ -1230,6 +1260,8 @@
pw.println(" mSinkPower: " + mSinkPower);
pw.println(" mUsbCharging: " + mUsbCharging);
pw.println(" mHideUsbNotification: " + mHideUsbNotification);
+ pw.println(" mAudioAccessoryConnected: " + mAudioAccessoryConnected);
+
try {
pw.println(" Kernel state: "
+ FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index f01e4c0..256e13b 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -106,6 +106,7 @@
public static final int EVENT_REDIRECTION_DETECTED = BASE + 44;
public static final int EVENT_PCO_DATA_RECEIVED = BASE + 45;
public static final int EVENT_SET_CARRIER_DATA_ENABLED = BASE + 46;
+ public static final int EVENT_DATA_RECONNECT = BASE + 47;
/***** Constants *****/
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 2d3d79a..9a03c53 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -17,6 +17,7 @@
package android.test.mock;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.PackageInstallObserver;
import android.content.ComponentName;
import android.content.Intent;
@@ -1159,4 +1160,13 @@
public String getInstantAppAndroidId(String packageName, UserHandle user) {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public void registerDexModule(String dexModulePath,
+ @Nullable DexModuleRegisterCallback callback) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 93677e3..5dd42dd 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -385,6 +385,23 @@
mNM.notify("timeout_min", 7013, n);
}
},
+ new Test("Too many cancels") {
+ public void run()
+ {
+ mNM.cancelAll();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ Notification n = new Notification.Builder(NotificationTestList.this, "default")
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Cancel then post")
+ .setContentText("instead of just updating the existing notification")
+ .build();
+ mNM.notify("cancel_madness", 7014, n);
+ }
+ },
new Test("Off") {
public void run() {
PowerManager pm = (PowerManager) NotificationTestList.this.getSystemService(
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 504d54e..3af0adc 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -52,7 +52,6 @@
libtinyxml2 \
libvintf \
libhwbinder \
- android.hidl.base@1.0 \
android.hidl.token@1.0
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/tests/net/java/android/net/nsd/NsdManagerTest.java
index b8ed766..063cd5dc 100644
--- a/tests/net/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/net/java/android/net/nsd/NsdManagerTest.java
@@ -19,14 +19,15 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.os.HandlerThread;
import android.os.Handler;
@@ -49,6 +50,8 @@
@SmallTest
public class NsdManagerTest {
+ static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD;
+
@Mock Context mContext;
@Mock INsdManager mService;
MockServiceHandler mServiceHandler;
@@ -107,6 +110,143 @@
}
@Test
+ public void testRegisterService() {
+ NsdManager manager = makeManager();
+
+ NsdServiceInfo request1 = new NsdServiceInfo("a_name", "a_type");
+ NsdServiceInfo request2 = new NsdServiceInfo("another_name", "another_type");
+ request1.setPort(2201);
+ request2.setPort(2202);
+ NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class);
+ NsdManager.RegistrationListener listener2 = mock(NsdManager.RegistrationListener.class);
+
+ // Register two services
+ manager.registerService(request1, PROTOCOL, listener1);
+ int key1 = verifyRequest(NsdManager.REGISTER_SERVICE);
+
+ manager.registerService(request2, PROTOCOL, listener2);
+ int key2 = verifyRequest(NsdManager.REGISTER_SERVICE);
+
+ // First reques fails, second request succeeds
+ sendResponse(NsdManager.REGISTER_SERVICE_SUCCEEDED, 0, key2, request2);
+ verify(listener2, timeout(mTimeoutMs).times(1)).onServiceRegistered(request2);
+
+ int err = 1;
+ sendResponse(NsdManager.REGISTER_SERVICE_FAILED, err, key1, request1);
+ verify(listener1, timeout(mTimeoutMs).times(1)).onRegistrationFailed(request1, err);
+
+ // Client retries first request, it succeeds
+ manager.registerService(request1, PROTOCOL, listener1);
+ int key3 = verifyRequest(NsdManager.REGISTER_SERVICE);
+
+ sendResponse(NsdManager.REGISTER_SERVICE_SUCCEEDED, 0, key3, request1);
+ verify(listener1, timeout(mTimeoutMs).times(1)).onServiceRegistered(request1);
+
+ // First request is unregistered, it succeeds
+ manager.unregisterService(listener1);
+ int key3again = verifyRequest(NsdManager.UNREGISTER_SERVICE);
+ assertEquals(key3, key3again);
+
+ sendResponse(NsdManager.UNREGISTER_SERVICE_SUCCEEDED, 0, key3again, null);
+ verify(listener1, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request1);
+
+ // Second request is unregistered, it fails
+ manager.unregisterService(listener2);
+ int key2again = verifyRequest(NsdManager.UNREGISTER_SERVICE);
+ assertEquals(key2, key2again);
+
+ sendResponse(NsdManager.UNREGISTER_SERVICE_FAILED, err, key2again, null);
+ verify(listener2, timeout(mTimeoutMs).times(1)).onUnregistrationFailed(request2, err);
+
+ // TODO: do not unregister listener until service is unregistered
+ // Client retries unregistration of second request, it succeeds
+ //manager.unregisterService(listener2);
+ //int key2yetAgain = verifyRequest(NsdManager.UNREGISTER_SERVICE);
+ //assertEquals(key2, key2yetAgain);
+
+ //sendResponse(NsdManager.UNREGISTER_SERVICE_SUCCEEDED, 0, key2yetAgain, null);
+ //verify(listener2, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request2);
+ }
+
+ @Test
+ public void testDiscoverService() {
+ NsdManager manager = makeManager();
+
+ NsdServiceInfo reply1 = new NsdServiceInfo("a_name", "a_type");
+ NsdServiceInfo reply2 = new NsdServiceInfo("another_name", "a_type");
+ NsdServiceInfo reply3 = new NsdServiceInfo("a_third_name", "a_type");
+
+ NsdManager.DiscoveryListener listener = mock(NsdManager.DiscoveryListener.class);
+
+ // Client registers for discovery, request fails
+ manager.discoverServices("a_type", PROTOCOL, listener);
+ int key1 = verifyRequest(NsdManager.DISCOVER_SERVICES);
+
+ int err = 1;
+ sendResponse(NsdManager.DISCOVER_SERVICES_FAILED, err, key1, null);
+ verify(listener, timeout(mTimeoutMs).times(1)).onStartDiscoveryFailed("a_type", err);
+
+ // Client retries, request succeeds
+ manager.discoverServices("a_type", PROTOCOL, listener);
+ int key2 = verifyRequest(NsdManager.DISCOVER_SERVICES);
+
+ sendResponse(NsdManager.DISCOVER_SERVICES_STARTED, 0, key2, reply1);
+ verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStarted("a_type");
+
+
+ // mdns notifies about services
+ sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply1);
+ verify(listener, timeout(mTimeoutMs).times(1)).onServiceFound(reply1);
+
+ sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply2);
+ verify(listener, timeout(mTimeoutMs).times(1)).onServiceFound(reply2);
+
+ sendResponse(NsdManager.SERVICE_LOST, 0, key2, reply2);
+ verify(listener, timeout(mTimeoutMs).times(1)).onServiceLost(reply2);
+
+
+ // Client unregisters its listener
+ manager.stopServiceDiscovery(listener);
+ int key2again = verifyRequest(NsdManager.STOP_DISCOVERY);
+ assertEquals(key2, key2again);
+
+ // TODO: unregister listener immediately and stop notifying it about services
+ // Notifications are still passed to the client's listener
+ sendResponse(NsdManager.SERVICE_LOST, 0, key2, reply1);
+ verify(listener, timeout(mTimeoutMs).times(1)).onServiceLost(reply1);
+
+ // Client is notified of complete unregistration
+ sendResponse(NsdManager.STOP_DISCOVERY_SUCCEEDED, 0, key2again, "a_type");
+ verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStopped("a_type");
+
+ // Notifications are not passed to the client anymore
+ sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply3);
+ verify(listener, timeout(mTimeoutMs).times(0)).onServiceLost(reply3);
+
+
+ // Client registers for service discovery
+ reset(listener);
+ manager.discoverServices("a_type", PROTOCOL, listener);
+ int key3 = verifyRequest(NsdManager.DISCOVER_SERVICES);
+
+ sendResponse(NsdManager.DISCOVER_SERVICES_STARTED, 0, key3, reply1);
+ verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStarted("a_type");
+
+ // Client unregisters immediately, it fails
+ manager.stopServiceDiscovery(listener);
+ int key3again = verifyRequest(NsdManager.STOP_DISCOVERY);
+ assertEquals(key3, key3again);
+
+ err = 2;
+ sendResponse(NsdManager.STOP_DISCOVERY_FAILED, err, key3again, "a_type");
+ verify(listener, timeout(mTimeoutMs).times(1)).onStopDiscoveryFailed("a_type", err);
+
+ // New notifications are not passed to the client anymore
+ sendResponse(NsdManager.SERVICE_FOUND, 0, key3, reply1);
+ verify(listener, timeout(mTimeoutMs).times(0)).onServiceFound(reply1);
+ }
+
+ @Test
public void testInvalidCalls() {
NsdManager manager = new NsdManager(mContext, mService);
@@ -118,38 +258,36 @@
NsdServiceInfo validService = new NsdServiceInfo("a_name", "a_type");
validService.setPort(2222);
- int protocol = NsdManager.PROTOCOL_DNS_SD;
-
// Service registration
// - invalid arguments
mustFail(() -> { manager.unregisterService(null); });
mustFail(() -> { manager.registerService(null, -1, null); });
- mustFail(() -> { manager.registerService(null, protocol, listener1); });
- mustFail(() -> { manager.registerService(invalidService, protocol, listener1); });
+ mustFail(() -> { manager.registerService(null, PROTOCOL, listener1); });
+ mustFail(() -> { manager.registerService(invalidService, PROTOCOL, listener1); });
mustFail(() -> { manager.registerService(validService, -1, listener1); });
- mustFail(() -> { manager.registerService(validService, protocol, null); });
- manager.registerService(validService, protocol, listener1);
+ mustFail(() -> { manager.registerService(validService, PROTOCOL, null); });
+ manager.registerService(validService, PROTOCOL, listener1);
// - listener already registered
- mustFail(() -> { manager.registerService(validService, protocol, listener1); });
+ mustFail(() -> { manager.registerService(validService, PROTOCOL, listener1); });
manager.unregisterService(listener1);
// TODO: make listener immediately reusable
//mustFail(() -> { manager.unregisterService(listener1); });
- //manager.registerService(validService, protocol, listener1);
+ //manager.registerService(validService, PROTOCOL, listener1);
// Discover service
// - invalid arguments
mustFail(() -> { manager.stopServiceDiscovery(null); });
mustFail(() -> { manager.discoverServices(null, -1, null); });
- mustFail(() -> { manager.discoverServices(null, protocol, listener2); });
+ mustFail(() -> { manager.discoverServices(null, PROTOCOL, listener2); });
mustFail(() -> { manager.discoverServices("a_service", -1, listener2); });
- mustFail(() -> { manager.discoverServices("a_service", protocol, null); });
- manager.discoverServices("a_service", protocol, listener2);
+ mustFail(() -> { manager.discoverServices("a_service", PROTOCOL, null); });
+ manager.discoverServices("a_service", PROTOCOL, listener2);
// - listener already registered
- mustFail(() -> { manager.discoverServices("another_service", protocol, listener2); });
+ mustFail(() -> { manager.discoverServices("another_service", PROTOCOL, listener2); });
manager.stopServiceDiscovery(listener2);
// TODO: make listener immediately reusable
//mustFail(() -> { manager.stopServiceDiscovery(listener2); });
- //manager.discoverServices("another_service", protocol, listener2);
+ //manager.discoverServices("another_service", PROTOCOL, listener2);
// Resolver service
// - invalid arguments
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 633a914..46dcdad 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -39,6 +39,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
+import android.net.CaptivePortal;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.PacketKeepalive;
@@ -77,6 +78,7 @@
import android.os.Parcelable;
import android.os.Process;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.test.mock.MockContentResolver;
@@ -121,7 +123,7 @@
private static final int TIMEOUT_MS = 500;
private static final int TEST_LINGER_DELAY_MS = 120;
- private BroadcastInterceptingContext mServiceContext;
+ private MockContext mServiceContext;
private WrappedConnectivityService mService;
private WrappedConnectivityManager mCm;
private MockNetworkAgent mWiFiNetworkAgent;
@@ -152,6 +154,7 @@
private final MockContentResolver mContentResolver;
@Spy private Resources mResources;
+ private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
MockContext(Context base) {
super(base);
@@ -169,6 +172,27 @@
}
@Override
+ public void startActivityAsUser(Intent intent, UserHandle handle) {
+ mStartedActivities.offer(intent);
+ }
+
+ public Intent expectStartActivityIntent(int timeoutMs) {
+ Intent intent = null;
+ try {
+ intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {}
+ assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
+ return intent;
+ }
+
+ public void expectNoStartActivityIntent(int timeoutMs) {
+ try {
+ assertNull("Received unexpected Intent to start activity",
+ mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {}
+ }
+
+ @Override
public Object getSystemService(String name) {
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
@@ -1830,6 +1854,52 @@
}
@SmallTest
+ public void testCaptivePortalApp() {
+ final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
+ final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
+ mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
+
+ final TestNetworkCallback validatedCallback = new TestNetworkCallback();
+ final NetworkRequest validatedRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_VALIDATED).build();
+ mCm.registerNetworkCallback(validatedRequest, validatedCallback);
+
+ // Bring up wifi.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+ validatedCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+ Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
+
+ // Check that calling startCaptivePortalApp does nothing.
+ final int fastTimeoutMs = 100;
+ mCm.startCaptivePortalApp(wifiNetwork);
+ mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
+
+ // Turn into a captive portal.
+ mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
+ mCm.reportNetworkConnectivity(wifiNetwork, false);
+ captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+ // Check that startCaptivePortalApp sends the expected intent.
+ mCm.startCaptivePortalApp(wifiNetwork);
+ Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
+ assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
+ assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK));
+
+ // Have the app report that the captive portal is dismissed, and check that we revalidate.
+ mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
+ CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
+ c.reportCaptivePortalDismissed();
+ validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+ mCm.unregisterNetworkCallback(validatedCallback);
+ mCm.unregisterNetworkCallback(captivePortalCallback);
+ }
+
+ @SmallTest
public void testAvoidOrIgnoreCaptivePortals() {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
diff --git a/tests/radio/src/android/hardware/radio/tests/RadioTest.java b/tests/radio/src/android/hardware/radio/tests/RadioTest.java
index e9c9b8c..7ab5618 100644
--- a/tests/radio/src/android/hardware/radio/tests/RadioTest.java
+++ b/tests/radio/src/android/hardware/radio/tests/RadioTest.java
@@ -22,6 +22,7 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
+import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
@@ -30,6 +31,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import static org.junit.Assert.*;
@@ -37,6 +39,7 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -48,6 +51,8 @@
public final Context mContext = InstrumentationRegistry.getContext();
+ private final int kConfigCallbacktimeoutNs = 10000;
+
private RadioManager mRadioManager;
private RadioTuner mRadioTuner;
private final List<RadioManager.ModuleProperties> mModules = new ArrayList<>();
@@ -56,6 +61,9 @@
RadioManager.AmBandDescriptor mAmBandDescriptor;
RadioManager.FmBandDescriptor mFmBandDescriptor;
+ RadioManager.BandConfig mAmBandConfig;
+ RadioManager.BandConfig mFmBandConfig;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -98,11 +106,14 @@
}
assertNotNull(mAmBandDescriptor);
assertNotNull(mFmBandDescriptor);
- RadioManager.BandConfig fmBandConfig =
- new RadioManager.FmBandConfig.Builder(mFmBandDescriptor).build();
+ mAmBandConfig = new RadioManager.AmBandConfig.Builder(mAmBandDescriptor).build();
+ mFmBandConfig = new RadioManager.FmBandConfig.Builder(mFmBandDescriptor).build();
- mRadioTuner = mRadioManager.openTuner(module.getId(), fmBandConfig, true, mCallback, null);
+ mRadioTuner = mRadioManager.openTuner(module.getId(), mFmBandConfig, true, mCallback, null);
assertNotNull(mRadioTuner);
+ verify(mCallback, timeout(kConfigCallbacktimeoutNs).times(1)).onConfigurationChanged(any());
+ verify(mCallback, never()).onError(anyInt());
+ Mockito.reset(mCallback);
}
@Test
@@ -112,26 +123,59 @@
}
@Test
- public void testReopenTuner() {
+ public void testReopenTuner() throws Throwable {
openTuner();
mRadioTuner.close();
mRadioTuner = null;
+ Thread.sleep(100); // TODO(b/36122635): force reopen
openTuner();
verify(mCallback, never()).onError(anyInt());
}
@Test
- @org.junit.Ignore("setConfiguration is not implemented yet")
public void testSetAndGetConfiguration() {
openTuner();
- RadioManager.BandConfig amBandConfig =
- new RadioManager.AmBandConfig.Builder(mAmBandDescriptor).build();
- mRadioTuner.setConfiguration(amBandConfig);
+ // set
+ int ret = mRadioTuner.setConfiguration(mAmBandConfig);
+ assertEquals(RadioManager.STATUS_OK, ret);
+ verify(mCallback, timeout(kConfigCallbacktimeoutNs).times(1)).onConfigurationChanged(any());
- verify(mCallback, times(1)).onConfigurationChanged(any());
+ // get
+ RadioManager.BandConfig[] config = new RadioManager.BandConfig[1];
+ ret = mRadioTuner.getConfiguration(config);
+ assertEquals(RadioManager.STATUS_OK, ret);
+
verify(mCallback, never()).onError(anyInt());
+ assertEquals(mAmBandConfig, config[0]);
+ }
- // TODO(b/36863239): implement "get" too
+ @Test
+ public void testSetBadConfiguration() throws Throwable {
+ openTuner();
+
+ // set bad config
+ Constructor<RadioManager.AmBandConfig> configConstr =
+ RadioManager.AmBandConfig.class.getDeclaredConstructor(
+ int.class, int.class, int.class, int.class, int.class, boolean.class);
+ configConstr.setAccessible(true);
+ RadioManager.AmBandConfig badConfig = configConstr.newInstance(
+ 0 /*region*/, RadioManager.BAND_AM /*type*/,
+ 10000 /*lowerLimit*/, 1 /*upperLimit*/, 100 /*spacing*/, false /*stereo*/);
+ int ret = mRadioTuner.setConfiguration(badConfig);
+ assertEquals(RadioManager.STATUS_BAD_VALUE, ret);
+ verify(mCallback, never()).onConfigurationChanged(any());
+
+ // set null config
+ ret = mRadioTuner.setConfiguration(null);
+ assertEquals(RadioManager.STATUS_BAD_VALUE, ret);
+ verify(mCallback, never()).onConfigurationChanged(any());
+
+ // setting good config should recover
+ ret = mRadioTuner.setConfiguration(mAmBandConfig);
+ assertEquals(RadioManager.STATUS_OK, ret);
+ verify(mCallback, timeout(kConfigCallbacktimeoutNs).times(1)).onConfigurationChanged(any());
+
+ verify(mCallback, never()).onError(anyInt());
}
}
diff --git a/tests/testables/src/android/testing/TestableContext.java b/tests/testables/src/android/testing/TestableContext.java
index 630a287..d6c06e4 100644
--- a/tests/testables/src/android/testing/TestableContext.java
+++ b/tests/testables/src/android/testing/TestableContext.java
@@ -69,6 +69,7 @@
private LeakCheck.Tracker mReceiver;
private LeakCheck.Tracker mService;
private LeakCheck.Tracker mComponent;
+ private TestableResources mTestableResources;
public TestableContext(Context base) {
this(base, null);
@@ -98,9 +99,37 @@
return super.getPackageManager();
}
+ /**
+ * Makes sure the resources being returned by this TestableContext are a version of
+ * TestableResources.
+ * @see #getResources()
+ */
+ public void ensureTestableResources() {
+ if (mTestableResources == null) {
+ mTestableResources = new TestableResources(super.getResources());
+ }
+ }
+
+ /**
+ * Get (and create if necessary) {@link TestableResources} for this TestableContext.
+ */
+ public TestableResources getOrCreateTestableResources() {
+ ensureTestableResources();
+ return mTestableResources;
+ }
+
+ /**
+ * Returns a Resources instance for the test.
+ *
+ * By default this returns the same resources object that would come from the
+ * {@link ContextWrapper}, but if {@link #ensureTestableResources()} or
+ * {@link #getOrCreateTestableResources()} has been called, it will return resources gotten from
+ * {@link TestableResources}.
+ */
@Override
public Resources getResources() {
- return super.getResources();
+ return mTestableResources != null ? mTestableResources.getResources()
+ : super.getResources();
}
public <T> void addMockSystemService(Class<T> service, T mock) {
diff --git a/tests/testables/src/android/testing/TestableResources.java b/tests/testables/src/android/testing/TestableResources.java
new file mode 100644
index 0000000..a2fa95d
--- /dev/null
+++ b/tests/testables/src/android/testing/TestableResources.java
@@ -0,0 +1,101 @@
+/*
+ * 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.testing;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+import android.util.SparseArray;
+
+import org.mockito.invocation.InvocationOnMock;
+
+/**
+ * Provides a version of Resources that defaults to all existing resources, but can have ids
+ * changed to return specific values.
+ * <p>
+ * TestableResources are lazily initialized, be sure to call
+ * {@link TestableContext#ensureTestableResources} before your tested code has an opportunity
+ * to cache {@link Context#getResources}.
+ * </p>
+ */
+public class TestableResources {
+
+ private static final String TAG = "TestableResources";
+ private final Resources mResources;
+ private final SparseArray<Object> mOverrides = new SparseArray<>();
+
+ TestableResources(Resources realResources) {
+ mResources = mock(Resources.class, withSettings()
+ .spiedInstance(realResources)
+ .defaultAnswer(this::answer));
+ }
+
+ /**
+ * Gets the implementation of Resources that will return overridden values when called.
+ */
+ public Resources getResources() {
+ return mResources;
+ }
+
+ /**
+ * Sets the return value for the specified resource id.
+ * <p>
+ * Since resource ids are unique there is a single addOverride that will override the value
+ * whenever it is gotten regardless of which method is used (i.e. getColor or getDrawable).
+ * </p>
+ * @param id The resource id to be overridden
+ * @param value The value of the resource, null to cause a {@link Resources.NotFoundException}
+ * when gotten.
+ */
+ public void addOverride(int id, Object value) {
+ mOverrides.put(id, value);
+ }
+
+ /**
+ * Removes the override for the specified id.
+ * <p>
+ * This should be called over addOverride(id, null), because specifying a null value will
+ * cause a {@link Resources.NotFoundException} whereas removing the override will actually
+ * switch back to returning the default/real value of the resource.
+ * </p>
+ * @param id
+ */
+ public void removeOverride(int id) {
+ mOverrides.remove(id);
+ }
+
+ private Object answer(InvocationOnMock invocationOnMock) throws Throwable {
+ try {
+ int id = invocationOnMock.getArgument(0);
+ int index = mOverrides.indexOfKey(id);
+ if (index >= 0) {
+ Object value = mOverrides.valueAt(index);
+ if (value == null) throw new Resources.NotFoundException();
+ return value;
+ }
+ } catch (Resources.NotFoundException e) {
+ // Let through NotFoundException.
+ throw e;
+ } catch (Throwable t) {
+ // Generic catching for the many things that can go wrong, fall back to
+ // the real implementation.
+ Log.i(TAG, "Falling back to default resources call " + t);
+ }
+ return invocationOnMock.callRealMethod();
+ }
+}
diff --git a/core/java/android/app/CompatibilityDisplayProperties.aidl b/tests/testables/tests/res/values/strings.xml
similarity index 62%
copy from core/java/android/app/CompatibilityDisplayProperties.aidl
copy to tests/testables/tests/res/values/strings.xml
index 626a63e..1ad0ade 100644
--- a/core/java/android/app/CompatibilityDisplayProperties.aidl
+++ b/tests/testables/tests/res/values/strings.xml
@@ -1,11 +1,13 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -13,8 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package android.app;
-
-/** @hide */
-parcelable CompatibilityDisplayProperties;
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="test_string">This is a test string</string>
+</resources>
diff --git a/tests/testables/tests/src/android/testing/TestableResourcesTest.java b/tests/testables/tests/src/android/testing/TestableResourcesTest.java
new file mode 100644
index 0000000..9a1c0a9
--- /dev/null
+++ b/tests/testables/tests/src/android/testing/TestableResourcesTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.testing;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import android.content.res.Resources;
+import android.support.test.InstrumentationRegistry;
+
+import com.android.testables.R;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+public class TestableResourcesTest {
+
+ @Rule
+ public TestableContext mContext = new TestableContext(InstrumentationRegistry.getContext());
+
+ @Test
+ public void testLazyInit() {
+ Resources before = mContext.getResources();
+ mContext.ensureTestableResources();
+ Resources after = mContext.getResources();
+ assertNotEquals(before, after);
+ }
+
+ @Test
+ public void testAddingResource() {
+ final int nonExistentId = 3; // Ids don't go this low.
+
+ try {
+ mContext.getColor(nonExistentId);
+ fail("Should throw NotFoundException");
+ } catch (Resources.NotFoundException e) {
+ }
+ mContext.getOrCreateTestableResources().addOverride(nonExistentId, 0xffffff);
+
+ assertEquals(0xffffff, mContext.getColor(nonExistentId));
+ }
+
+ @Test
+ public void testClearingResource() {
+ final int nonExistentId = 3; // Ids don't go this low.
+
+ mContext.getOrCreateTestableResources().addOverride(nonExistentId, 0xffffff);
+ assertEquals(0xffffff, mContext.getColor(nonExistentId));
+ mContext.getOrCreateTestableResources().removeOverride(nonExistentId);
+ try {
+ mContext.getColor(nonExistentId);
+ fail("Should throw NotFoundException");
+ } catch (Resources.NotFoundException e) {
+ }
+ }
+
+ @Test
+ public void testOverrideExisting() {
+ int existentId = R.string.test_string;
+
+ assertNotNull(mContext.getString(existentId));
+ mContext.getOrCreateTestableResources().addOverride(existentId, "Other strings");
+
+ assertEquals("Other strings", mContext.getString(existentId));
+ }
+
+ @Test(expected = Resources.NotFoundException.class)
+ public void testNonExistentException() {
+ int existentId = R.string.test_string;
+
+ assertNotNull(mContext.getString(existentId));
+ mContext.getOrCreateTestableResources().addOverride(existentId, null);
+
+ assertNull(mContext.getString(existentId));
+ }
+}
\ No newline at end of file
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 90f713b..6dfabf1 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -934,7 +934,7 @@
}
struct SymbolComparator {
- bool operator()(const Attribute::Symbol& a, const Attribute::Symbol& b) {
+ bool operator()(const Attribute::Symbol& a, const Attribute::Symbol& b) const {
return a.symbol.name.value() < b.symbol.name.value();
}
};
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 34360e7..b5996af 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -699,6 +699,14 @@
return ResourceHelper.getDrawable(value, mContext, mTheme);
}
+ /**
+ * Version of {@link #getDrawable(int)} that accepts an override density.
+ * @hide
+ */
+ @Override
+ public Drawable getDrawableForDensity(int index, int density) {
+ return getDrawable(index);
+ }
/**
* Retrieve the Typeface for the attribute at <var>index</var>.
diff --git a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
index 672ff6d..11cb046 100644
--- a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
+++ b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
@@ -18,8 +18,10 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ServiceInfo;
+import android.os.Handler;
import android.view.IWindow;
import android.view.View;
@@ -206,6 +208,18 @@
return true;
}
+ /**
+ * Registers an {@link AccessibilityStateChangeListener} for changes in
+ * the global accessibility state of the system. If the listener has already been registered,
+ * the handler used to call it back is updated.
+ *
+ * @param listener The listener.
+ * @param handler The handler on which the listener should be called back, or {@code null}
+ * for a callback on the process's main handler.
+ */
+ public void addAccessibilityStateChangeListener(
+ @NonNull AccessibilityStateChangeListener listener, @Nullable Handler handler) {}
+
public boolean removeAccessibilityStateChangeListener(
AccessibilityStateChangeListener listener) {
return true;
@@ -224,6 +238,18 @@
}
/**
+ * Registers an {@link TouchExplorationStateChangeListener} for changes in
+ * the global touch exploration state of the system. If the listener has already been
+ * registered, the handler used to call it back is updated.
+ *
+ * @param listener The listener.
+ * @param handler The handler on which the listener should be called back, or {@code null}
+ * for a callback on the process's main handler.
+ */
+ public void addTouchExplorationStateChangeListener(
+ @NonNull TouchExplorationStateChangeListener listener, @Nullable Handler handler) {}
+
+ /**
* Unregisters a {@link TouchExplorationStateChangeListener}.
*
* @param listener The listener.
@@ -239,25 +265,21 @@
* the global high text contrast state of the system.
*
* @param listener The listener.
- * @return True if successfully registered.
*
+ * @hide
*/
- public boolean addHighTextContrastStateChangeListener(
- @NonNull HighTextContrastChangeListener listener) {
- return true;
- }
+ public void addHighTextContrastStateChangeListener(
+ @NonNull HighTextContrastChangeListener listener, @Nullable Handler handler) {}
/**
* Unregisters a {@link HighTextContrastChangeListener}.
*
* @param listener The listener.
- * @return True if successfully unregistered.
*
+ * @hide
*/
- public boolean removeHighTextContrastStateChangeListener(
- @NonNull HighTextContrastChangeListener listener) {
- return true;
- }
+ public void removeHighTextContrastStateChangeListener(
+ @NonNull HighTextContrastChangeListener listener) {}
/**
* Sets the current state and notifies listeners, if necessary.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 764eeeb..47dad34 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -949,4 +949,10 @@
public String getInstantAppAndroidId(String packageName, UserHandle user) {
return null;
}
+
+ @Override
+ public void registerDexModule(String dexModulePath,
+ @Nullable DexModuleRegisterCallback callback) {
+ callback.onDexModuleRegistered(dexModulePath, false, null);
+ }
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index faae90b..d942d05 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -131,7 +131,7 @@
boolean stopSoftAp();
- WifiConfiguration startLocalOnlyHotspot(in Messenger messenger, in IBinder binder);
+ int startLocalOnlyHotspot(in Messenger messenger, in IBinder binder);
void stopLocalOnlyHotspot();
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index ff632a5..b133a44 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -660,10 +660,10 @@
@Deprecated
public int tx_rate;
- /** average transmit rate. Unit (100kbps). */
+ /** average transmit rate. Unit (kbps). */
public int txRate;
- /** average receiving rate Unit (100kbps). */
+ /** average receiving rate Unit (kbps). */
public int rxRate;
/**
@@ -673,7 +673,7 @@
@Deprecated
public long rtt_ns;
- /** average round trip time in 0.1 nano second. */
+ /** average round trip time in picoseconds. */
public long rtt;
/**
@@ -683,7 +683,7 @@
@Deprecated
public long rtt_sd_ns;
- /** standard deviation of RTT in 0.1 ns. */
+ /** standard deviation of RTT in picoseconds. */
public long rttStandardDeviation;
/**
@@ -693,7 +693,7 @@
@Deprecated
public long rtt_spread_ns;
- /** spread (i.e. max - min) RTT in 0.1 ns. */
+ /** spread (i.e. max - min) RTT in picoseconds. */
public long rttSpread;
/**
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e31a74b..f7333e2 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -839,6 +839,10 @@
*/
public static final int NETWORK_SELECTION_ENABLE = 0;
/**
+ * The starting index for network selection disabled reasons
+ */
+ public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
+ /**
* @deprecated it is not used any more.
* This network is disabled because higher layer (>2) network is bad
*/
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 8fbf472..e59b74f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -478,7 +478,6 @@
*/
public static final int IFACE_IP_MODE_LOCAL_ONLY = 2;
-
/**
* Broadcast intent action indicating that a connection to the supplicant has
* been established (and it is now possible
@@ -1850,8 +1849,9 @@
* Tethering to provide an upstream to another device, LocalOnlyHotspot will not start due to
* an incompatible mode. The possible error codes include:
* {@link LocalOnlyHotspotCallback#ERROR_NO_CHANNEL},
- * {@link LocalOnlyHotspotCallback#ERROR_GENERIC} and
- * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE}.
+ * {@link LocalOnlyHotspotCallback#ERROR_GENERIC},
+ * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE} and
+ * {@link LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED}.
* <p>
* Internally, requests will be tracked to prevent the hotspot from being torn down while apps
* are still using it. The {@link LocalOnlyHotspotReservation} object passed in the {@link
@@ -1882,8 +1882,6 @@
* operating status.
* @param handler Handler to be used for callbacks. If the caller passes a null Handler, the
* main thread will be used.
- *
- * @hide
*/
public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback,
@Nullable Handler handler) {
@@ -1892,12 +1890,10 @@
LocalOnlyHotspotCallbackProxy proxy =
new LocalOnlyHotspotCallbackProxy(this, looper, callback);
try {
- WifiConfiguration config = mService.startLocalOnlyHotspot(
- proxy.getMessenger(), new Binder());
- if (config == null) {
+ int returnCode = mService.startLocalOnlyHotspot(proxy.getMessenger(), new Binder());
+ if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
// Send message to the proxy to make sure we call back on the correct thread
- proxy.notifyFailed(
- LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE);
+ proxy.notifyFailed(returnCode);
return;
}
mLOHSCallbackProxy = proxy;
@@ -2274,8 +2270,6 @@
* any further callbacks. If the LocalOnlyHotspot is stopped due to a
* user triggered mode change, applications will be notified via the {@link
* LocalOnlyHotspotCallback#onStopped()} callback.
- *
- * @hide
*/
public class LocalOnlyHotspotReservation implements AutoCloseable {
@@ -2289,7 +2283,7 @@
mCloseGuard.open("close");
}
- public WifiConfiguration getConfig() {
+ public WifiConfiguration getWifiConfiguration() {
return mConfig;
}
@@ -2318,13 +2312,15 @@
/**
* Callback class for applications to receive updates about the LocalOnlyHotspot status.
- *
- * @hide
*/
public static class LocalOnlyHotspotCallback {
+ /** @hide */
+ public static final int REQUEST_REGISTERED = 0;
+
public static final int ERROR_NO_CHANNEL = 1;
public static final int ERROR_GENERIC = 2;
public static final int ERROR_INCOMPATIBLE_MODE = 3;
+ public static final int ERROR_TETHERING_DISALLOWED = 4;
/** LocalOnlyHotspot start succeeded. */
public void onStarted(LocalOnlyHotspotReservation reservation) {};
@@ -2345,7 +2341,8 @@
* {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} again at
* a later time.
* <p>
- * @param reason The reason for failure could be one of: {@link #ERROR_INCOMPATIBLE_MODE},
+ * @param reason The reason for failure could be one of: {@link
+ * #ERROR_TETHERING_DISALLOWED}, {@link #ERROR_INCOMPATIBLE_MODE},
* {@link #ERROR_NO_CHANNEL}, or {@link #ERROR_GENERIC}.
*/
public void onFailed(int reason) { };
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 333a4f7d..f892bb0 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -80,9 +80,15 @@
* Configurations under Policy subtree.
*/
private Policy mPolicy = null;
+ /**
+ * @hide
+ */
public void setPolicy(Policy policy) {
mPolicy = policy;
}
+ /**
+ * @hide
+ */
public Policy getPolicy() {
return mPolicy;
}
@@ -91,9 +97,15 @@
* Meta data for performing subscription update.
*/
private UpdateParameter mSubscriptionUpdate = null;
+ /**
+ * @hide
+ */
public void setSubscriptionUpdate(UpdateParameter subscriptionUpdate) {
mSubscriptionUpdate = subscriptionUpdate;
}
+ /**
+ * @hide
+ */
public UpdateParameter getSubscriptionUpdate() {
return mSubscriptionUpdate;
}
@@ -104,9 +116,15 @@
* identity during EAP authentication.
*/
private Map<String, byte[]> mTrustRootCertList = null;
+ /**
+ * @hide
+ */
public void setTrustRootCertList(Map<String, byte[]> trustRootCertList) {
mTrustRootCertList = trustRootCertList;
}
+ /**
+ * @hide
+ */
public Map<String, byte[]> getTrustRootCertList() {
return mTrustRootCertList;
}
@@ -118,9 +136,15 @@
* Use Integer.MIN_VALUE to indicate unset value.
*/
private int mUpdateIdentifier = Integer.MIN_VALUE;
+ /**
+ * @hide
+ */
public void setUpdateIdentifier(int updateIdentifier) {
mUpdateIdentifier = updateIdentifier;
}
+ /**
+ * @hide
+ */
public int getUpdateIdentifier() {
return mUpdateIdentifier;
}
@@ -131,9 +155,15 @@
* Use Integer.MIN_VALUE to indicate unset value.
*/
private int mCredentialPriority = Integer.MIN_VALUE;
+ /**
+ * @hide
+ */
public void setCredentialPriority(int credentialPriority) {
mCredentialPriority = credentialPriority;
}
+ /**
+ * @hide
+ */
public int getCredentialPriority() {
return mCredentialPriority;
}
@@ -144,12 +174,18 @@
*
* Use Long.MIN_VALUE to indicate unset value.
*/
- private long mSubscriptionCreationTimeInMs = Long.MIN_VALUE;
- public void setSubscriptionCreationTimeInMs(long subscriptionCreationTimeInMs) {
- mSubscriptionCreationTimeInMs = subscriptionCreationTimeInMs;
+ private long mSubscriptionCreationTimeInMillis = Long.MIN_VALUE;
+ /**
+ * @hide
+ */
+ public void setSubscriptionCreationTimeInMillis(long subscriptionCreationTimeInMillis) {
+ mSubscriptionCreationTimeInMillis = subscriptionCreationTimeInMillis;
}
- public long getSubscriptionCreationTimeInMs() {
- return mSubscriptionCreationTimeInMs;
+ /**
+ * @hide
+ */
+ public long getSubscriptionCreationTimeInMillis() {
+ return mSubscriptionCreationTimeInMillis;
}
/**
@@ -158,12 +194,18 @@
*
* Use Long.MIN_VALUE to indicate unset value.
*/
- private long mSubscriptionExpirationTimeInMs = Long.MIN_VALUE;
- public void setSubscriptionExpirationTimeInMs(long subscriptionExpirationTimeInMs) {
- mSubscriptionExpirationTimeInMs = subscriptionExpirationTimeInMs;
+ private long mSubscriptionExpirationTimeInMillis = Long.MIN_VALUE;
+ /**
+ * @hide
+ */
+ public void setSubscriptionExpirationTimeInMillis(long subscriptionExpirationTimeInMillis) {
+ mSubscriptionExpirationTimeInMillis = subscriptionExpirationTimeInMillis;
}
- public long getSubscriptionExpirationTimeInMs() {
- return mSubscriptionExpirationTimeInMs;
+ /**
+ * @hide
+ */
+ public long getSubscriptionExpirationTimeInMillis() {
+ return mSubscriptionExpirationTimeInMillis;
}
/**
@@ -171,9 +213,15 @@
* specific.
*/
private String mSubscriptionType = null;
+ /**
+ * @hide
+ */
public void setSubscriptionType(String subscriptionType) {
mSubscriptionType = subscriptionType;
}
+ /**
+ * @hide
+ */
public String getSubscriptionType() {
return mSubscriptionType;
}
@@ -184,9 +232,15 @@
* “pay as you go” - PAYG service). A non-zero value specifies the usage interval in minutes.
*/
private long mUsageLimitUsageTimePeriodInMinutes = Long.MIN_VALUE;
+ /**
+ * @hide
+ */
public void setUsageLimitUsageTimePeriodInMinutes(long usageLimitUsageTimePeriodInMinutes) {
mUsageLimitUsageTimePeriodInMinutes = usageLimitUsageTimePeriodInMinutes;
}
+ /**
+ * @hide
+ */
public long getUsageLimitUsageTimePeriodInMinutes() {
return mUsageLimitUsageTimePeriodInMinutes;
}
@@ -197,12 +251,18 @@
*
* Use Long.MIN_VALUE to indicate unset value.
*/
- private long mUsageLimitStartTimeInMs = Long.MIN_VALUE;
- public void setUsageLimitStartTimeInMs(long usageLimitStartTimeInMs) {
- mUsageLimitStartTimeInMs = usageLimitStartTimeInMs;
+ private long mUsageLimitStartTimeInMillis = Long.MIN_VALUE;
+ /**
+ * @hide
+ */
+ public void setUsageLimitStartTimeInMillis(long usageLimitStartTimeInMillis) {
+ mUsageLimitStartTimeInMillis = usageLimitStartTimeInMillis;
}
- public long getUsageLimitStartTimeInMs() {
- return mUsageLimitStartTimeInMs;
+ /**
+ * @hide
+ */
+ public long getUsageLimitStartTimeInMillis() {
+ return mUsageLimitStartTimeInMillis;
}
/**
@@ -212,9 +272,15 @@
* Use Long.MIN_VALUE to indicate unset value.
*/
private long mUsageLimitDataLimit = Long.MIN_VALUE;
+ /**
+ * @hide
+ */
public void setUsageLimitDataLimit(long usageLimitDataLimit) {
mUsageLimitDataLimit = usageLimitDataLimit;
}
+ /**
+ * @hide
+ */
public long getUsageLimitDataLimit() {
return mUsageLimitDataLimit;
}
@@ -224,9 +290,15 @@
* A value of zero indicate unlimited time usage.
*/
private long mUsageLimitTimeLimitInMinutes = Long.MIN_VALUE;
+ /**
+ * @hide
+ */
public void setUsageLimitTimeLimitInMinutes(long usageLimitTimeLimitInMinutes) {
mUsageLimitTimeLimitInMinutes = usageLimitTimeLimitInMinutes;
}
+ /**
+ * @hide
+ */
public long getUsageLimitTimeLimitInMinutes() {
return mUsageLimitTimeLimitInMinutes;
}
@@ -263,11 +335,11 @@
}
mUpdateIdentifier = source.mUpdateIdentifier;
mCredentialPriority = source.mCredentialPriority;
- mSubscriptionCreationTimeInMs = source.mSubscriptionCreationTimeInMs;
- mSubscriptionExpirationTimeInMs = source.mSubscriptionExpirationTimeInMs;
+ mSubscriptionCreationTimeInMillis = source.mSubscriptionCreationTimeInMillis;
+ mSubscriptionExpirationTimeInMillis = source.mSubscriptionExpirationTimeInMillis;
mSubscriptionType = source.mSubscriptionType;
mUsageLimitDataLimit = source.mUsageLimitDataLimit;
- mUsageLimitStartTimeInMs = source.mUsageLimitStartTimeInMs;
+ mUsageLimitStartTimeInMillis = source.mUsageLimitStartTimeInMillis;
mUsageLimitTimeLimitInMinutes = source.mUsageLimitTimeLimitInMinutes;
mUsageLimitUsageTimePeriodInMinutes = source.mUsageLimitUsageTimePeriodInMinutes;
}
@@ -286,11 +358,11 @@
writeTrustRootCerts(dest, mTrustRootCertList);
dest.writeInt(mUpdateIdentifier);
dest.writeInt(mCredentialPriority);
- dest.writeLong(mSubscriptionCreationTimeInMs);
- dest.writeLong(mSubscriptionExpirationTimeInMs);
+ dest.writeLong(mSubscriptionCreationTimeInMillis);
+ dest.writeLong(mSubscriptionExpirationTimeInMillis);
dest.writeString(mSubscriptionType);
dest.writeLong(mUsageLimitUsageTimePeriodInMinutes);
- dest.writeLong(mUsageLimitStartTimeInMs);
+ dest.writeLong(mUsageLimitStartTimeInMillis);
dest.writeLong(mUsageLimitDataLimit);
dest.writeLong(mUsageLimitTimeLimitInMinutes);
}
@@ -313,11 +385,11 @@
&& isTrustRootCertListEquals(mTrustRootCertList, that.mTrustRootCertList)
&& mUpdateIdentifier == that.mUpdateIdentifier
&& mCredentialPriority == that.mCredentialPriority
- && mSubscriptionCreationTimeInMs == that.mSubscriptionCreationTimeInMs
- && mSubscriptionExpirationTimeInMs == that.mSubscriptionExpirationTimeInMs
+ && mSubscriptionCreationTimeInMillis == that.mSubscriptionCreationTimeInMillis
+ && mSubscriptionExpirationTimeInMillis == that.mSubscriptionExpirationTimeInMillis
&& TextUtils.equals(mSubscriptionType, that.mSubscriptionType)
&& mUsageLimitUsageTimePeriodInMinutes == that.mUsageLimitUsageTimePeriodInMinutes
- && mUsageLimitStartTimeInMs == that.mUsageLimitStartTimeInMs
+ && mUsageLimitStartTimeInMillis == that.mUsageLimitStartTimeInMillis
&& mUsageLimitDataLimit == that.mUsageLimitDataLimit
&& mUsageLimitTimeLimitInMinutes == that.mUsageLimitTimeLimitInMinutes;
}
@@ -325,9 +397,9 @@
@Override
public int hashCode() {
return Objects.hash(mHomeSp, mCredential, mPolicy, mSubscriptionUpdate, mTrustRootCertList,
- mUpdateIdentifier, mCredentialPriority, mSubscriptionCreationTimeInMs,
- mSubscriptionExpirationTimeInMs, mUsageLimitUsageTimePeriodInMinutes,
- mUsageLimitStartTimeInMs, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes);
+ mUpdateIdentifier, mCredentialPriority, mSubscriptionCreationTimeInMillis,
+ mSubscriptionExpirationTimeInMillis, mUsageLimitUsageTimePeriodInMinutes,
+ mUsageLimitStartTimeInMillis, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes);
}
@Override
@@ -336,13 +408,13 @@
builder.append("UpdateIdentifier: ").append(mUpdateIdentifier).append("\n");
builder.append("CredentialPriority: ").append(mCredentialPriority).append("\n");
builder.append("SubscriptionCreationTime: ").append(
- mSubscriptionCreationTimeInMs != Long.MIN_VALUE
- ? new Date(mSubscriptionCreationTimeInMs) : "Not specified").append("\n");
+ mSubscriptionCreationTimeInMillis != Long.MIN_VALUE
+ ? new Date(mSubscriptionCreationTimeInMillis) : "Not specified").append("\n");
builder.append("SubscriptionExpirationTime: ").append(
- mSubscriptionExpirationTimeInMs != Long.MIN_VALUE
- ? new Date(mSubscriptionExpirationTimeInMs) : "Not specified").append("\n");
- builder.append("UsageLimitStartTime: ").append(mUsageLimitStartTimeInMs != Long.MIN_VALUE
- ? new Date(mUsageLimitStartTimeInMs) : "Not specified").append("\n");
+ mSubscriptionExpirationTimeInMillis != Long.MIN_VALUE
+ ? new Date(mSubscriptionExpirationTimeInMillis) : "Not specified").append("\n");
+ builder.append("UsageLimitStartTime: ").append(mUsageLimitStartTimeInMillis != Long.MIN_VALUE
+ ? new Date(mUsageLimitStartTimeInMillis) : "Not specified").append("\n");
builder.append("UsageTimePeriod: ").append(mUsageLimitUsageTimePeriodInMinutes)
.append("\n");
builder.append("UsageLimitDataLimit: ").append(mUsageLimitDataLimit).append("\n");
@@ -433,11 +505,11 @@
config.setTrustRootCertList(readTrustRootCerts(in));
config.setUpdateIdentifier(in.readInt());
config.setCredentialPriority(in.readInt());
- config.setSubscriptionCreationTimeInMs(in.readLong());
- config.setSubscriptionExpirationTimeInMs(in.readLong());
+ config.setSubscriptionCreationTimeInMillis(in.readLong());
+ config.setSubscriptionExpirationTimeInMillis(in.readLong());
config.setSubscriptionType(in.readString());
config.setUsageLimitUsageTimePeriodInMinutes(in.readLong());
- config.setUsageLimitStartTimeInMs(in.readLong());
+ config.setUsageLimitStartTimeInMillis(in.readLong());
config.setUsageLimitDataLimit(in.readLong());
config.setUsageLimitTimeLimitInMinutes(in.readLong());
return config;
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
index 5dc5d13..f6183fa 100644
--- a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
@@ -903,10 +903,10 @@
for (PPSNode child: node.getChildren()) {
switch (child.getName()) {
case NODE_CREATION_DATE:
- credential.setCreationTimeInMs(parseDate(getPpsNodeValue(child)));
+ credential.setCreationTimeInMillis(parseDate(getPpsNodeValue(child)));
break;
case NODE_EXPIRATION_DATE:
- credential.setExpirationTimeInMs(parseDate(getPpsNodeValue(child)));
+ credential.setExpirationTimeInMillis(parseDate(getPpsNodeValue(child)));
break;
case NODE_USERNAME_PASSWORD:
credential.setUserCredential(parseUserCredential(child));
@@ -1517,10 +1517,10 @@
for (PPSNode child : node.getChildren()) {
switch (child.getName()) {
case NODE_CREATION_DATE:
- config.setSubscriptionCreationTimeInMs(parseDate(getPpsNodeValue(child)));
+ config.setSubscriptionCreationTimeInMillis(parseDate(getPpsNodeValue(child)));
break;
case NODE_EXPIRATION_DATE:
- config.setSubscriptionExpirationTimeInMs(parseDate(getPpsNodeValue(child)));
+ config.setSubscriptionExpirationTimeInMillis(parseDate(getPpsNodeValue(child)));
break;
case NODE_TYPE_OF_SUBSCRIPTION:
config.setSubscriptionType(getPpsNodeValue(child));
@@ -1555,7 +1555,7 @@
config.setUsageLimitDataLimit(parseLong(getPpsNodeValue(child), 10));
break;
case NODE_START_DATE:
- config.setUsageLimitStartTimeInMs(parseDate(getPpsNodeValue(child)));
+ config.setUsageLimitStartTimeInMillis(parseDate(getPpsNodeValue(child)));
break;
case NODE_TIME_LIMIT:
config.setUsageLimitTimeLimitInMinutes(parseLong(getPpsNodeValue(child), 10));
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 67fa1bb..d712feb 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -58,12 +58,18 @@
* of milliseconds since January 1, 1970, 00:00:00 GMT.
* Using Long.MIN_VALUE to indicate unset value.
*/
- private long mCreationTimeInMs = Long.MIN_VALUE;
- public void setCreationTimeInMs(long creationTimeInMs) {
- mCreationTimeInMs = creationTimeInMs;
+ private long mCreationTimeInMillis = Long.MIN_VALUE;
+ /**
+ * @hide
+ */
+ public void setCreationTimeInMillis(long creationTimeInMillis) {
+ mCreationTimeInMillis = creationTimeInMillis;
}
- public long getCreationTimeInMs() {
- return mCreationTimeInMs;
+ /**
+ * @hide
+ */
+ public long getCreationTimeInMillis() {
+ return mCreationTimeInMillis;
}
/**
@@ -71,12 +77,18 @@
* of milliseconds since January 1, 1970, 00:00:00 GMT.
* Using Long.MIN_VALUE to indicate unset value.
*/
- private long mExpirationTimeInMs = Long.MIN_VALUE;
- public void setExpirationTimeInMs(long expirationTimeInMs) {
- mExpirationTimeInMs = expirationTimeInMs;
+ private long mExpirationTimeInMillis = Long.MIN_VALUE;
+ /**
+ * @hide
+ */
+ public void setExpirationTimeInMillis(long expirationTimeInMillis) {
+ mExpirationTimeInMillis = expirationTimeInMillis;
}
- public long getExpirationTimeInMs() {
- return mExpirationTimeInMs;
+ /**
+ * @hide
+ */
+ public long getExpirationTimeInMillis() {
+ return mExpirationTimeInMillis;
}
/**
@@ -98,9 +110,15 @@
* Protocol) authentication.
*/
private boolean mCheckAaaServerCertStatus = false;
+ /**
+ * @hide
+ */
public void setCheckAaaServerCertStatus(boolean checkAaaServerCertStatus) {
mCheckAaaServerCertStatus = checkAaaServerCertStatus;
}
+ /**
+ * @hide
+ */
public boolean getCheckAaaServerCertStatus() {
return mCheckAaaServerCertStatus;
}
@@ -166,9 +184,15 @@
* Flag indicating if the password is machine managed.
*/
private boolean mMachineManaged = false;
+ /**
+ * @hide
+ */
public void setMachineManaged(boolean machineManaged) {
mMachineManaged = machineManaged;
}
+ /**
+ * @hide
+ */
public boolean getMachineManaged() {
return mMachineManaged;
}
@@ -177,9 +201,15 @@
* The name of the application used to generate the password.
*/
private String mSoftTokenApp = null;
+ /**
+ * @hide
+ */
public void setSoftTokenApp(String softTokenApp) {
mSoftTokenApp = softTokenApp;
}
+ /**
+ * @hide
+ */
public String getSoftTokenApp() {
return mSoftTokenApp;
}
@@ -188,9 +218,15 @@
* Flag indicating if this credential is usable on other mobile devices as well.
*/
private boolean mAbleToShare = false;
+ /**
+ * @hide
+ */
public void setAbleToShare(boolean ableToShare) {
mAbleToShare = ableToShare;
}
+ /**
+ * @hide
+ */
public boolean getAbleToShare() {
return mAbleToShare;
}
@@ -720,8 +756,8 @@
*/
public Credential(Credential source) {
if (source != null) {
- mCreationTimeInMs = source.mCreationTimeInMs;
- mExpirationTimeInMs = source.mExpirationTimeInMs;
+ mCreationTimeInMillis = source.mCreationTimeInMillis;
+ mExpirationTimeInMillis = source.mExpirationTimeInMillis;
mRealm = source.mRealm;
mCheckAaaServerCertStatus = source.mCheckAaaServerCertStatus;
if (source.mUserCredential != null) {
@@ -749,8 +785,8 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mCreationTimeInMs);
- dest.writeLong(mExpirationTimeInMs);
+ dest.writeLong(mCreationTimeInMillis);
+ dest.writeLong(mExpirationTimeInMillis);
dest.writeString(mRealm);
dest.writeInt(mCheckAaaServerCertStatus ? 1 : 0);
dest.writeParcelable(mUserCredential, flags);
@@ -772,8 +808,8 @@
Credential that = (Credential) thatObject;
return TextUtils.equals(mRealm, that.mRealm)
- && mCreationTimeInMs == that.mCreationTimeInMs
- && mExpirationTimeInMs == that.mExpirationTimeInMs
+ && mCreationTimeInMillis == that.mCreationTimeInMillis
+ && mExpirationTimeInMillis == that.mExpirationTimeInMillis
&& mCheckAaaServerCertStatus == that.mCheckAaaServerCertStatus
&& (mUserCredential == null ? that.mUserCredential == null
: mUserCredential.equals(that.mUserCredential))
@@ -788,7 +824,7 @@
@Override
public int hashCode() {
- return Objects.hash(mRealm, mCreationTimeInMs, mExpirationTimeInMs,
+ return Objects.hash(mRealm, mCreationTimeInMillis, mExpirationTimeInMillis,
mCheckAaaServerCertStatus, mUserCredential, mCertCredential, mSimCredential,
mCaCertificate, mClientCertificateChain, mClientPrivateKey);
}
@@ -797,10 +833,10 @@
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Realm: ").append(mRealm).append("\n");
- builder.append("CreationTime: ").append(mCreationTimeInMs != Long.MIN_VALUE
- ? new Date(mCreationTimeInMs) : "Not specified").append("\n");
- builder.append("ExpirationTime: ").append(mExpirationTimeInMs != Long.MIN_VALUE
- ? new Date(mExpirationTimeInMs) : "Not specified").append("\n");
+ builder.append("CreationTime: ").append(mCreationTimeInMillis != Long.MIN_VALUE
+ ? new Date(mCreationTimeInMillis) : "Not specified").append("\n");
+ builder.append("ExpirationTime: ").append(mExpirationTimeInMillis != Long.MIN_VALUE
+ ? new Date(mExpirationTimeInMillis) : "Not specified").append("\n");
builder.append("CheckAAAServerStatus: ").append(mCheckAaaServerCertStatus).append("\n");
if (mUserCredential != null) {
builder.append("UserCredential Begin ---\n");
@@ -863,8 +899,8 @@
@Override
public Credential createFromParcel(Parcel in) {
Credential credential = new Credential();
- credential.setCreationTimeInMs(in.readLong());
- credential.setExpirationTimeInMs(in.readLong());
+ credential.setCreationTimeInMillis(in.readLong());
+ credential.setExpirationTimeInMillis(in.readLong());
credential.setRealm(in.readString());
credential.setCheckAaaServerCertStatus(in.readInt() != 0);
credential.setUserCredential(in.readParcelable(null));
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 9192ab0..2247860 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -74,9 +74,15 @@
* Icon URL of this home service provider.
*/
private String mIconUrl = null;
+ /**
+ * @hide
+ */
public void setIconUrl(String iconUrl) {
mIconUrl = iconUrl;
}
+ /**
+ * @hide
+ */
public String getIconUrl() {
return mIconUrl;
}
@@ -89,9 +95,15 @@
* string is assumed to be encoded using UTF-8.
*/
private Map<String, Long> mHomeNetworkIds = null;
+ /**
+ * @hide
+ */
public void setHomeNetworkIds(Map<String, Long> homeNetworkIds) {
mHomeNetworkIds = homeNetworkIds;
}
+ /**
+ * @hide
+ */
public Map<String, Long> getHomeNetworkIds() {
return mHomeNetworkIds;
}
@@ -107,9 +119,15 @@
* (MO) tree for more detail.
*/
private long[] mMatchAllOis = null;
+ /**
+ * @hide
+ */
public void setMatchAllOis(long[] matchAllOis) {
mMatchAllOis = matchAllOis;
}
+ /**
+ * @hide
+ */
public long[] getMatchAllOis() {
return mMatchAllOis;
}
@@ -128,9 +146,15 @@
* (MO) tree for more detail.
*/
private long[] mMatchAnyOis = null;
+ /**
+ * @hide
+ */
public void setMatchAnyOis(long[] matchAnyOis) {
mMatchAnyOis = matchAnyOis;
}
+ /**
+ * @hide
+ */
public long[] getMatchAnyOis() {
return mMatchAnyOis;
}
@@ -142,9 +166,15 @@
* operator merges between the providers.
*/
private String[] mOtherHomePartners = null;
+ /**
+ * @hide
+ */
public void setOtherHomePartners(String[] otherHomePartners) {
mOtherHomePartners = otherHomePartners;
}
+ /**
+ * @hide
+ */
public String[] getOtherHomePartners() {
return mOtherHomePartners;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index 1df70f8..ee0894b 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -40,6 +40,8 @@
*
* For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
* Release 2 Technical Specification.
+ *
+ * @hide
*/
public final class Policy implements Parcelable {
private static final String TAG = "Policy";
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
index a7adfeb..9eb6314 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
@@ -34,6 +34,8 @@
*
* For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
* Release 2 Technical Specification.
+ *
+ * @hide
*/
public final class UpdateParameter implements Parcelable {
private static final String TAG = "UpdateParameter";
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 3c0fc6e..03ef319 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -22,6 +22,7 @@
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
+import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -125,12 +126,12 @@
public void testCreationAndCloseOfLocalOnlyHotspotReservation() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(mApConfig);
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig));
- assertEquals(mApConfig, callback.mRes.getConfig());
+ assertEquals(mApConfig, callback.mRes.getWifiConfiguration());
callback.mRes.close();
verify(mWifiService).stopLocalOnlyHotspot();
}
@@ -143,13 +144,13 @@
throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(mApConfig);
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig));
try (WifiManager.LocalOnlyHotspotReservation res = callback.mRes) {
- assertEquals(mApConfig, res.getConfig());
+ assertEquals(mApConfig, res.getWifiConfiguration());
}
verify(mWifiService).stopLocalOnlyHotspot();
@@ -337,7 +338,7 @@
// record thread from looper.getThread and check ids.
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(null);
+ .thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -355,7 +356,7 @@
when(mContext.getMainLooper()).thenReturn(altLooper.getLooper());
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(null);
+ .thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, null);
altLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -372,7 +373,7 @@
TestLooper callbackLooper = new TestLooper();
Handler callbackHandler = new Handler(callbackLooper.getLooper());
when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
- any(IBinder.class))).thenReturn(mApConfig);
+ any(IBinder.class))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -386,7 +387,7 @@
mLooper.dispatchAll();
callbackLooper.dispatchAll();
assertTrue(callback.mOnStartedCalled);
- assertEquals(mApConfig, callback.mRes.getConfig());
+ assertEquals(mApConfig, callback.mRes.getWifiConfiguration());
}
/**
@@ -399,7 +400,7 @@
TestLooper callbackLooper = new TestLooper();
Handler callbackHandler = new Handler(callbackLooper.getLooper());
when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
- any(IBinder.class))).thenReturn(mApConfig);
+ any(IBinder.class))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -424,7 +425,7 @@
TestLooper callbackLooper = new TestLooper();
Handler callbackHandler = new Handler(callbackLooper.getLooper());
when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
- any(IBinder.class))).thenReturn(mApConfig);
+ any(IBinder.class))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -447,7 +448,7 @@
TestLooper callbackLooper = new TestLooper();
Handler callbackHandler = new Handler(callbackLooper.getLooper());
when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
- any(IBinder.class))).thenReturn(mApConfig);
+ any(IBinder.class))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -470,7 +471,7 @@
public void testLocalOnlyHotspotCallbackFullOnNullConfig() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(null);
+ .thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -508,7 +509,7 @@
public void testLocalOnlyHotspotCallbackFullOnNoChannelError() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(mApConfig);
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
//assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
@@ -524,7 +525,7 @@
public void testCancelLocalOnlyHotspotRequestCallsStopOnWifiService() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(mApConfig);
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mWifiManager.cancelLocalOnlyHotspotRequest();
verify(mWifiService).stopLocalOnlyHotspot();
@@ -546,7 +547,7 @@
public void testCallbackAfterLocalOnlyHotspotWasCancelled() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(mApConfig);
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mWifiManager.cancelLocalOnlyHotspotRequest();
verify(mWifiService).stopLocalOnlyHotspot();
@@ -565,7 +566,7 @@
public void testCancelAfterLocalOnlyHotspotCallbackTriggered() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
- .thenReturn(null);
+ .thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 7df4fcf..afcf3e3 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -158,11 +158,11 @@
config.setTrustRootCertList(trustRootCertList);
config.setUpdateIdentifier(1);
config.setCredentialPriority(120);
- config.setSubscriptionCreationTimeInMs(231200);
- config.setSubscriptionExpirationTimeInMs(2134232);
+ config.setSubscriptionCreationTimeInMillis(231200);
+ config.setSubscriptionExpirationTimeInMillis(2134232);
config.setSubscriptionType("Gold");
config.setUsageLimitUsageTimePeriodInMinutes(3600);
- config.setUsageLimitStartTimeInMs(124214213);
+ config.setUsageLimitStartTimeInMillis(124214213);
config.setUsageLimitDataLimit(14121);
config.setUsageLimitTimeLimitInMinutes(78912);
return config;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
index 7cd72f0..afa9fd6 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
@@ -113,11 +113,11 @@
config.setSubscriptionUpdate(subscriptionUpdate);
// Subscription parameters.
- config.setSubscriptionCreationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
- config.setSubscriptionExpirationTimeInMs(format.parse("2016-03-01T10:00:00Z").getTime());
+ config.setSubscriptionCreationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime());
+ config.setSubscriptionExpirationTimeInMillis(format.parse("2016-03-01T10:00:00Z").getTime());
config.setSubscriptionType("Gold");
config.setUsageLimitDataLimit(921890);
- config.setUsageLimitStartTimeInMs(format.parse("2016-12-01T10:00:00Z").getTime());
+ config.setUsageLimitStartTimeInMillis(format.parse("2016-12-01T10:00:00Z").getTime());
config.setUsageLimitTimeLimitInMinutes(120);
config.setUsageLimitUsageTimePeriodInMinutes(99910);
@@ -138,8 +138,8 @@
// Credential configuration.
Credential credential = new Credential();
- credential.setCreationTimeInMs(format.parse("2016-01-01T10:00:00Z").getTime());
- credential.setExpirationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
+ credential.setCreationTimeInMillis(format.parse("2016-01-01T10:00:00Z").getTime());
+ credential.setExpirationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime());
credential.setRealm("shaken.stirred.com");
credential.setCheckAaaServerCertStatus(true);
Credential.UserCredential userCredential = new Credential.UserCredential();
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index c7ade00..9bfc010 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -56,8 +56,8 @@
X509Certificate[] clientCertificateChain,
PrivateKey clientPrivateKey) {
Credential cred = new Credential();
- cred.setCreationTimeInMs(123455L);
- cred.setExpirationTimeInMs(2310093L);
+ cred.setCreationTimeInMillis(123455L);
+ cred.setExpirationTimeInMillis(2310093L);
cred.setRealm("realm");
cred.setCheckAaaServerCertStatus(true);
cred.setUserCredential(userCred);
@@ -440,4 +440,4 @@
Credential copyCred = new Credential(sourceCred);
assertTrue(copyCred.equals(sourceCred));
}
-}
\ No newline at end of file
+}