Merge "Update core widgets to save attribute source info."
diff --git a/api/TEST_MAPPING b/api/TEST_MAPPING
new file mode 100644
index 0000000..8a676e9
--- /dev/null
+++ b/api/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsCurrentApiSignatureTestCases"
+ }
+ ]
+}
diff --git a/api/current.txt b/api/current.txt
index abab901..0002a0c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14191,13 +14191,16 @@
field public static final int YV12 = 842094169; // 0x32315659
}
- public final class Insets {
+ public final class Insets implements android.os.Parcelable {
method @NonNull public static android.graphics.Insets add(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
+ method public int describeContents();
method @NonNull public static android.graphics.Insets max(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
method @NonNull public static android.graphics.Insets min(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
method @NonNull public static android.graphics.Insets of(int, int, int, int);
method @NonNull public static android.graphics.Insets of(@Nullable android.graphics.Rect);
method @NonNull public static android.graphics.Insets subtract(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.graphics.Insets> CREATOR;
field public static final android.graphics.Insets NONE;
field public final int bottom;
field public final int left;
@@ -16489,6 +16492,7 @@
field public static final int BIOMETRIC_ERROR_LOCKOUT = 7; // 0x7
field public static final int BIOMETRIC_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
field public static final int BIOMETRIC_ERROR_NO_BIOMETRICS = 11; // 0xb
+ field public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14; // 0xe
field public static final int BIOMETRIC_ERROR_NO_SPACE = 4; // 0x4
field public static final int BIOMETRIC_ERROR_TIMEOUT = 3; // 0x3
field public static final int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
@@ -16511,8 +16515,8 @@
public static class BiometricPrompt.Builder {
ctor public BiometricPrompt.Builder(android.content.Context);
method public android.hardware.biometrics.BiometricPrompt build();
+ method public android.hardware.biometrics.BiometricPrompt.Builder setAllowDeviceCredential(boolean);
method public android.hardware.biometrics.BiometricPrompt.Builder setDescription(@NonNull CharSequence);
- method public android.hardware.biometrics.BiometricPrompt.Builder setEnableFallback(boolean);
method public android.hardware.biometrics.BiometricPrompt.Builder setNegativeButton(@NonNull CharSequence, @NonNull java.util.concurrent.Executor, @NonNull android.content.DialogInterface.OnClickListener);
method public android.hardware.biometrics.BiometricPrompt.Builder setRequireConfirmation(boolean);
method public android.hardware.biometrics.BiometricPrompt.Builder setSubtitle(@NonNull CharSequence);
@@ -24535,7 +24539,9 @@
}
public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
+ ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int);
method public boolean covers(@NonNull android.media.MediaFormat);
+ method public boolean covers(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint);
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100;
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120;
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200;
@@ -24570,8 +24576,8 @@
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50;
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60;
field public final int frameRate;
- field public final int height;
- field public final int width;
+ field public final long macroBlockRate;
+ field public final int macroBlocks;
}
public final class MediaCodecList {
@@ -38340,11 +38346,7 @@
method @NonNull public static String getVolumeName(@NonNull android.net.Uri);
method @NonNull public static android.provider.MediaStore.PendingSession openPending(@NonNull android.content.Context, @NonNull android.net.Uri);
method @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri);
- method @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
method @NonNull public static android.net.Uri setRequireOriginal(@NonNull android.net.Uri);
- method public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
- method public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
- method public static void untrash(@NonNull android.content.Context, @NonNull android.net.Uri);
field public static final String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
field public static final String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
field public static final String ACTION_REVIEW = "android.provider.action.REVIEW";
@@ -38615,14 +38617,14 @@
public static interface MediaStore.MediaColumns extends android.provider.BaseColumns {
field @Deprecated public static final String DATA = "_data";
field public static final String DATE_ADDED = "date_added";
- field public static final String DATE_EXPIRES = "date_expires";
field public static final String DATE_MODIFIED = "date_modified";
field public static final String DISPLAY_NAME = "_display_name";
- field public static final String HASH = "_hash";
+ field public static final String DOCUMENT_ID = "document_id";
field public static final String HEIGHT = "height";
+ field public static final String INSTANCE_ID = "instance_id";
field public static final String IS_PENDING = "is_pending";
- field public static final String IS_TRASHED = "is_trashed";
field public static final String MIME_TYPE = "mime_type";
+ field public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
field public static final String OWNER_PACKAGE_NAME = "owner_package_name";
field public static final String PRIMARY_DIRECTORY = "primary_directory";
field public static final String SECONDARY_DIRECTORY = "secondary_directory";
@@ -48995,6 +48997,7 @@
method public boolean[] hasKeys(int...);
method public boolean hasMicrophone();
method public boolean isEnabled();
+ method public boolean isExternal();
method public boolean isVirtual();
method public boolean supportsSource(int);
method public void writeToParcel(android.os.Parcel, int);
@@ -49550,6 +49553,7 @@
ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
method public abstract android.view.LayoutInflater cloneInContext(android.content.Context);
method public final android.view.View createView(String, String, android.util.AttributeSet) throws java.lang.ClassNotFoundException, android.view.InflateException;
+ method @Nullable public final android.view.View createView(@NonNull android.content.Context, @NonNull String, @Nullable String, @Nullable android.util.AttributeSet) throws java.lang.ClassNotFoundException, android.view.InflateException;
method public static android.view.LayoutInflater from(android.content.Context);
method public android.content.Context getContext();
method public final android.view.LayoutInflater.Factory getFactory();
@@ -49561,6 +49565,7 @@
method public android.view.View inflate(org.xmlpull.v1.XmlPullParser, @Nullable android.view.ViewGroup, boolean);
method protected android.view.View onCreateView(String, android.util.AttributeSet) throws java.lang.ClassNotFoundException;
method protected android.view.View onCreateView(android.view.View, String, android.util.AttributeSet) throws java.lang.ClassNotFoundException;
+ method @Nullable public android.view.View onCreateView(@NonNull android.content.Context, @Nullable android.view.View, @NonNull String, @Nullable android.util.AttributeSet) throws java.lang.ClassNotFoundException;
method public void setFactory(android.view.LayoutInflater.Factory);
method public void setFactory2(android.view.LayoutInflater.Factory2);
method public void setFilter(android.view.LayoutInflater.Filter);
@@ -51111,6 +51116,7 @@
method public int getScaledHoverSlop();
method public int getScaledMaximumDrawingCacheSize();
method public int getScaledMaximumFlingVelocity();
+ method public int getScaledMinScalingSpan();
method public int getScaledMinimumFlingVelocity();
method public int getScaledOverflingDistance();
method public int getScaledOverscrollDistance();
@@ -52607,7 +52613,6 @@
public abstract class Animation implements java.lang.Cloneable {
ctor public Animation();
ctor public Animation(android.content.Context, android.util.AttributeSet);
- method public void addAnimationListener(android.view.animation.Animation.AnimationListener);
method protected void applyTransformation(float, android.view.animation.Transformation);
method public void cancel();
method protected android.view.animation.Animation clone() throws java.lang.CloneNotSupportedException;
@@ -52632,7 +52637,6 @@
method public void initialize(int, int, int, int);
method public boolean isFillEnabled();
method public boolean isInitialized();
- method public void removeAnimationListener(android.view.animation.Animation.AnimationListener);
method public void reset();
method protected float resolveSize(int, float, int, int);
method public void restrictDuration(long);
@@ -55245,6 +55249,7 @@
method public void performCompletion();
method protected void performFiltering(CharSequence, int);
method public void performValidation();
+ method public final void refreshAutoCompleteResults();
method protected void replaceText(CharSequence);
method public <T extends android.widget.ListAdapter & android.widget.Filterable> void setAdapter(T);
method public void setCompletionHint(CharSequence);
@@ -55864,11 +55869,16 @@
method public boolean executeKeyEvent(android.view.KeyEvent);
method public void fling(int);
method public boolean fullScroll(int);
+ method @ColorInt public int getLeftEdgeEffectColor();
method public int getMaxScrollAmount();
+ method @ColorInt public int getRightEdgeEffectColor();
method public boolean isFillViewport();
method public boolean isSmoothScrollingEnabled();
method public boolean pageScroll(int);
+ method public void setEdgeEffectColor(@ColorInt int);
method public void setFillViewport(boolean);
+ method public void setLeftEdgeEffectColor(@ColorInt int);
+ method public void setRightEdgeEffectColor(@ColorInt int);
method public void setSmoothScrollingEnabled(boolean);
method public final void smoothScrollBy(int, int);
method public final void smoothScrollTo(int, int);
@@ -56009,6 +56019,7 @@
method @Nullable public android.view.View getAnchorView();
method @StyleRes public int getAnimationStyle();
method @Nullable public android.graphics.drawable.Drawable getBackground();
+ method @Nullable public android.graphics.Rect getEpicenterBounds();
method public int getHeight();
method public int getHorizontalOffset();
method public int getInputMethodMode();
@@ -56035,6 +56046,7 @@
method public void setBackgroundDrawable(@Nullable android.graphics.drawable.Drawable);
method public void setContentWidth(int);
method public void setDropDownGravity(int);
+ method public void setEpicenterBounds(@Nullable android.graphics.Rect);
method public void setHeight(int);
method public void setHorizontalOffset(int);
method public void setInputMethodMode(int);
@@ -56295,6 +56307,7 @@
method public android.view.View getContentView();
method public float getElevation();
method @Nullable public android.transition.Transition getEnterTransition();
+ method @Nullable public android.graphics.Rect getEpicenterBounds();
method @Nullable public android.transition.Transition getExitTransition();
method public int getHeight();
method public int getInputMethodMode();
@@ -56307,30 +56320,37 @@
method public int getWindowLayoutType();
method public boolean isAboveAnchor();
method public boolean isAttachedInDecor();
+ method public boolean isClipToScreenEnabled();
method public boolean isClippingEnabled();
method public boolean isFocusable();
+ method public boolean isLayoutInScreenEnabled();
method public boolean isOutsideTouchable();
method public boolean isShowing();
method public boolean isSplitTouchEnabled();
+ method public boolean isTouchModal();
method public boolean isTouchable();
method public void setAnimationStyle(int);
method public void setAttachedInDecor(boolean);
method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+ method public void setClipToScreenEnabled(boolean);
method public void setClippingEnabled(boolean);
method public void setContentView(android.view.View);
method public void setElevation(float);
method public void setEnterTransition(@Nullable android.transition.Transition);
+ method public void setEpicenterBounds(@Nullable android.graphics.Rect);
method public void setExitTransition(@Nullable android.transition.Transition);
method public void setFocusable(boolean);
method public void setHeight(int);
method public void setIgnoreCheekPress();
method public void setInputMethodMode(int);
+ method public void setLayoutInScreenEnabled(boolean);
method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
method public void setOutsideTouchable(boolean);
method public void setOverlapAnchor(boolean);
method public void setSoftInputMode(int);
method public void setSplitTouchEnabled(boolean);
method public void setTouchInterceptor(android.view.View.OnTouchListener);
+ method public void setTouchModal(boolean);
method public void setTouchable(boolean);
method public void setWidth(int);
method @Deprecated public void setWindowLayoutMode(int, int);
@@ -56359,6 +56379,7 @@
ctor public ProgressBar(android.content.Context, android.util.AttributeSet);
ctor public ProgressBar(android.content.Context, android.util.AttributeSet, int);
ctor public ProgressBar(android.content.Context, android.util.AttributeSet, int, int);
+ method @Nullable public android.graphics.drawable.Drawable getCurrentDrawable();
method public android.graphics.drawable.Drawable getIndeterminateDrawable();
method @Nullable public android.content.res.ColorStateList getIndeterminateTintList();
method @Nullable public android.graphics.PorterDuff.Mode getIndeterminateTintMode();
@@ -56656,13 +56677,18 @@
method public boolean executeKeyEvent(android.view.KeyEvent);
method public void fling(int);
method public boolean fullScroll(int);
+ method @ColorInt public int getBottomEdgeEffectColor();
method public int getMaxScrollAmount();
+ method @ColorInt public int getTopEdgeEffectColor();
method public boolean isFillViewport();
method public boolean isSmoothScrollingEnabled();
method public boolean pageScroll(int);
method public void scrollToDescendant(android.view.View);
+ method public void setBottomEdgeEffectColor(@ColorInt int);
+ method public void setEdgeEffectColor(@ColorInt int);
method public void setFillViewport(boolean);
method public void setSmoothScrollingEnabled(boolean);
+ method public void setTopEdgeEffectColor(@ColorInt int);
method public final void smoothScrollBy(int, int);
method public final void smoothScrollTo(int, int);
}
@@ -61183,9 +61209,9 @@
method public String getName();
method public int getReferenceKind();
method public default boolean isVarArgs();
- method public static boolean refKindIsField(int);
- method public static boolean refKindIsValid(int);
- method public static String refKindName(int);
+ method @Deprecated public static boolean refKindIsField(int);
+ method @Deprecated public static boolean refKindIsValid(int);
+ method @Deprecated public static String refKindName(int);
method public static String referenceKindToString(int);
method public <T extends java.lang.reflect.Member> T reflectAs(Class<T>, java.lang.invoke.MethodHandles.Lookup);
method public static String toString(int, Class<?>, String, java.lang.invoke.MethodType);
diff --git a/api/removed.txt b/api/removed.txt
index 262ffec..f5bd434 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -507,6 +507,19 @@
field @Deprecated public static final String TIMESTAMP = "timestamp";
}
+ public final class MediaStore {
+ method @Deprecated @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
+ method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
+ method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
+ method @Deprecated public static void untrash(@NonNull android.content.Context, @NonNull android.net.Uri);
+ }
+
+ public static interface MediaStore.MediaColumns extends android.provider.BaseColumns {
+ field @Deprecated public static final String DATE_EXPIRES = "date_expires";
+ field @Deprecated public static final String HASH = "_hash";
+ field @Deprecated public static final String IS_TRASHED = "is_trashed";
+ }
+
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field @Deprecated public static final String CONTACT_METADATA_SYNC = "contact_metadata_sync";
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 02718cb..7babf56 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -201,11 +201,11 @@
}
public static final class R.array {
- field public static final int config_defaultRoleHolders = 17235974; // 0x1070006
field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005
}
public static final class R.attr {
+ field public static final int allowClearUserDataOnFailedRestore = 16844198; // 0x10105a6
field public static final int inheritShowWhenLocked = 16844194; // 0x10105a2
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
@@ -237,6 +237,12 @@
}
public static final class R.string {
+ field public static final int config_defaultAssistant = 17039393; // 0x1040021
+ field public static final int config_defaultBrowser = 17039394; // 0x1040022
+ field public static final int config_defaultDialer = 17039395; // 0x1040023
+ field public static final int config_defaultGallery = 17039398; // 0x1040026
+ field public static final int config_defaultMusic = 17039397; // 0x1040025
+ field public static final int config_defaultSms = 17039396; // 0x1040024
field public static final int config_feedbackIntentExtraKey = 17039391; // 0x104001f
field public static final int config_feedbackIntentNameKey = 17039392; // 0x1040020
field public static final int config_helpIntentExtraKey = 17039389; // 0x104001d
@@ -1145,7 +1151,7 @@
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
method public int getUsageSource();
- method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
+ method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
method public void reportUsageStart(@NonNull android.app.Activity, @NonNull String);
@@ -5739,10 +5745,6 @@
field public static final String SERVICE_ENABLED = "service_enabled";
}
- public static interface DeviceConfig.ContentCapture {
- field public static final String NAMESPACE = "content_capture";
- }
-
public static interface DeviceConfig.DexBoot {
field public static final String NAMESPACE = "dex_boot";
field public static final String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled";
@@ -5785,6 +5787,11 @@
field public static final String NAMESPACE = "runtime_native_boot";
}
+ public static interface DeviceConfig.Scheduler {
+ field public static final String ENABLE_FAST_METRICS_COLLECTION = "enable_fast_metrics_collection";
+ field public static final String NAMESPACE = "scheduler";
+ }
+
public static interface DeviceConfig.Storage {
field public static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
field public static final String NAMESPACE = "storage";
diff --git a/api/test-current.txt b/api/test-current.txt
index 2c8d08c..6954011 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -17,8 +17,9 @@
field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
}
- public static final class R.array {
- field public static final int config_defaultRoleHolders = 17235974; // 0x1070006
+ public static final class R.string {
+ field public static final int config_defaultAssistant = 17039393; // 0x1040021
+ field public static final int config_defaultDialer = 17039395; // 0x1040023
}
}
@@ -1784,8 +1785,10 @@
}
public final class DeviceConfig {
+ method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(String, String);
method @RequiresPermission("android.permission.WRITE_DEVICE_CONFIG") public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission("android.permission.WRITE_DEVICE_CONFIG") public static boolean setProperty(String, String, String, boolean);
+ field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
}
public static interface DeviceConfig.Privacy {
@@ -1810,7 +1813,6 @@
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
- field public static final String AUTOFILL_SMART_SUGGESTION_EMULATION_FLAGS = "autofill_smart_suggestion_emulation_flags";
field public static final String AUTOMATIC_POWER_SAVER_MODE = "automatic_power_saver_mode";
field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
@@ -1853,6 +1855,7 @@
field @Deprecated public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
field public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
+ field public static final String NOTIFICATION_BADGING = "notification_badging";
field public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
field @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
field public static final String USER_SETUP_COMPLETE = "user_setup_complete";
@@ -2152,6 +2155,10 @@
ctor public CallAudioState(boolean, int, int, @Nullable android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.bluetooth.BluetoothDevice>);
}
+ public abstract class Conference extends android.telecom.Conferenceable {
+ method public android.telecom.Connection getPrimaryConnection();
+ }
+
public final class PhoneAccountSuggestion implements android.os.Parcelable {
ctor public PhoneAccountSuggestion(android.telecom.PhoneAccountHandle, int, boolean);
}
@@ -2164,6 +2171,16 @@
field public static final String SERVICE_INTERFACE = "android.telecom.PhoneAccountSuggestionService";
}
+ public class TelecomManager {
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCurrentTtyMode();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(android.telecom.PhoneAccountHandle);
+ field public static final int TTY_MODE_FULL = 1; // 0x1
+ field public static final int TTY_MODE_HCO = 2; // 0x2
+ field public static final int TTY_MODE_OFF = 0; // 0x0
+ field public static final int TTY_MODE_VCO = 3; // 0x3
+ }
+
}
package android.telephony {
@@ -2676,6 +2693,7 @@
public final class AutofillManager {
method public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1
field public static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 120000; // 0x1d4c0
}
@@ -2717,6 +2735,7 @@
public final class ContentCaptureManager {
method public boolean isContentCaptureFeatureEnabled();
method public void setContentCaptureFeatureEnabled(boolean);
+ field public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED = "service_explicitly_enabled";
}
public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 2fef407..d757e46 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -56,6 +56,7 @@
shared_libs: [
"libandroidfw",
"libbase",
+ "libcutils",
"libutils",
"libziparchive",
],
@@ -150,6 +151,7 @@
shared_libs: [
"libandroidfw",
"libbase",
+ "libcutils",
"libidmap2",
"libutils",
"libziparchive",
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index 0c581f3..6703909 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -29,6 +29,7 @@
#include "idmap2/Idmap.h"
#include "idmap2/Policies.h"
#include "idmap2/Result.h"
+#include "idmap2/SysTrace.h"
using android::ApkAssets;
using android::idmap2::BinaryStreamVisitor;
@@ -42,6 +43,7 @@
using android::idmap2::utils::UidHasWriteAccessToPath;
bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
+ SYSTRACE << "Create " << args;
std::string target_apk_path;
std::string overlay_apk_path;
std::string idmap_path;
diff --git a/cmds/idmap2/idmap2/Dump.cpp b/cmds/idmap2/idmap2/Dump.cpp
index c8cdcfa..3947703 100644
--- a/cmds/idmap2/idmap2/Dump.cpp
+++ b/cmds/idmap2/idmap2/Dump.cpp
@@ -24,6 +24,7 @@
#include "idmap2/Idmap.h"
#include "idmap2/PrettyPrintVisitor.h"
#include "idmap2/RawPrintVisitor.h"
+#include "idmap2/SysTrace.h"
using android::idmap2::CommandLineOptions;
using android::idmap2::Idmap;
@@ -31,6 +32,7 @@
using android::idmap2::RawPrintVisitor;
bool Dump(const std::vector<std::string>& args, std::ostream& out_error) {
+ SYSTRACE << "Dump " << args;
std::string idmap_path;
bool verbose;
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index cfb5dd5..553d8ca 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -37,6 +37,7 @@
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
#include "idmap2/Result.h"
+#include "idmap2/SysTrace.h"
#include "idmap2/Xml.h"
#include "idmap2/ZipFile.h"
@@ -156,6 +157,7 @@
} // namespace
bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) {
+ SYSTRACE << "Lookup " << args;
std::vector<std::string> idmap_paths;
std::string config_str;
std::string resid_str;
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index 445fac5..a0ffccb 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -24,6 +24,7 @@
#include <vector>
#include "idmap2/CommandLineOptions.h"
+#include "idmap2/SysTrace.h"
#include "Commands.h"
@@ -48,6 +49,7 @@
} // namespace
int main(int argc, char** argv) {
+ SYSTRACE << "main";
const NameToFunctionMap commands = {
{"create", Create}, {"dump", Dump}, {"lookup", Lookup}, {"scan", Scan}, {"verify", Verify},
};
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index b1ed42a..873779f 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -30,6 +30,7 @@
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
#include "idmap2/ResourceUtils.h"
+#include "idmap2/SysTrace.h"
#include "idmap2/Xml.h"
#include "idmap2/ZipFile.h"
@@ -67,6 +68,7 @@
std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::string>& dirs,
bool recursive, std::ostream& out_error) {
+ SYSTRACE << "FindApkFiles " << dirs << " " << recursive;
const auto predicate = [](unsigned char type, const std::string& path) -> bool {
static constexpr size_t kExtLen = 4; // strlen(".apk")
return type == DT_REG && path.size() > kExtLen &&
@@ -104,6 +106,7 @@
} // namespace
bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
+ SYSTRACE << "Scan " << args;
std::vector<std::string> input_directories;
std::string target_package_name;
std::string target_apk_path;
diff --git a/cmds/idmap2/idmap2/Verify.cpp b/cmds/idmap2/idmap2/Verify.cpp
index 4d4a0e7..d8fe7aa 100644
--- a/cmds/idmap2/idmap2/Verify.cpp
+++ b/cmds/idmap2/idmap2/Verify.cpp
@@ -21,11 +21,13 @@
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
+#include "idmap2/SysTrace.h"
using android::idmap2::CommandLineOptions;
using android::idmap2::IdmapHeader;
bool Verify(const std::vector<std::string>& args, std::ostream& out_error) {
+ SYSTRACE << "Verify " << args;
std::string idmap_path;
const CommandLineOptions opts =
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index f30ce9b..0e4bd89 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -29,13 +29,13 @@
#include "android-base/stringprintf.h"
#include "binder/IPCThreadState.h"
#include "utils/String8.h"
-#include "utils/Trace.h"
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
#include "idmap2/Policies.h"
#include "idmap2/Result.h"
+#include "idmap2/SysTrace.h"
#include "idmap2d/Idmap2Service.h"
@@ -72,6 +72,7 @@
Status Idmap2Service::getIdmapPath(const std::string& overlay_apk_path,
int32_t user_id ATTRIBUTE_UNUSED, std::string* _aidl_return) {
assert(_aidl_return);
+ SYSTRACE << "Idmap2Service::getIdmapPath " << overlay_apk_path;
*_aidl_return = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
return ok();
}
@@ -79,6 +80,7 @@
Status Idmap2Service::removeIdmap(const std::string& overlay_apk_path,
int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) {
assert(_aidl_return);
+ SYSTRACE << "Idmap2Service::removeIdmap " << overlay_apk_path;
const uid_t uid = IPCThreadState::self()->getCallingUid();
const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
if (!UidHasWriteAccessToPath(uid, idmap_path)) {
@@ -98,6 +100,7 @@
int32_t fulfilled_policies ATTRIBUTE_UNUSED,
bool enforce_overlayable ATTRIBUTE_UNUSED,
int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) {
+ SYSTRACE << "Idmap2Service::verifyIdmap " << overlay_apk_path;
assert(_aidl_return);
const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
std::ifstream fin(idmap_path);
@@ -113,15 +116,10 @@
Status Idmap2Service::createIdmap(const std::string& target_apk_path,
const std::string& overlay_apk_path, int32_t fulfilled_policies,
- bool enforce_overlayable, int32_t user_id,
+ bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED,
std::unique_ptr<std::string>* _aidl_return) {
assert(_aidl_return);
- std::stringstream trace;
- trace << __FUNCTION__ << " " << target_apk_path << " " << overlay_apk_path << " "
- << std::to_string(user_id);
- ATRACE_NAME(trace.str().c_str());
- std::cout << trace.str() << std::endl;
-
+ SYSTRACE << "Idmap2Service::createIdmap " << target_apk_path << " " << overlay_apk_path;
_aidl_return->reset(nullptr);
const PolicyBitmask policy_bitmask = ConvertAidlArgToPolicyBitmask(fulfilled_policies);
diff --git a/cmds/idmap2/include/idmap2/SysTrace.h b/cmds/idmap2/include/idmap2/SysTrace.h
new file mode 100644
index 0000000..19b4353
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/SysTrace.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_SYSTRACE_H_
+#define IDMAP2_INCLUDE_IDMAP2_SYSTRACE_H_
+
+#define ATRACE_TAG ATRACE_TAG_RRO
+
+#include <sstream>
+#include <vector>
+
+#include "cutils/trace.h"
+
+namespace android::idmap2::utils {
+#ifdef __ANDROID__
+
+class ScopedTraceNoStart {
+ public:
+ ~ScopedTraceNoStart() {
+ ATRACE_END();
+ }
+};
+
+class ScopedTraceMessageHelper {
+ public:
+ ~ScopedTraceMessageHelper() {
+ ATRACE_BEGIN(buffer_.str().c_str());
+ }
+
+ std::ostream& stream() {
+ return buffer_;
+ }
+
+ private:
+ std::ostringstream buffer_;
+};
+
+#define SYSTRACE \
+ android::idmap2::utils::ScopedTraceNoStart _trace##__LINE__; \
+ (ATRACE_ENABLED()) && android::idmap2::utils::ScopedTraceMessageHelper().stream()
+
+#else
+
+class DummyStream {
+ public:
+ std::ostream& stream() {
+ return buffer_;
+ }
+
+ private:
+ std::ostringstream buffer_;
+};
+
+#define SYSTRACE android::idmap2::utils::DummyStream().stream()
+
+#endif
+} // namespace android::idmap2::utils
+
+template <typename T>
+std::ostream& operator<<(std::ostream& stream, const std::vector<T>& vector) {
+ bool first = true;
+ stream << "[";
+ for (const auto& item : vector) {
+ if (!first) {
+ stream << ", ";
+ }
+ stream << item;
+ first = false;
+ }
+ stream << "]";
+ return stream;
+}
+
+#endif // IDMAP2_INCLUDE_IDMAP2_SYSTRACE_H_
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index b19d7a9..99b5f0f 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -34,6 +34,7 @@
#include "idmap2/Idmap.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
+#include "idmap2/SysTrace.h"
#include "idmap2/ZipFile.h"
namespace android::idmap2 {
@@ -258,6 +259,7 @@
std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream,
std::ostream& out_error) {
+ SYSTRACE << "Idmap::FromBinaryStream";
std::unique_ptr<Idmap> idmap(new Idmap());
idmap->header_ = IdmapHeader::FromBinaryStream(stream);
@@ -304,6 +306,7 @@
const std::string& target_apk_path, const ApkAssets& target_apk_assets,
const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets,
const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error) {
+ SYSTRACE << "Idmap::FromApkAssets";
AssetManager2 target_asset_manager;
if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true, false)) {
out_error << "error: failed to create target asset manager" << std::endl;
diff --git a/cmds/idmap2/static-checks.sh b/cmds/idmap2/static-checks.sh
index 5740710..41d3c69 100755
--- a/cmds/idmap2/static-checks.sh
+++ b/cmds/idmap2/static-checks.sh
@@ -59,7 +59,7 @@
function _bpfmt()
{
- local output="$(bpfmt -s -d $bp_files)"
+ local output="$(bpfmt -d $bp_files)"
if [[ "$output" ]]; then
echo "$output"
return 1
@@ -72,6 +72,7 @@
local cpplint="${ANDROID_BUILD_TOP}/tools/repohooks/tools/cpplint.py"
local output="$($cpplint --quiet $cpp_files 2>&1 >/dev/null | grep -v \
-e 'Found C system header after C++ system header.' \
+ -e 'Unknown NOLINT error category: cert-dcl50-cpp' \
-e 'Unknown NOLINT error category: misc-non-private-member-variables-in-classes' \
-e 'Unknown NOLINT error category: performance-unnecessary-copy-initialization' \
)"
@@ -116,7 +117,7 @@
exit $errors
elif [[ $opt_mode == "fix" ]]; then
clang-format -style=file -i $cpp_files
- bpfmt -s -w $bp_files
+ bpfmt -w $bp_files
exit 0
elif [[ $opt_mode == "help" ]]; then
echo "Run static analysis tools such as clang-format and cpplint on the idmap2"
diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp
index 40da583..3dc1093 100644
--- a/cmds/incidentd/Android.bp
+++ b/cmds/incidentd/Android.bp
@@ -94,8 +94,10 @@
data: ["testdata/**/*"],
- static_libs: ["libgmock"],
-
+ static_libs: [
+ "libgmock",
+ "libplatformprotos",
+ ],
shared_libs: [
"libbase",
"libbinder",
diff --git a/cmds/incidentd/tests/Reporter_test.cpp b/cmds/incidentd/tests/Reporter_test.cpp
index f54f738..b5e41d7 100644
--- a/cmds/incidentd/tests/Reporter_test.cpp
+++ b/cmds/incidentd/tests/Reporter_test.cpp
@@ -35,6 +35,16 @@
using ::testing::StrEq;
using ::testing::Test;
+namespace {
+void getHeaderData(const IncidentHeaderProto& headerProto, vector<uint8_t>* out) {
+ out->clear();
+ auto serialized = headerProto.SerializeAsString();
+ if (serialized.empty()) return;
+ out->resize(serialized.length());
+ std::copy(serialized.begin(), serialized.end(), out->begin());
+}
+}
+
class TestListener : public IIncidentReportStatusListener {
public:
int startInvoked;
@@ -143,7 +153,10 @@
args2.addSection(2);
IncidentHeaderProto header;
header.set_alert_id(12);
- args2.addHeader(header);
+
+ vector<uint8_t> out;
+ getHeaderData(header, &out);
+ args2.addHeader(out);
sp<ReportRequest> r1 = new ReportRequest(args1, l, tf.fd);
sp<ReportRequest> r2 = new ReportRequest(args2, l, tf.fd);
@@ -169,8 +182,12 @@
IncidentHeaderProto header1, header2;
header1.set_alert_id(12);
header2.set_reason("abcd");
- args.addHeader(header1);
- args.addHeader(header2);
+
+ vector<uint8_t> out;
+ getHeaderData(header1, &out);
+ args.addHeader(out);
+ getHeaderData(header2, &out);
+ args.addHeader(out);
sp<ReportRequest> r = new ReportRequest(args, l, -1);
reporter->batch.add(r);
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 9b684a0..24454ed 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -82,6 +82,16 @@
virtual IBinder* onAsBinder() override { return nullptr; };
};
+namespace {
+void getHeaderData(const IncidentHeaderProto& headerProto, vector<uint8_t>* out) {
+ out->clear();
+ auto serialized = headerProto.SerializeAsString();
+ if (serialized.empty()) return;
+ out->resize(serialized.length());
+ std::copy(serialized.begin(), serialized.end(), out->begin());
+}
+}
+
TEST_F(SectionTest, HeaderSection) {
HeaderSection hs;
@@ -94,9 +104,15 @@
head1.set_reason("axe");
head2.set_reason("pup");
- args1.addHeader(head1);
- args1.addHeader(head2);
- args2.addHeader(head2);
+ vector<uint8_t> out;
+ getHeaderData(head1, &out);
+ args1.addHeader(out);
+
+ getHeaderData(head2, &out);
+ args1.addHeader(out);
+
+ getHeaderData(head2, &out);
+ args2.addHeader(out);
requests.add(new ReportRequest(args1, new SimpleListener(), -1));
requests.add(new ReportRequest(args2, new SimpleListener(), tf.fd));
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 250f5bf..dd18bd4 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -526,9 +526,10 @@
proto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_ID, (long long)pair.first.GetId());
proto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_UID, pair.first.GetUid());
- vector<const MetricProducer*> acrtiveMetrics;
- pair.second->getActiveMetrics(acrtiveMetrics);
- for (const MetricProducer* metric : acrtiveMetrics) {
+ vector<MetricProducer*> activeMetrics;
+ pair.second->prepForShutDown(currentTimeNs);
+ pair.second->getActiveMetrics(activeMetrics);
+ for (MetricProducer* metric : activeMetrics) {
if (metric->isActive()) {
uint64_t metricToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
FIELD_ID_ACTIVE_METRIC);
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 77d9a2f..caf1a71 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -195,6 +195,7 @@
FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
+ FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1);
FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2);
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index ad5eae3..6b46b8b 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -23,7 +23,6 @@
#include "external/Perfetto.h"
#include "external/Perfprofd.h"
-#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
#include "subscriber/IncidentdReporter.h"
#include "subscriber/SubscriberReporter.h"
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 4f17d69..458e0f5 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -41,12 +41,13 @@
import "frameworks/base/core/proto/android/service/usb.proto";
import "frameworks/base/core/proto/android/stats/enums.proto";
import "frameworks/base/core/proto/android/stats/docsui/docsui_enums.proto";
+import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto";
+import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto";
import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
import "frameworks/base/core/proto/android/telephony/enums.proto";
import "frameworks/base/core/proto/android/view/enums.proto";
-import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto";
-import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto";
+import "frameworks/base/core/proto/android/wifi/enums.proto";
/**
* The master atom class. This message defines all of the available
@@ -214,7 +215,7 @@
SpeechDspStatReported speech_dsp_stat_reported = 145;
UsbContaminantReported usb_contaminant_reported = 146;
WatchdogRollbackOccurred watchdog_rollback_occurred = 147;
- BiometricHalDeathReported biometric_hal_death_reported = 148;
+ BiometricSystemHealthIssueDetected biometric_system_health_issue_detected = 148;
BubbleUIChanged bubble_ui_changed = 149;
ScheduledJobConstraintChanged scheduled_job_constraint_changed = 150;
BluetoothActiveDeviceChanged bluetooth_active_device_changed = 151;
@@ -296,6 +297,7 @@
NumBiometricsEnrolled num_faces_enrolled = 10048;
RoleHolder role_holder = 10049;
DangerousPermissionState dangerous_permission_state = 10050;
+ TrainInfo train_info = 10051;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -994,6 +996,9 @@
ON = 1;
}
optional State state = 2;
+
+ // WifiLock type, from frameworks/base/core/proto/android/wifi/enums.proto.
+ optional android.net.wifi.WifiModeEnum mode = 3;
}
/**
@@ -2082,9 +2087,9 @@
// Salt: Randomly generated 256 bit value
// Hash algorithm: HMAC-SHA256
// Size: 32 byte
- // Default: null or empty if the device identifier is not known
+ // Default: null or empty if this is a server listener socket
optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
- // Port of this socket
+ // Temporary port of this socket for the current connection or session only
// Default 0 when unknown or don't care
optional int32 port = 2;
// Socket type as mentioned in
@@ -2098,6 +2103,14 @@
optional int64 tx_bytes = 5;
// Number of bytes received from remote device during this connection
optional int64 rx_bytes = 6;
+ // Socket owner's UID
+ optional int32 uid = 7 [(is_uid) = true];
+ // Server port of this socket, if any. When both |server_port| and |port| fields are populated,
+ // |port| must be spawned by |server_port|
+ // Default 0 when unknown or don't care
+ optional int32 server_port = 8;
+ // Whether this is a server listener socket
+ optional android.bluetooth.SocketRoleEnum is_server = 9;
}
/**
@@ -3046,13 +3059,15 @@
}
/**
- * Logs when a biometric HAL has crashed.
+ * Logs when a system health issue is detected.
* Logged from:
* frameworks/base/services/core/java/com/android/server/biometrics
*/
-message BiometricHalDeathReported {
+message BiometricSystemHealthIssueDetected {
// Biometric modality.
optional android.hardware.biometrics.ModalityEnum modality = 1;
+ // Type of issue detected.
+ optional android.hardware.biometrics.IssueEnum issue = 2;
}
message Notification {
@@ -5489,3 +5504,20 @@
// True if the package is privileged.
optional bool is_priv_app = 4;
}
+
+/**
+ * Potential experiment ids that goes with a train install.
+ */
+message TrainExperimentIds {
+ repeated int64 experiment_id = 1;
+}
+
+/**
+ * Pulls the ongoing mainline install train version code.
+ * Pulled from StatsCompanionService
+ */
+message TrainInfo {
+ optional int64 train_version_code = 1;
+
+ optional TrainExperimentIds train_experiment_id = 2;
+}
diff --git a/cmds/statsd/src/external/PullDataReceiver.h b/cmds/statsd/src/external/PullDataReceiver.h
index b071682..d2193f4 100644
--- a/cmds/statsd/src/external/PullDataReceiver.h
+++ b/cmds/statsd/src/external/PullDataReceiver.h
@@ -32,9 +32,10 @@
* @param data The pulled data.
* @param pullSuccess Whether the pull succeeded. If the pull does not succeed, the data for the
* bucket should be invalidated.
+ * @param originalPullTimeNs This is when all the pulls have been initiated (elapsed time).
*/
virtual void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data,
- bool pullSuccess) = 0;
+ bool pullSuccess, int64_t originalPullTimeNs) = 0;
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 9b603d6..ecdcd21 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -174,9 +174,12 @@
// Size of specific categories of files. Eg. Music.
{android::util::CATEGORY_SIZE,
{.puller = new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
- // Number of fingerprints registered to each user.
+ // Number of fingerprints enrolled for each user.
{android::util::NUM_FINGERPRINTS_ENROLLED,
{.puller = new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS_ENROLLED)}},
+ // Number of faces enrolled for each user.
+ {android::util::NUM_FACES_ENROLLED,
+ {.puller = new StatsCompanionServicePuller(android::util::NUM_FACES_ENROLLED)}},
// ProcStats.
{android::util::PROC_STATS,
{.puller = new StatsCompanionServicePuller(android::util::PROC_STATS)}},
@@ -381,7 +384,7 @@
for (const auto& receiverInfo : pullInfo.second) {
sp<PullDataReceiver> receiverPtr = receiverInfo->receiver.promote();
if (receiverPtr != nullptr) {
- receiverPtr->onDataPulled(data, pullSuccess);
+ receiverPtr->onDataPulled(data, pullSuccess, elapsedTimeNs);
// We may have just come out of a coma, compute next pull time.
int numBucketsAhead =
(elapsedTimeNs - receiverInfo->nextPullTimeNs) / receiverInfo->intervalNs;
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 37d5ba0..c4034ff 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -423,41 +423,50 @@
mPulledAtomStats[atomId].emptyData++;
}
-void StatsdStats::noteHardDimensionLimitReached(int metricId) {
+void StatsdStats::noteHardDimensionLimitReached(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).hardDimensionLimitReached++;
}
-void StatsdStats::noteLateLogEventSkipped(int metricId) {
+void StatsdStats::noteLateLogEventSkipped(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).lateLogEventSkipped++;
}
-void StatsdStats::noteSkippedForwardBuckets(int metricId) {
+void StatsdStats::noteSkippedForwardBuckets(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).skippedForwardBuckets++;
}
-void StatsdStats::noteBadValueType(int metricId) {
+void StatsdStats::noteBadValueType(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).badValueType++;
}
-void StatsdStats::noteBucketDropped(int metricId) {
+void StatsdStats::noteBucketDropped(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).bucketDropped++;
}
-void StatsdStats::noteConditionChangeInNextBucket(int metricId) {
+void StatsdStats::noteConditionChangeInNextBucket(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).conditionChangeInNextBucket++;
}
-void StatsdStats::noteInvalidatedBucket(int metricId) {
+void StatsdStats::noteInvalidatedBucket(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).invalidatedBucket++;
}
+void StatsdStats::noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayNs) {
+ lock_guard<std::mutex> lock(mLock);
+ AtomMetricStats& pullStats = getAtomMetricStats(metricId);
+ pullStats.maxBucketBoundaryDelayNs =
+ std::max(pullStats.maxBucketBoundaryDelayNs, timeDelayNs);
+ pullStats.minBucketBoundaryDelayNs =
+ std::min(pullStats.minBucketBoundaryDelayNs, timeDelayNs);
+}
+
StatsdStats::AtomMetricStats& StatsdStats::getAtomMetricStats(int metricId) {
auto atomMetricStatsIter = mAtomMetricStats.find(metricId);
if (atomMetricStatsIter != mAtomMetricStats.end()) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 20ea7e5..ea3f3b3 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -342,37 +342,43 @@
/**
* Hard limit was reached in the cardinality of an atom
*/
- void noteHardDimensionLimitReached(int atomId);
+ void noteHardDimensionLimitReached(int64_t metricId);
/**
* A log event was too late, arrived in the wrong bucket and was skipped
*/
- void noteLateLogEventSkipped(int atomId);
+ void noteLateLogEventSkipped(int64_t metricId);
/**
* Buckets were skipped as time elapsed without any data for them
*/
- void noteSkippedForwardBuckets(int atomId);
+ void noteSkippedForwardBuckets(int64_t metricId);
/**
* An unsupported value type was received
*/
- void noteBadValueType(int atomId);
+ void noteBadValueType(int64_t metricId);
/**
* Buckets were dropped due to reclaim memory.
*/
- void noteBucketDropped(int metricId);
+ void noteBucketDropped(int64_t metricId);
/**
* A condition change was too late, arrived in the wrong bucket and was skipped
*/
- void noteConditionChangeInNextBucket(int atomId);
+ void noteConditionChangeInNextBucket(int64_t metricId);
/**
* A bucket has been tagged as invalid.
*/
- void noteInvalidatedBucket(int metricId);
+ void noteInvalidatedBucket(int64_t metricId);
+
+ /**
+ * For pulls at bucket boundaries, it represents the misalignment between the real timestamp and
+ * the end of the bucket.
+ */
+ void noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayNs);
/**
* Reset the historical stats. Including all stats in icebox, and the tracked stats about
@@ -420,6 +426,8 @@
long conditionChangeInNextBucket = 0;
long invalidatedBucket = 0;
long bucketDropped = 0;
+ int64_t minBucketBoundaryDelayNs = 0;
+ int64_t maxBucketBoundaryDelayNs = 0;
} AtomMetricStats;
private:
@@ -503,6 +511,7 @@
FRIEND_TEST(StatsdStatsTest, TestAnomalyMonitor);
FRIEND_TEST(StatsdStatsTest, TestSystemServerCrash);
FRIEND_TEST(StatsdStatsTest, TestPullAtomStats);
+ FRIEND_TEST(StatsdStatsTest, TestAtomMetricsStats);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 2609937..d56a355 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -407,7 +407,7 @@
}
void GaugeMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
- bool pullSuccess) {
+ bool pullSuccess, int64_t originalPullTimeNs) {
std::lock_guard<std::mutex> lock(mMutex);
if (!pullSuccess || allData.size() == 0) {
return;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index d480941..64a1833 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -68,7 +68,7 @@
// Handles when the pulled data arrives.
void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data,
- bool pullSuccess) override;
+ bool pullSuccess, int64_t originalPullTimeNs) override;
// GaugeMetric needs to immediately trigger another pull when we create the partial bucket.
void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index b362e37..495138e 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -107,6 +107,10 @@
if (it == mEventActivationMap.end()) {
return;
}
+ if (mActivationType == MetricActivation::ACTIVATE_ON_BOOT) {
+ it->second.state = ActivationState::kActiveOnBoot;
+ return;
+ }
it->second.activation_ns = elapsedTimestampNs;
it->second.state = ActivationState::kActive;
mIsActive = true;
@@ -116,12 +120,19 @@
if (mEventActivationMap.size() == 0) {
return;
}
- auto& activation = mEventActivationMap.begin()->second;
- activation.activation_ns = currentTimeNs + remainingTtlNs - activation.ttl_ns;
- activation.state = kActive;
- mIsActive = true;
- VLOG("setting new activation time to %lld, %lld, %lld", (long long)activation.activation_ns,
- (long long)currentTimeNs, (long long)remainingTtlNs);
+ for (auto& pair : mEventActivationMap) {
+ auto& activation = pair.second;
+ if (activation.ttl_ns >= remainingTtlNs) {
+ activation.activation_ns = currentTimeNs + remainingTtlNs - activation.ttl_ns;
+ activation.state = kActive;
+ mIsActive = true;
+ VLOG("setting new activation time to %lld, %lld, %lld",
+ (long long)activation.activation_ns, (long long)currentTimeNs,
+ (long long)remainingTtlNs);
+ return;
+ }
+ }
+ ALOGE("Required ttl is longer than all possible activations.");
}
int64_t MetricProducer::getRemainingTtlNsLocked(int64_t currentTimeNs) const {
@@ -135,6 +146,19 @@
return maxTtl;
}
+void MetricProducer::prepActiveForBootIfNecessaryLocked(int64_t currentTimeNs) {
+ if (mActivationType != MetricActivation::ACTIVATE_ON_BOOT) {
+ return;
+ }
+ for (auto& activation : mEventActivationMap) {
+ if (activation.second.state == kActiveOnBoot) {
+ activation.second.state = kActive;
+ activation.second.activation_ns = currentTimeNs;
+ mIsActive = true;
+ }
+ }
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index ca37bbb..849cb76 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -37,12 +37,13 @@
// If the metric has no activation requirement, it will be active once the metric producer is
// created.
// If the metric needs to be activated by atoms, the metric producer will start
-// with kNotActive state, turn to kActive when the activation event arrives, become kNotActive
-// when it reaches the duration limit (timebomb). If the activation event arrives again before
-// or after it expires, the event producer will be re-activated and ttl will be reset.
+// with kNotActive state, turn to kActive or kActiveOnBoot when the activation event arrives, become
+// kNotActive when it reaches the duration limit (timebomb). If the activation event arrives again
+// before or after it expires, the event producer will be re-activated and ttl will be reset.
enum ActivationState {
kNotActive = 0,
kActive = 1,
+ kActiveOnBoot = 2,
};
// A MetricProducer is responsible for compute one single metrics, creating stats log report, and
@@ -218,8 +219,17 @@
return isActiveLocked();
}
+ void prepActiveForBootIfNecessary(int64_t currentTimeNs) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ prepActiveForBootIfNecessaryLocked(currentTimeNs);
+ }
+
void addActivation(int activationTrackerIndex, int64_t ttl_seconds);
+ inline void setActivationType(const MetricActivation::ActivationType& activationType) {
+ mActivationType = activationType;
+ }
+
void flushIfExpire(int64_t elapsedTimestampNs);
protected:
@@ -243,6 +253,8 @@
return mIsActive;
}
+ void prepActiveForBootIfNecessaryLocked(int64_t currentTimeNs);
+
int64_t getRemainingTtlNsLocked(int64_t currentTimeNs) const;
void setActiveLocked(int64_t currentTimeNs, int64_t remainingTtlNs);
@@ -367,9 +379,12 @@
bool mIsActive;
+ MetricActivation::ActivationType mActivationType;
+
FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
+ FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index fdc28ea..cb1cefb 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -132,7 +132,7 @@
return mIsActive;
}
- inline void getActiveMetrics(std::vector<const MetricProducer*>& metrics) const {
+ inline void getActiveMetrics(std::vector<MetricProducer*>& metrics) const {
for (const auto& metric : mAllMetricProducers) {
if (metric->isActive()) {
metrics.push_back(metric.get());
@@ -140,6 +140,12 @@
}
}
+ inline void prepForShutDown(int64_t currentTimeNs) {
+ for (const auto& metric : mAllMetricProducers) {
+ metric->prepActiveForBootIfNecessary(currentTimeNs);
+ }
+ }
+
void setActiveMetrics(ActiveConfig config, int64_t currentTimeNs);
private:
@@ -271,6 +277,7 @@
FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
+ FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 1bd3ef2..ac6c27a 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -361,7 +361,57 @@
invalidateCurrentBucket();
return;
}
- const int64_t pullDelayNs = getElapsedRealtimeNs() - timestampNs;
+
+ accumulateEvents(allData, timestampNs, timestampNs);
+}
+
+int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTimeNs) {
+ return mTimeBaseNs + ((currentTimeNs - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
+}
+
+void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
+ bool pullSuccess, int64_t originalPullTimeNs) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (mCondition) {
+ if (!pullSuccess) {
+ // If the pull failed, we won't be able to compute a diff.
+ invalidateCurrentBucket();
+ return;
+ }
+
+ // For scheduled pulled data, the effective event time is snap to the nearest
+ // bucket end. In the case of waking up from a deep sleep state, we will
+ // attribute to the previous bucket end. If the sleep was long but not very long, we
+ // will be in the immediate next bucket. Previous bucket may get a larger number as
+ // we pull at a later time than real bucket end.
+ // If the sleep was very long, we skip more than one bucket before sleep. In this case,
+ // if the diff base will be cleared and this new data will serve as new diff base.
+ int64_t bucketEndTime = calcPreviousBucketEndTime(originalPullTimeNs) - 1;
+ StatsdStats::getInstance().noteBucketBoundaryDelayNs(
+ mMetricId, originalPullTimeNs - bucketEndTime);
+ accumulateEvents(allData, originalPullTimeNs, bucketEndTime);
+
+ // We can probably flush the bucket. Since we used bucketEndTime when calling
+ // #onMatchedLogEventInternalLocked, the current bucket will not have been flushed.
+ flushIfNeededLocked(originalPullTimeNs);
+
+ } else {
+ VLOG("No need to commit data on condition false.");
+ }
+}
+
+void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
+ int64_t originalPullTimeNs, int64_t eventElapsedTimeNs) {
+ bool isEventLate = eventElapsedTimeNs < mCurrentBucketStartTimeNs;
+ if (isEventLate) {
+ VLOG("Skip bucket end pull due to late arrival: %lld vs %lld",
+ (long long)eventElapsedTimeNs, (long long)mCurrentBucketStartTimeNs);
+ StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
+ invalidateCurrentBucket();
+ return;
+ }
+
+ const int64_t pullDelayNs = getElapsedRealtimeNs() - originalPullTimeNs;
StatsdStats::getInstance().notePullDelay(mPullTagId, pullDelayNs);
if (pullDelayNs > mMaxPullDelayNs) {
ALOGE("Pull finish too late for atom %d, longer than %lld", mPullTagId,
@@ -373,75 +423,33 @@
return;
}
- if (timestampNs < mCurrentBucketStartTimeNs) {
- // The data will be skipped in onMatchedLogEventInternalLocked, but we don't want to report
- // for every event, just the pull
- StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
+ if (allData.size() == 0) {
+ VLOG("Data pulled is empty");
+ StatsdStats::getInstance().noteEmptyData(mPullTagId);
}
+ mMatchedMetricDimensionKeys.clear();
for (const auto& data : allData) {
- // make a copy before doing and changes
LogEvent localCopy = data->makeCopy();
- localCopy.setElapsedTimestampNs(timestampNs);
if (mEventMatcherWizard->matchLogEvent(localCopy, mWhatMatcherIndex) ==
MatchingState::kMatched) {
+ localCopy.setElapsedTimestampNs(eventElapsedTimeNs);
onMatchedLogEventLocked(mWhatMatcherIndex, localCopy);
}
}
- mHasGlobalBase = true;
-}
-
-int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTimeNs) {
- return mTimeBaseNs + ((currentTimeNs - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
-}
-
-void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
- bool pullSuccess) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (mCondition) {
- if (!pullSuccess) {
- // If the pull failed, we won't be able to compute a diff.
- invalidateCurrentBucket();
- return;
- }
-
- if (allData.size() == 0) {
- VLOG("Data pulled is empty");
- StatsdStats::getInstance().noteEmptyData(mPullTagId);
- return;
- }
- // For scheduled pulled data, the effective event time is snap to the nearest
- // bucket end. In the case of waking up from a deep sleep state, we will
- // attribute to the previous bucket end. If the sleep was long but not very long, we
- // will be in the immediate next bucket. Previous bucket may get a larger number as
- // we pull at a later time than real bucket end.
- // If the sleep was very long, we skip more than one bucket before sleep. In this case,
- // if the diff base will be cleared and this new data will serve as new diff base.
- int64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
- int64_t bucketEndTime = calcPreviousBucketEndTime(realEventTime) - 1;
- bool isEventLate = bucketEndTime < mCurrentBucketStartTimeNs;
- if (isEventLate) {
- VLOG("Skip bucket end pull due to late arrival: %lld vs %lld", (long long)bucketEndTime,
- (long long)mCurrentBucketStartTimeNs);
- StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
- }
-
- for (const auto& data : allData) {
- LogEvent localCopy = data->makeCopy();
- if (mEventMatcherWizard->matchLogEvent(localCopy, mWhatMatcherIndex) ==
- MatchingState::kMatched) {
- localCopy.setElapsedTimestampNs(bucketEndTime);
- onMatchedLogEventLocked(mWhatMatcherIndex, localCopy);
+ // If the new pulled data does not contains some keys we track in our intervals, we need to
+ // reset the base.
+ for (auto& slice : mCurrentSlicedBucket) {
+ bool presentInPulledData = mMatchedMetricDimensionKeys.find(slice.first)
+ != mMatchedMetricDimensionKeys.end();
+ if (!presentInPulledData) {
+ for (auto& interval : slice.second) {
+ interval.hasBase = false;
}
}
- mHasGlobalBase = true;
-
- // We can probably flush the bucket. Since we used bucketEndTime when calling
- // #onMatchedLogEventInternalLocked, the current bucket will not have been flushed.
- flushIfNeededLocked(realEventTime);
- } else {
- VLOG("No need to commit data on condition false.");
}
+ mMatchedMetricDimensionKeys.clear();
+ mHasGlobalBase = true;
}
void ValueMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
@@ -539,6 +547,7 @@
(long long)mCurrentBucketStartTimeNs);
return;
}
+ mMatchedMetricDimensionKeys.insert(eventKey);
flushIfNeededLocked(eventTimeNs);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 0cfefa9..d1c2315 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -52,7 +52,7 @@
// Process data pulled on bucket boundary.
void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data,
- bool pullSuccess) override;
+ bool pullSuccess, int64_t originalPullTimeNs) override;
// ValueMetric needs special logic if it's a pulled atom.
void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
@@ -116,6 +116,9 @@
// Value fields for matching.
std::vector<Matcher> mFieldMatchers;
+ // Value fields for matching.
+ std::set<MetricDimensionKey> mMatchedMetricDimensionKeys;
+
// tagId for pulled data. -1 if this is not pulled
const int mPullTagId;
@@ -160,6 +163,9 @@
void pullAndMatchEventsLocked(const int64_t timestampNs);
+ void accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
+ int64_t originalPullTimeNs, int64_t eventElapsedTimeNs);
+
ValueBucket buildPartialBucket(int64_t bucketEndTime,
const std::vector<Interval>& intervals);
void initCurrentSlicedBucket();
@@ -242,6 +248,10 @@
FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed);
FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded);
FRIEND_TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange);
+ FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled);
+ FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged);
+ FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary);
+ FRIEND_TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 180a1ae..463b5a0 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -725,6 +725,8 @@
ALOGE("Invalid metric tracker index.");
return false;
}
+ allMetricProducers[metricTrackerIndex]->setActivationType(
+ metric_activation.activation_type());
metricsWithActivation.push_back(metricTrackerIndex);
for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
const EventActivation& activation = metric_activation.event_activation(j);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 73aab48..6a07a3f 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -419,6 +419,8 @@
optional int64 condition_change_in_next_bucket = 6;
optional int64 invalidated_bucket = 7;
optional int64 bucket_dropped = 8;
+ optional int64 min_bucket_boundary_delay_ns = 9;
+ optional int64 max_bucket_boundary_delay_ns = 10;
}
repeated AtomMetricStats atom_metric_stats = 17;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index f76a9ad..aa8cfc5 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -80,6 +80,8 @@
const int FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET = 6;
const int FIELD_ID_INVALIDATED_BUCKET = 7;
const int FIELD_ID_BUCKET_DROPPED = 8;
+const int FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS = 9;
+const int FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS = 10;
namespace {
@@ -500,6 +502,10 @@
(long long)pair.second.invalidatedBucket);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_DROPPED,
(long long)pair.second.bucketDropped);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS,
+ (long long)pair.second.minBucketBoundaryDelayNs);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS,
+ (long long)pair.second.maxBucketBoundaryDelayNs);
protoOutput->end(token);
}
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 9d3a669..5c6d548 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -379,6 +379,13 @@
message MetricActivation {
optional int64 metric_id = 1;
+ enum ActivationType {
+ UNKNOWN = 0;
+ ACTIVATE_IMMEDIATELY = 1;
+ ACTIVATE_ON_BOOT = 2;
+ }
+ optional ActivationType activation_type = 3;
+
repeated EventActivation event_activation = 2;
}
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
index 6e4b2c8..42cac0c 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -17,32 +17,67 @@
#include "Log.h"
#include "IncidentdReporter.h"
-#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
#include <android/os/IIncidentManager.h>
#include <android/os/IncidentReportArgs.h>
+#include <android/util/ProtoOutputStream.h>
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
+#include <vector>
+
namespace android {
namespace os {
namespace statsd {
+using android::util::ProtoOutputStream;
+using std::vector;
+
+using util::FIELD_TYPE_MESSAGE;
+using util::FIELD_TYPE_INT32;
+using util::FIELD_TYPE_INT64;
+
+// field ids in IncidentHeaderProto
+const int FIELD_ID_ALERT_ID = 1;
+const int FIELD_ID_CONFIG_KEY = 3;
+const int FIELD_ID_CONFIG_KEY_UID = 1;
+const int FIELD_ID_CONFIG_KEY_ID = 2;
+
+namespace {
+void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uint8_t>* protoData) {
+ ProtoOutputStream headerProto;
+ headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_ID, (long long)rule_id);
+ uint64_t token =
+ headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
+ headerProto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_KEY_UID, configKey.GetUid());
+ headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_KEY_ID, (long long)configKey.GetId());
+ headerProto.end(token);
+
+ protoData->resize(headerProto.size());
+ size_t pos = 0;
+ auto iter = headerProto.data();
+ while (iter.readBuffer() != NULL) {
+ size_t toRead = iter.currentToRead();
+ std::memcpy(&((*protoData)[pos]), iter.readBuffer(), toRead);
+ pos += toRead;
+ iter.rp()->move(toRead);
+ }
+}
+} // namespace
+
bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_id,
const ConfigKey& configKey) {
if (config.section_size() == 0) {
VLOG("The alert %lld contains zero section in config(%d,%lld)", (unsigned long long)rule_id,
- configKey.GetUid(), (long long) configKey.GetId());
+ configKey.GetUid(), (long long)configKey.GetId());
return false;
}
IncidentReportArgs incidentReport;
- android::os::IncidentHeaderProto header;
- header.set_alert_id(rule_id);
- header.mutable_config_key()->set_uid(configKey.GetUid());
- header.mutable_config_key()->set_id(configKey.GetId());
- incidentReport.addHeader(header);
+ vector<uint8_t> protoData;
+ getProtoData(rule_id, configKey, &protoData);
+ incidentReport.addHeader(protoData);
for (int i = 0; i < config.section_size(); i++) {
incidentReport.addSection(config.section(i));
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 64008b5..60df165 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -574,6 +574,127 @@
EXPECT_EQ(timeBase2 + ttl6 - activation1006.ttl_ns, activation1003.activation_ns);
}
+TEST(StatsLogProcessorTest, TestActivationOnBoot) {
+ int uid = 1111;
+
+ // Setup a simple config, no activation
+ StatsdConfig config1;
+ config1.set_id(12341);
+ config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+ *config1.add_atom_matcher() = wakelockAcquireMatcher;
+
+ long metricId1 = 1234561;
+ long metricId2 = 1234562;
+ auto countMetric1 = config1.add_count_metric();
+ countMetric1->set_id(metricId1);
+ countMetric1->set_what(wakelockAcquireMatcher.id());
+ countMetric1->set_bucket(FIVE_MINUTES);
+
+ auto countMetric2 = config1.add_count_metric();
+ countMetric2->set_id(metricId2);
+ countMetric2->set_what(wakelockAcquireMatcher.id());
+ countMetric2->set_bucket(FIVE_MINUTES);
+
+ auto metric1Activation = config1.add_metric_activation();
+ metric1Activation->set_metric_id(metricId1);
+ metric1Activation->set_activation_type(MetricActivation::ACTIVATE_ON_BOOT);
+ auto metric1ActivationTrigger = metric1Activation->add_event_activation();
+ metric1ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+ metric1ActivationTrigger->set_ttl_seconds(100);
+
+ ConfigKey cfgKey1(uid, 12341);
+ long timeBase1 = 1;
+ sp<StatsLogProcessor> processor =
+ CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
+
+ EXPECT_EQ(1, processor->mMetricsManagers.size());
+ auto it = processor->mMetricsManagers.find(cfgKey1);
+ EXPECT_TRUE(it != processor->mMetricsManagers.end());
+ auto& metricsManager1 = it->second;
+ EXPECT_TRUE(metricsManager1->isActive());
+
+ auto metricIt = metricsManager1->mAllMetricProducers.begin();
+ for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+ if ((*metricIt)->getMetricId() == metricId1) {
+ break;
+ }
+ }
+ EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+ auto& metricProducer1 = *metricIt;
+ EXPECT_FALSE(metricProducer1->isActive());
+
+ metricIt = metricsManager1->mAllMetricProducers.begin();
+ for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+ if ((*metricIt)->getMetricId() == metricId2) {
+ break;
+ }
+ }
+ EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+ auto& metricProducer2 = *metricIt;
+ EXPECT_TRUE(metricProducer2->isActive());
+
+ const auto& activation1 = metricProducer1->mEventActivationMap.begin()->second;
+ EXPECT_EQ(100 * NS_PER_SEC, activation1.ttl_ns);
+ EXPECT_EQ(0, activation1.activation_ns);
+ EXPECT_EQ(kNotActive, activation1.state);
+
+ std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+ auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+ processor->OnLogEvent(event.get());
+
+ EXPECT_FALSE(metricProducer1->isActive());
+ EXPECT_EQ(0, activation1.activation_ns);
+ EXPECT_EQ(kActiveOnBoot, activation1.state);
+
+ int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+
+ processor->WriteMetricsActivationToDisk(shutDownTime);
+ EXPECT_TRUE(metricProducer1->isActive());
+ int64_t ttl1 = metricProducer1->getRemainingTtlNs(shutDownTime);
+ EXPECT_EQ(100 * NS_PER_SEC, ttl1);
+
+ long timeBase2 = 1000;
+ sp<StatsLogProcessor> processor2 =
+ CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+
+ EXPECT_EQ(1, processor2->mMetricsManagers.size());
+ it = processor2->mMetricsManagers.find(cfgKey1);
+ EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+ auto& metricsManager1001 = it->second;
+ EXPECT_TRUE(metricsManager1001->isActive());
+
+ metricIt = metricsManager1001->mAllMetricProducers.begin();
+ for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+ if ((*metricIt)->getMetricId() == metricId1) {
+ break;
+ }
+ }
+ EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+ auto& metricProducer1001 = *metricIt;
+ EXPECT_FALSE(metricProducer1001->isActive());
+
+ metricIt = metricsManager1001->mAllMetricProducers.begin();
+ for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+ if ((*metricIt)->getMetricId() == metricId2) {
+ break;
+ }
+ }
+ EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+ auto& metricProducer1002 = *metricIt;
+ EXPECT_TRUE(metricProducer1002->isActive());
+
+ const auto& activation1001 = metricProducer1001->mEventActivationMap.begin()->second;
+ EXPECT_EQ(100 * NS_PER_SEC, activation1001.ttl_ns);
+ EXPECT_EQ(0, activation1001.activation_ns);
+ EXPECT_EQ(kNotActive, activation1001.state);
+
+ processor2->LoadMetricsActivationFromDisk();
+
+ EXPECT_TRUE(metricProducer1001->isActive());
+ EXPECT_EQ(timeBase2 + ttl1 - activation1001.ttl_ns, activation1001.activation_ns);
+}
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 6069516..92aa998 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -278,6 +278,39 @@
EXPECT_EQ(3335L, report.pulled_atom_stats(0).max_pull_delay_nanos());
}
+TEST(StatsdStatsTest, TestAtomMetricsStats) {
+ StatsdStats stats;
+ time_t now = time(nullptr);
+ // old event, we get it from the stats buffer. should be ignored.
+ stats.noteBucketDropped(1000L);
+
+ stats.noteBucketBoundaryDelayNs(1000L, -1L);
+ stats.noteBucketBoundaryDelayNs(1000L, -10L);
+ stats.noteBucketBoundaryDelayNs(1000L, 2L);
+
+ stats.noteBucketBoundaryDelayNs(1001L, 1L);
+
+ vector<uint8_t> output;
+ stats.dumpStats(&output, false);
+ StatsdStatsReport report;
+ bool good = report.ParseFromArray(&output[0], output.size());
+ EXPECT_TRUE(good);
+
+ EXPECT_EQ(2, report.atom_metric_stats().size());
+
+ auto atomStats = report.atom_metric_stats(0);
+ EXPECT_EQ(1000L, atomStats.metric_id());
+ EXPECT_EQ(1L, atomStats.bucket_dropped());
+ EXPECT_EQ(-10L, atomStats.min_bucket_boundary_delay_ns());
+ EXPECT_EQ(2L, atomStats.max_bucket_boundary_delay_ns());
+
+ auto atomStats2 = report.atom_metric_stats(1);
+ EXPECT_EQ(1001L, atomStats2.metric_id());
+ EXPECT_EQ(0L, atomStats2.bucket_dropped());
+ EXPECT_EQ(0L, atomStats2.min_bucket_boundary_delay_ns());
+ EXPECT_EQ(1L, atomStats2.max_bucket_boundary_delay_ns());
+}
+
TEST(StatsdStatsTest, TestAnomalyMonitor) {
StatsdStats stats;
stats.noteRegisteredAnomalyAlarmChanged();
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 1725160..6286823 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -133,7 +133,7 @@
event->init();
allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true);
+ gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
EXPECT_EQ(INT, it->mValue.getType());
@@ -151,7 +151,7 @@
event2->write(25);
event2->init();
allData.push_back(event2);
- gaugeProducer.onDataPulled(allData, /** succeed */ true);
+ gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
EXPECT_EQ(INT, it->mValue.getType());
@@ -305,7 +305,7 @@
event->write(1);
event->init();
allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true);
+ gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -328,7 +328,7 @@
event->write(3);
event->init();
allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true);
+ gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
@@ -371,7 +371,7 @@
event->write(1);
event->init();
allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true);
+ gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -440,7 +440,7 @@
event->write(110);
event->init();
allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true);
+ gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
@@ -541,7 +541,7 @@
event->write(110);
event->init();
allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true);
+ gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
@@ -590,7 +590,7 @@
event1->write(13);
event1->init();
- gaugeProducer.onDataPulled({event1}, /** succeed */ true);
+ gaugeProducer.onDataPulled({event1}, /** succeed */ true, bucketStartTimeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -604,7 +604,7 @@
event2->write(15);
event2->init();
- gaugeProducer.onDataPulled({event2}, /** succeed */ true);
+ gaugeProducer.onDataPulled({event2}, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -619,7 +619,7 @@
event3->write(26);
event3->init();
- gaugeProducer.onDataPulled({event3}, /** succeed */ true);
+ gaugeProducer.onDataPulled({event3}, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -633,7 +633,7 @@
std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
event4->write("some value");
event4->init();
- gaugeProducer.onDataPulled({event4}, /** succeed */ true);
+ gaugeProducer.onDataPulled({event4}, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
}
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 91b98ec..ae3cdbc 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -160,7 +160,7 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -178,7 +178,7 @@
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -198,7 +198,7 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -265,7 +265,7 @@
event->write(2);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** success */ true);
+ valueProducer.onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
// Partial buckets created in 2nd bucket.
valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
@@ -327,7 +327,7 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
@@ -346,7 +346,7 @@
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// No new data seen, so data has been cleared.
EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
@@ -363,7 +363,7 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -412,7 +412,7 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -428,7 +428,7 @@
event->write(10);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -445,7 +445,7 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
@@ -493,7 +493,7 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -509,7 +509,7 @@
event->write(10);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -524,7 +524,7 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
@@ -599,7 +599,7 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
@@ -710,7 +710,7 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
@@ -725,7 +725,7 @@
event->write(150);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(20L,
@@ -764,7 +764,7 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
@@ -1068,7 +1068,7 @@
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -1086,7 +1086,7 @@
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -1107,7 +1107,7 @@
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
// startUpdated:false sum:12
@@ -1195,7 +1195,7 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
@@ -1291,7 +1291,7 @@
EXPECT_EQ(20, curInterval.value.long_value);
EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
- // Now the alarm is delivered, but it is considered late, it has no effect
+ // Now the alarm is delivered, but it is considered late, the bucket is invalidated.
vector<shared_ptr<LogEvent>> allData;
allData.clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
@@ -1299,10 +1299,10 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(130, curInterval.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
@@ -1752,7 +1752,7 @@
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
@@ -1842,7 +1842,7 @@
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
@@ -1871,7 +1871,7 @@
event1->write(5);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval2.hasBase);
@@ -1893,7 +1893,7 @@
event2->write(5);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval2.hasBase);
@@ -1968,7 +1968,7 @@
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
@@ -2000,7 +2000,7 @@
event1->write(5);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
// Only one interval left. One was trimmed.
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
@@ -2018,7 +2018,7 @@
event1->write(14);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, interval2.hasBase);
@@ -2078,7 +2078,7 @@
EXPECT_EQ(false, curInterval.hasValue);
vector<shared_ptr<LogEvent>> allData;
- valueProducer.onDataPulled(allData, /** succeed */ false);
+ valueProducer.onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2179,7 +2179,7 @@
valueProducer.mCondition = true;
vector<shared_ptr<LogEvent>> allData;
- valueProducer.onDataPulled(allData, /** succeed */ false);
+ valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
valueProducer.onConditionChanged(false, bucketStartTimeNs + 1);
@@ -2361,7 +2361,7 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
// This will fail and should invalidate the whole bucket since we do not have all the data
// needed to compute the metric value when the screen was on.
@@ -2375,7 +2375,7 @@
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
@@ -2446,7 +2446,7 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ false);
+ valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
valueProducer.onConditionChanged(false, bucketStartTimeNs + 2);
valueProducer.onConditionChanged(true, bucketStartTimeNs + 3);
@@ -2458,7 +2458,7 @@
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
@@ -2529,7 +2529,7 @@
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
// This will fail and should invalidate the whole bucket since we do not have all the data
// needed to compute the metric value when the screen was on.
@@ -2543,7 +2543,7 @@
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ false);
+ valueProducer.onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
@@ -2557,6 +2557,268 @@
EXPECT_EQ(false, valueProducer.mHasGlobalBase);
}
+TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_max_pull_delay_sec(INT_MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Start bucket.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+
+ // Bucket 2 start.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event->write(tagId);
+ event->write(110);
+ event->init();
+ allData.push_back(event);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+
+ // Bucket 3 empty.
+ allData.clear();
+ shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+ event2->init();
+ allData.push_back(event2);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ // Data has been trimmed.
+ EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+}
+
+TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_condition(StringToId("SCREEN_ON"));
+ metric.set_max_pull_delay_sec(INT_MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First onConditionChanged
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval& curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+
+ // Empty pull.
+ valueProducer.onConditionChanged(false, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+}
+
+TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_condition(StringToId("SCREEN_ON"));
+ metric.set_max_pull_delay_sec(INT_MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First onConditionChanged
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(1);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(2);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(5);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
+ valueProducer.onConditionChanged(false, bucketStartTimeNs + 11);
+ valueProducer.onConditionChanged(true, bucketStartTimeNs + 12);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval& curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+
+ // End of bucket
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ // Data is empty, base should be reset.
+ EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(5, curInterval.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+}
+
+
+TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.mutable_dimensions_in_what()->set_field(tagId);
+ metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+ metric.set_condition(StringToId("SCREEN_ON"));
+ metric.set_max_pull_delay_sec(INT_MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First onConditionChanged
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(1);
+ event->write(1);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+
+ // End of bucket
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event->write(2);
+ event->write(2);
+ event->init();
+ allData.push_back(event);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Key 1 should be reset since in not present in the most pull.
+ EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+ auto iterator = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(true, iterator->second[0].hasBase);
+ EXPECT_EQ(2, iterator->second[0].base.long_value);
+ EXPECT_EQ(false, iterator->second[0].hasValue);
+ iterator++;
+ EXPECT_EQ(false, iterator->second[0].hasBase);
+ EXPECT_EQ(1, iterator->second[0].base.long_value);
+ EXPECT_EQ(false, iterator->second[0].hasValue);
+
+ EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/config/hiddenapi-greylist-max-p.txt b/config/hiddenapi-greylist-max-p.txt
index 7840b18..4c643e1 100644
--- a/config/hiddenapi-greylist-max-p.txt
+++ b/config/hiddenapi-greylist-max-p.txt
@@ -48,6 +48,8 @@
Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
Landroid/telephony/CarrierMessagingServiceManager;-><init>()V
+Landroid/view/IGraphicsStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/view/IGraphicsStats$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IGraphicsStats;
Landroid/view/IWindowManager;->setInTouchMode(Z)V
Landroid/view/IWindowManager;->showStrictModeViolation(Z)V
Lcom/android/internal/R$styleable;->AndroidManifestActivityAlias:[I
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index a0d8a12..010e447 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1474,8 +1474,6 @@
Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager;
Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V
Landroid/view/IDockedStackListener$Stub;-><init>()V
-Landroid/view/IGraphicsStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/view/IGraphicsStats$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IGraphicsStats;
Landroid/view/IRecentsAnimationController;->finish(Z)V
Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot;
Landroid/view/IRecentsAnimationController;->setAnimationTargetsBehindSystemBars(Z)V
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 5814e69..ce71998 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -26,6 +26,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Insets;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.os.RemoteException;
@@ -84,6 +85,8 @@
/** The ActivityView is only allowed to contain one task. */
private final boolean mSingleTaskInstance;
+ private Insets mForwardedInsets;
+
@UnsupportedAppUsage
public ActivityView(Context context) {
this(context, null /* attrs */);
@@ -369,11 +372,13 @@
.build();
try {
+ // TODO: Find a way to consolidate these calls to the server.
wm.reparentDisplayContent(displayId, mRootSurfaceControl);
wm.dontOverrideDisplayInfo(displayId);
if (mSingleTaskInstance) {
mActivityTaskManager.setDisplayToSingleTaskInstance(displayId);
}
+ wm.setForwardedInsets(displayId, mForwardedInsets);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
@@ -454,6 +459,24 @@
}
/**
+ * Set forwarded insets on the virtual display.
+ *
+ * @see IWindowManager#setForwardedInsets
+ */
+ public void setForwardedInsets(Insets insets) {
+ mForwardedInsets = insets;
+ if (mVirtualDisplay == null) {
+ return;
+ }
+ try {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ wm.setForwardedInsets(mVirtualDisplay.getDisplay().getDisplayId(), mForwardedInsets);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* A task change listener that detects background color change of the topmost stack on our
* virtual display and updates the background of the surface view. This background will be shown
* when surface view is resized, but the app hasn't drawn its content in new size yet.
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index f522d71..17f645d 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -125,7 +125,7 @@
public static final int RESULT_ALTERNATE = 1;
/**
- * @deprecated see {@link BiometricPrompt.Builder#setEnableFallback(boolean)}
+ * @deprecated see {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)}
*
* Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics
* if enrolled) for the current user of the device. The caller is expected to launch this
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 028e3ef..dc4f343 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8243,6 +8243,7 @@
private void buildIntoRemoteViewContent(RemoteViews remoteViews,
RemoteViews customContent, TemplateBindResult result) {
+ int childIndex = -1;
if (customContent != null) {
// Need to clone customContent before adding, because otherwise it can no longer be
// parceled independently of remoteViews.
@@ -8250,7 +8251,11 @@
remoteViews.removeAllViewsExceptId(R.id.notification_main_column, R.id.progress);
remoteViews.addView(R.id.notification_main_column, customContent, 0 /* index */);
remoteViews.addFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED);
+ childIndex = 0;
}
+ remoteViews.setIntTag(R.id.notification_main_column,
+ com.android.internal.R.id.notification_custom_view_index_tag,
+ childIndex);
// also update the end margin if there is an image
Resources resources = mBuilder.mContext.getResources();
int endMargin = resources.getDimensionPixelSize(
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index 78ec8a1..65859c7 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -6,5 +6,13 @@
{
"path": "frameworks/base/services/core/java/com/android/server/wm"
}
+ ],
+ "presubmit": [
+ {
+ "name": "CtsFragmentTestCases"
+ },
+ {
+ "name": "CtsFragmentTestCasesSdk26"
+ }
]
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3ff6973..8861151 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4618,6 +4618,10 @@
* <p>If the installer must have access to the credentials, call
* {@link #installKeyPair(ComponentName, PrivateKey, Certificate[], String, boolean)} instead.
*
+ * <p>Note: If the provided {@code alias} is of an existing alias, all former grants that apps
+ * have been given to access the key and certificates associated with this alias will be
+ * revoked.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
* {@code null} if calling from a delegated certificate installer.
* @param privKey The private key to install.
@@ -4645,6 +4649,10 @@
* immediately, without user approval. It is a best practice not to request this unless strictly
* necessary since it opens up additional security vulnerabilities.
*
+ * <p>Note: If the provided {@code alias} is of an existing alias, all former grants that apps
+ * have been given to access the key and certificates associated with this alias will be
+ * revoked.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
* {@code null} if calling from a delegated certificate installer.
* @param privKey The private key to install.
@@ -4685,6 +4693,10 @@
* <p>Include {@link #INSTALLKEY_SET_USER_SELECTABLE} in the {@code flags} argument to allow
* the user to select the key from a dialog.
*
+ * <p>Note: If the provided {@code alias} is of an existing alias, all former grants that apps
+ * have been given to access the key and certificates associated with this alias will be
+ * revoked.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
* {@code null} if calling from a delegated certificate installer.
* @param privKey The private key to install.
@@ -4761,6 +4773,10 @@
* <p>Because this method might take several seconds to complete, it should only be called from
* a worker thread. This method returns {@code null} when called from the main thread.
*
+ * <p>Note: If the provided {@code alias} is of an existing alias, all former grants that apps
+ * have been given to access the key and certificates associated with this alias will be
+ * revoked.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
* {@code null} if calling from a delegated certificate installer.
* @param algorithm The key generation algorithm, see {@link java.security.KeyPairGenerator}.
@@ -9628,7 +9644,7 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param enabled {@code true} to enable the backup service, {@code false} to disable it.
- * @throws SecurityException if {@code admin} is not a device owner.
+ * @throws SecurityException if {@code admin} is not a device owner or a profile owner.
*/
public void setBackupServiceEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setBackupServiceEnabled");
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index fa2a6a1..edd3ef98 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -69,6 +69,22 @@
private static final String LOG_TAG = RoleManager.class.getSimpleName();
/**
+ * The name of the assistant app role.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final String ROLE_ASSISTANT = "android.app.role.ASSISTANT";
+
+ /**
+ * The name of the browser role.
+ *
+ * @see Intent#CATEGORY_APP_BROWSER
+ */
+ public static final String ROLE_BROWSER = "android.app.role.BROWSER";
+
+ /**
* The name of the dialer role.
*
* @see Intent#ACTION_DIAL
@@ -83,25 +99,11 @@
public static final String ROLE_SMS = "android.app.role.SMS";
/**
- * The name of the browser role.
+ * The name of the emergency role
*
- * @see Intent#CATEGORY_APP_BROWSER
+ * @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE
*/
- public static final String ROLE_BROWSER = "android.app.role.BROWSER";
-
- /**
- * The name of the gallery role.
- *
- * @see Intent#CATEGORY_APP_GALLERY
- */
- public static final String ROLE_GALLERY = "android.app.role.GALLERY";
-
- /**
- * The name of the music player role.
- *
- * @see Intent#CATEGORY_APP_MUSIC
- */
- public static final String ROLE_MUSIC = "android.app.role.MUSIC";
+ public static final String ROLE_EMERGENCY = "android.app.role.EMERGENCY";
/**
* The name of the home role.
@@ -111,11 +113,18 @@
public static final String ROLE_HOME = "android.app.role.HOME";
/**
- * The name of the emergency role
+ * The name of the music player role.
*
- * @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE
+ * @see Intent#CATEGORY_APP_MUSIC
*/
- public static final String ROLE_EMERGENCY = "android.app.role.EMERGENCY";
+ public static final String ROLE_MUSIC = "android.app.role.MUSIC";
+
+ /**
+ * The name of the gallery role.
+ *
+ * @see Intent#CATEGORY_APP_GALLERY
+ */
+ public static final String ROLE_GALLERY = "android.app.role.GALLERY";
/**
* The name of the car mode dialer app role.
@@ -131,20 +140,20 @@
* TODO: STOPSHIP: Make name of required roles public API
* @hide
*/
- public static final String ROLE_CAR_MODE_DIALER_APP = "android.app.role.CAR_MODE_DIALER_APP";
+ public static final String ROLE_CAR_MODE_DIALER = "android.app.role.CAR_MODE_DIALER";
/**
- * The name of the proxy calling role.
+ * The name of the call redirection role.
* <p>
- * A proxy calling app provides a means to re-write the phone number for an outgoing call to
- * place the call through a proxy calling service.
+ * A call redirection app provides a means to re-write the phone number for an outgoing call to
+ * place the call through a call redirection service.
*
* @see android.telecom.CallRedirectionService
*
* TODO: STOPSHIP: Make name of required roles public API
* @hide
*/
- public static final String ROLE_PROXY_CALLING_APP = "android.app.role.PROXY_CALLING_APP";
+ public static final String ROLE_CALL_REDIRECTION = "android.app.role.CALL_REDIRECTION";
/**
* The name of the call screening and caller id role.
@@ -154,7 +163,7 @@
* TODO: STOPSHIP: Make name of required roles public API
* @hide
*/
- public static final String ROLE_CALL_SCREENING_APP = "android.app.role.CALL_SCREENING_APP";
+ public static final String ROLE_CALL_SCREENING = "android.app.role.CALL_SCREENING";
/**
* The name of the call companion app role.
@@ -170,16 +179,7 @@
* TODO: STOPSHIP: Make name of required roles public API
* @hide
*/
- public static final String ROLE_CALL_COMPANION_APP = "android.app.role.CALL_COMPANION_APP";
-
- /**
- * The name of the assistant app role.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- public static final String ROLE_ASSISTANT = "android.app.role.ASSISTANT";
+ public static final String ROLE_CALL_COMPANION = "android.app.role.CALL_COMPANION";
/**
* @hide
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 51397a2..dc5bdc6 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -745,7 +745,11 @@
* Registering an {@code observerId} that was already registered will override the previous one.
* No more than 1000 unique {@code observerId} may be registered by a single uid
* at any one time.
- * A limit may be unregistered via {@link #unregisterAppUsageLimitObserver}
+ * A limit is not cleared when the usage time is exceeded. It needs to be unregistered via
+ * {@link #unregisterAppUsageLimitObserver}.
+ * <p>
+ * Note: usage limits are not persisted in the system and are cleared on reboots. Callers
+ * must reset any limits that they need on reboots.
* <p>
* This method is similar to {@link #registerAppUsageObserver}, but the usage limit set here
* will be visible to the launcher so that it can report the limit to the user and how much
@@ -757,12 +761,15 @@
* @param observedEntities The list of packages and token to observe for usage time. Cannot be
* null and must include at least one package or token.
* @param timeLimit The total time the set of apps can be in the foreground before the
- * callbackIntent is delivered. Must be at least one minute.
+ * callbackIntent is delivered. Must be at least one minute. Note: a limit of
+ * 0 can be set to indicate that the user has already exhausted the limit for
+ * a group, in which case, the given {@code callbackIntent} will be ignored.
* @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
- * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is
+ * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is
* exceeded by the group of apps. The delivered Intent will also contain
* the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and
- * {@link #EXTRA_TIME_USED}. Cannot be null.
+ * {@link #EXTRA_TIME_USED}. Cannot be {@code null} unless the observer is
+ * being registered with a {@code timeLimit} of 0.
* @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE
* permissions.
* @hide
@@ -772,7 +779,7 @@
android.Manifest.permission.SUSPEND_APPS,
android.Manifest.permission.OBSERVE_APP_USAGE})
public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities,
- long timeLimit, @NonNull TimeUnit timeUnit, @NonNull PendingIntent callbackIntent) {
+ long timeLimit, @NonNull TimeUnit timeUnit, PendingIntent callbackIntent) {
try {
mService.registerAppUsageLimitObserver(observerId, observedEntities,
timeUnit.toMillis(timeLimit), callbackIntent, mContext.getOpPackageName());
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index b27c5dc..6c6fcb2 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -650,6 +650,18 @@
*/
public static final int PRIVATE_FLAG_USE_EMBEDDED_DEX = 1 << 25;
+ /**
+ * Value for {@link #privateFlags}: indicates whether this application's data will be cleared
+ * on a failed restore.
+ *
+ * <p>Comes from the
+ * android.R.styleable#AndroidManifestApplication_allowClearUserDataOnFailedRestore attribute
+ * of the <application> tag.
+ *
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE = 1 << 26;
+
/** @hide */
@IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -676,6 +688,7 @@
PRIVATE_FLAG_VENDOR,
PRIVATE_FLAG_VIRTUAL_PRELOAD,
PRIVATE_FLAG_HAS_FRAGILE_USER_DATA,
+ PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApplicationInfoPrivateFlags {}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 6e52b33..eaf6c5a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -715,7 +715,6 @@
INSTALL_FORCE_PERMISSION_PROMPT,
INSTALL_INSTANT_APP,
INSTALL_DONT_KILL_APP,
- INSTALL_FORCE_SDK,
INSTALL_FULL_APP,
INSTALL_ALLOCATE_AGGRESSIVE,
INSTALL_VIRTUAL_PRELOAD,
@@ -816,15 +815,6 @@
public static final int INSTALL_DONT_KILL_APP = 0x00001000;
/**
- * Flag parameter for {@link #installPackage} to indicate that this package is an
- * upgrade to a package that refers to the SDK via release letter or is targeting an SDK via
- * release letter that the current build does not support.
- *
- * @hide
- */
- public static final int INSTALL_FORCE_SDK = 0x00002000;
-
- /**
* Flag parameter for {@link #installPackage} to indicate that this package is
* to be installed as a heavy weight app. This is fundamentally the opposite of
* {@link #INSTALL_INSTANT_APP}.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 5020a94..0abd5ea 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -839,7 +839,6 @@
public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
public static final int PARSE_ENFORCE_CODE = 1 << 6;
- public static final int PARSE_FORCE_SDK = 1 << 7;
public static final int PARSE_CHATTY = 1 << 31;
@IntDef(flag = true, prefix = { "PARSE_" }, value = {
@@ -847,7 +846,6 @@
PARSE_COLLECT_CERTIFICATES,
PARSE_ENFORCE_CODE,
PARSE_EXTERNAL_STORAGE,
- PARSE_FORCE_SDK,
PARSE_IGNORE_PROCESSES,
PARSE_IS_SYSTEM_DIR,
PARSE_MUST_BE_APK,
@@ -2684,8 +2682,6 @@
* @param platformSdkCodenames array of allowed pre-release SDK codenames
* for this platform
* @param outError output array to populate with error, if applicable
- * @param forceCurrentDev if development target code is not available, use the current
- * development version by default.
* @return the targetSdkVersion to use at runtime, or -1 if the package is
* not compatible with this platform
* @hide Exposed for unit testing only.
@@ -2693,7 +2689,7 @@
@TestApi
public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
@Nullable String targetCode, @NonNull String[] platformSdkCodenames,
- @NonNull String[] outError, boolean forceCurrentDev) {
+ @NonNull String[] outError) {
// If it's a release SDK, return the version number unmodified.
if (targetCode == null) {
return targetVers;
@@ -2701,7 +2697,7 @@
// If it's a pre-release SDK and the codename matches this platform, it
// definitely targets this SDK.
- if (matchTargetCode(platformSdkCodenames, targetCode) || forceCurrentDev) {
+ if (matchTargetCode(platformSdkCodenames, targetCode)) {
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
@@ -2768,9 +2764,8 @@
return null;
}
- boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
final int targetSdkVersion = computeTargetSdkVersion(targetVers,
- targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
+ targetCode, SDK_CODENAMES, outError);
if (targetSdkVersion < 0) {
return null;
}
@@ -3752,6 +3747,13 @@
ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
}
+ if (sa.getBoolean(
+ com.android.internal.R.styleable
+ .AndroidManifestApplication_allowClearUserDataOnFailedRestore,
+ true)) {
+ ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE;
+ }
+
ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
ai.minAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0);
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index faf17e0..49b4cb0 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -47,6 +47,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Map;
/**
* Provides access to an application's raw asset files; see {@link Resources}
@@ -1345,6 +1346,17 @@
}
}
+ /**
+ * @hide
+ */
+ @GuardedBy("this")
+ public @Nullable Map<String, String> getOverlayableMap(String packageName) {
+ synchronized (this) {
+ ensureValidLocked();
+ return nativeGetOverlayableMap(mObject, packageName);
+ }
+ }
+
@GuardedBy("this")
private void incRefsLocked(long id) {
if (DEBUG_REFS) {
@@ -1462,6 +1474,8 @@
private static native void nativeVerifySystemIdmaps();
private static native String[] nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
+ private static native @Nullable Map nativeGetOverlayableMap(long ptr,
+ @NonNull String packageName);
// Global debug native methods.
/**
diff --git a/core/java/android/debug/AdbManagerInternal.java b/core/java/android/debug/AdbManagerInternal.java
index 4469f0f..51eb7fc 100644
--- a/core/java/android/debug/AdbManagerInternal.java
+++ b/core/java/android/debug/AdbManagerInternal.java
@@ -16,6 +16,8 @@
package android.debug;
+import java.io.File;
+
/**
* This class allows the control of ADB-related functions that should only be called from the system
* server.
@@ -41,4 +43,14 @@
* Returns {@code true} if ADB debugging is enabled.
*/
public abstract boolean isAdbEnabled();
+
+ /**
+ * Returns the file that contains all of the ADB keys used by the device.
+ */
+ public abstract File getAdbKeysFile();
+
+ /**
+ * Returns the file that contains all of the ADB keys and their last used time.
+ */
+ public abstract File getAdbTempKeysFile();
}
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index c814b7c..1cb7eb0 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -17,6 +17,7 @@
package android.hardware.biometrics;
import android.annotation.UnsupportedAppUsage;
+import android.app.KeyguardManager;
/**
@@ -126,6 +127,13 @@
int BIOMETRIC_ERROR_NEGATIVE_BUTTON = 13;
/**
+ * The device does not have pin, pattern, or password set up. See
+ * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+ * {@link KeyguardManager#isDeviceSecure()}
+ */
+ int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
+
+ /**
* @hide
*/
@UnsupportedAppUsage
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index b708ef1..459ec62 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -16,6 +16,7 @@
package android.hardware.biometrics;
+import android.app.KeyguardManager;
import android.hardware.face.FaceManager;
/**
@@ -134,6 +135,13 @@
public static final int FACE_ERROR_NEGATIVE_BUTTON = 13;
/**
+ * The device does not have pin, pattern, or password set up. See
+ * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+ * {@link KeyguardManager#isDeviceSecure()}
+ */
+ public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
+
+ /**
* @hide
*/
public static final int FACE_ERROR_VENDOR_BASE = 1000;
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 041b2e6..6cbab47 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -17,6 +17,7 @@
package android.hardware.biometrics;
import android.annotation.UnsupportedAppUsage;
+import android.app.KeyguardManager;
import android.hardware.fingerprint.FingerprintManager;
/**
@@ -119,6 +120,14 @@
public static final int FINGERPRINT_ERROR_NEGATIVE_BUTTON = 13;
/**
+ * The device does not have pin, pattern, or password set up. See
+ * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+ * {@link KeyguardManager#isDeviceSecure()}
+ * @hide
+ */
+ public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
+
+ /**
* @hide
*/
@UnsupportedAppUsage
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index d569a78..baf972b 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.app.KeyguardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Binder;
@@ -80,7 +81,7 @@
/**
* @hide
*/
- public static final String KEY_ENABLE_FALLBACK = "enable_fallback";
+ public static final String KEY_ALLOW_DEVICE_CREDENTIAL = "allow_device_credential";
/**
* Error/help message will show for this amount of time.
@@ -203,7 +204,8 @@
* "Cancel" button, but may be also used to show an alternative method for authentication,
* such as screen that asks for a backup password.
*
- * Note that this should not be set if {@link #setEnableFallback(boolean)} is set to true.
+ * Note that this should not be set if {@link #setAllowDeviceCredential(boolean)
+ * is set to true.
*
* @param text
* @return
@@ -250,7 +252,10 @@
/**
* The user will first be prompted to authenticate with biometrics, but also given the
- * option to authenticate with their device PIN, pattern, or password.
+ * option to authenticate with their device PIN, pattern, or password. Developers should
+ * first check {@link KeyguardManager#isDeviceSecure()} before enabling this. If the device
+ * is not secure, {@link BiometricPrompt#BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL} will be
+ * returned in {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)}}
*
* Note that {@link #setNegativeButton(CharSequence, Executor,
* DialogInterface.OnClickListener)} should not be set if this is set to true.
@@ -259,8 +264,8 @@
* credentials (PIN, pattern, or password).
* @return
*/
- public Builder setEnableFallback(boolean enable) {
- mBundle.putBoolean(KEY_ENABLE_FALLBACK, enable);
+ public Builder setAllowDeviceCredential(boolean enable) {
+ mBundle.putBoolean(KEY_ALLOW_DEVICE_CREDENTIAL, enable);
return this;
}
@@ -273,7 +278,7 @@
final CharSequence title = mBundle.getCharSequence(KEY_TITLE);
final CharSequence negative = mBundle.getCharSequence(KEY_NEGATIVE_TEXT);
final boolean useDefaultTitle = mBundle.getBoolean(KEY_USE_DEFAULT_TITLE);
- final boolean enableFallback = mBundle.getBoolean(KEY_ENABLE_FALLBACK);
+ final boolean enableFallback = mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL);
if (TextUtils.isEmpty(title) && !useDefaultTitle) {
throw new IllegalArgumentException("Title must be set and non-empty");
@@ -281,7 +286,7 @@
throw new IllegalArgumentException("Negative text must be set and non-empty");
} else if (!TextUtils.isEmpty(negative) && enableFallback) {
throw new IllegalArgumentException("Can't have both negative button behavior"
- + " and fallback enabled");
+ + " and device credential enabled");
}
return new BiometricPrompt(mContext, mBundle, mPositiveButtonInfo, mNegativeButtonInfo);
}
@@ -541,8 +546,8 @@
if (callback == null) {
throw new IllegalArgumentException("Must supply a callback");
}
- if (mBundle.getBoolean(KEY_ENABLE_FALLBACK)) {
- throw new IllegalArgumentException("Fallback not supported with crypto");
+ if (mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL)) {
+ throw new IllegalArgumentException("Device credential not supported with crypto");
}
authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
}
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index e4336d1..a20e2bf 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -54,7 +54,7 @@
// TODO(b/123378871): Remove when moved.
// CDCA needs to send results to BiometricService if it was invoked using BiometricPrompt's
- // setEnableFallback method, since there's no way for us to intercept onActivityResult.
+ // setAllowDeviceCredential method, since there's no way for us to intercept onActivityResult.
// CDCA is launched from BiometricService (startActivityAsUser) instead of *ForResult.
void onConfirmDeviceCredentialSuccess();
// TODO(b/123378871): Remove when moved.
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
index 27f0b04..f413d7c 100644
--- a/core/java/android/hardware/display/ColorDisplayManager.java
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -365,6 +365,17 @@
}
/**
+ * Gets whether or not a non-default saturation level is currently applied to the display.
+ *
+ * @return {@code true} if the display is not at full saturation
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
+ public boolean isSaturationActivated() {
+ return mManager.isSaturationActivated();
+ }
+
+ /**
* Set the level of color saturation to apply to a specific app.
*
* @param packageName the package name of the app whose windows should be desaturated
@@ -588,6 +599,14 @@
}
}
+ boolean isSaturationActivated() {
+ try {
+ return mCdm.isSaturationActivated();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
boolean setAppSaturationLevel(String packageName, int saturationLevel) {
try {
return mCdm.setAppSaturationLevel(packageName, saturationLevel);
diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl
index 30e76cf..88b59a6 100644
--- a/core/java/android/hardware/display/IColorDisplayManager.aidl
+++ b/core/java/android/hardware/display/IColorDisplayManager.aidl
@@ -24,6 +24,7 @@
boolean setSaturationLevel(int saturationLevel);
boolean setAppSaturationLevel(String packageName, int saturationLevel);
+ boolean isSaturationActivated();
int getTransformCapabilities();
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index c9a7830..efe24e5 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -565,16 +565,16 @@
*/
public static String getErrorString(Context context, int errMsg, int vendorCode) {
switch (errMsg) {
- case FACE_ERROR_UNABLE_TO_PROCESS:
- return context.getString(
- com.android.internal.R.string.face_error_unable_to_process);
case FACE_ERROR_HW_UNAVAILABLE:
return context.getString(
com.android.internal.R.string.face_error_hw_not_available);
- case FACE_ERROR_NO_SPACE:
- return context.getString(com.android.internal.R.string.face_error_no_space);
+ case FACE_ERROR_UNABLE_TO_PROCESS:
+ return context.getString(
+ com.android.internal.R.string.face_error_unable_to_process);
case FACE_ERROR_TIMEOUT:
return context.getString(com.android.internal.R.string.face_error_timeout);
+ case FACE_ERROR_NO_SPACE:
+ return context.getString(com.android.internal.R.string.face_error_no_space);
case FACE_ERROR_CANCELED:
return context.getString(com.android.internal.R.string.face_error_canceled);
case FACE_ERROR_LOCKOUT:
@@ -629,6 +629,24 @@
return context.getString(R.string.face_acquired_poor_gaze);
case FACE_ACQUIRED_NOT_DETECTED:
return context.getString(R.string.face_acquired_not_detected);
+ case FACE_ACQUIRED_TOO_MUCH_MOTION:
+ return context.getString(R.string.face_acquired_too_much_motion);
+ case FACE_ACQUIRED_RECALIBRATE:
+ return context.getString(R.string.face_acquired_recalibrate);
+ case FACE_ACQUIRED_TOO_DIFFERENT:
+ return context.getString(R.string.face_acquired_too_different);
+ case FACE_ACQUIRED_TOO_SIMILAR:
+ return context.getString(R.string.face_acquired_too_similar);
+ case FACE_ACQUIRED_PAN_TOO_EXTREME:
+ return context.getString(R.string.face_acquired_pan_too_extreme);
+ case FACE_ACQUIRED_TILT_TOO_EXTREME:
+ return context.getString(R.string.face_acquired_tilt_too_extreme);
+ case FACE_ACQUIRED_ROLL_TOO_EXTREME:
+ return context.getString(R.string.face_acquired_roll_too_extreme);
+ case FACE_ACQUIRED_FACE_OBSCURED:
+ return context.getString(R.string.face_acquired_obscured);
+ case FACE_ACQUIRED_START:
+ return null;
case FACE_ACQUIRED_VENDOR: {
String[] msgArray = context.getResources().getStringArray(
R.array.face_acquired_vendor);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index bb98211..80d404d 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -949,17 +949,17 @@
*/
public static String getErrorString(Context context, int errMsg, int vendorCode) {
switch (errMsg) {
+ case FINGERPRINT_ERROR_HW_UNAVAILABLE:
+ return context.getString(
+ com.android.internal.R.string.fingerprint_error_hw_not_available);
case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
return context.getString(
com.android.internal.R.string.fingerprint_error_unable_to_process);
- case FINGERPRINT_ERROR_HW_UNAVAILABLE:
- return context.getString(
- com.android.internal.R.string.fingerprint_error_hw_not_available);
+ case FINGERPRINT_ERROR_TIMEOUT:
+ return context.getString(com.android.internal.R.string.fingerprint_error_timeout);
case FINGERPRINT_ERROR_NO_SPACE:
return context.getString(
com.android.internal.R.string.fingerprint_error_no_space);
- case FINGERPRINT_ERROR_TIMEOUT:
- return context.getString(com.android.internal.R.string.fingerprint_error_timeout);
case FINGERPRINT_ERROR_CANCELED:
return context.getString(com.android.internal.R.string.fingerprint_error_canceled);
case FINGERPRINT_ERROR_LOCKOUT:
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 629289b..0384faa 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1093,6 +1093,12 @@
return buildUniqueFileWithExtension(parent, parts[0], parts[1]);
}
+ /** {@hide} */
+ public static File buildNonUniqueFile(File parent, String mimeType, String displayName) {
+ final String[] parts = splitFileName(mimeType, displayName);
+ return buildFile(parent, parts[0], parts[1]);
+ }
+
/**
* Generates a unique file name under the given parent directory, keeping
* any extension intact.
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index d2ab053..9e97e37 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -526,11 +526,12 @@
@Nullable String packageName,
@Nullable String[] packagesForUid,
@Nullable String[] visibleVols,
+ @Nullable String sandboxId,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
- packagesForUid, visibleVols, /*useBlastulaPool=*/ true, zygoteArgs);
+ packagesForUid, visibleVols, sandboxId, /*useBlastulaPool=*/ true, zygoteArgs);
}
/** @hide */
@@ -547,11 +548,12 @@
@Nullable String packageName,
@Nullable String[] packagesForUid,
@Nullable String[] visibleVols,
+ @Nullable String sandboxId,
@Nullable String[] zygoteArgs) {
return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
- packagesForUid, visibleVols, /*useBlastulaPool=*/ false, zygoteArgs);
+ packagesForUid, visibleVols, sandboxId, /*useBlastulaPool=*/ false, zygoteArgs);
}
/**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index e94ad2b..ee3d354 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -324,13 +324,15 @@
@Nullable String packageName,
@Nullable String[] packagesForUid,
@Nullable String[] visibleVols,
+ @Nullable String sandboxId,
boolean useBlastulaPool,
@Nullable String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/false,
- packageName, packagesForUid, visibleVols, useBlastulaPool, zygoteArgs);
+ packageName, packagesForUid, visibleVols, sandboxId,
+ useBlastulaPool, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -541,6 +543,7 @@
@Nullable String packageName,
@Nullable String[] packagesForUid,
@Nullable String[] visibleVols,
+ @Nullable String sandboxId,
boolean useBlastulaPool,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
@@ -639,6 +642,10 @@
argsForZygote.add(sb.toString());
}
+ if (sandboxId != null) {
+ argsForZygote.add("--sandbox-id=" + sandboxId);
+ }
+
argsForZygote.add(processClass);
if (extraArgs != null) {
@@ -1014,7 +1021,7 @@
gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
true /* startChildZygote */, null /* packageName */,
- null /* packagesForUid */, null /* visibleVolumes */,
+ null /* packagesForUid */, null /* visibleVolumes */, null /* sandboxId */,
false /* useBlastulaPool */, extraArgs);
} catch (ZygoteStartFailedEx ex) {
throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index f521c68..03b2c2c 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -132,4 +132,9 @@
* @param listener The listener that will be notified on reset events.
*/
public abstract void addResetListener(ResetListener listener);
+
+ /**
+ * Return the sandboxId for the given package on external storage.
+ */
+ public abstract String getSandboxId(String packageName);
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 8e7906e..8254e33 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -72,45 +72,13 @@
public static final String NAMESPACE_AUTOFILL = "autofill";
/**
- * ContentCapture-related properties definitions.
- *
- * @hide
- */
- @SystemApi
- public interface ContentCapture {
- String NAMESPACE = "content_capture";
-
- /**
- * Property used by {@code com.android.server.SystemServer} on start to decide whether
- * the Content Capture service should be created or not.
- *
- * <p>Possible values are:
- *
- * <ul>
- * <li>If set to {@code default}, it will only be set if the OEM provides and defines the
- * service name by overlaying {@code config_defaultContentCaptureService} (this is the
- * "default" mode)
- * <li>If set to {@code always}, it will always be enabled, even when the resource is not
- * overlaid (this is useful during development and to run the CTS tests on AOSP builds).
- * <li>Otherwise, it's explicitly disabled (this could work as a "kill switch" so OEMs
- * can disable it remotely in case of emergency by setting to something else (like
- * {@code "false"}); notice that it's also disabled if the OEM doesn't explicitly set one
- * of the values above).
- * </ul>
- *
- * @hide
- */
- // TODO(b/121153631): revert back to SERVICE_EXPLICITLY_ENABLED approach
- String PROPERTY_CONTENTCAPTURE_ENABLED = "enable_contentcapture";
- }
-
- /**
* Namespace for content capture feature used by on-device machine intelligence
* to provide suggestions in a privacy-safe manner.
*
* @hide
*/
@SystemApi
+ @TestApi
public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
/**
@@ -340,6 +308,25 @@
String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled";
}
+ /**
+ * Namespace for system scheduler related features. These features will be applied
+ * immediately upon change.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface Scheduler {
+ String NAMESPACE = "scheduler";
+
+ /**
+ * Flag for enabling fast metrics collection in system scheduler.
+ * A flag value of '' or '0' means the fast metrics collection is not
+ * enabled. Otherwise fast metrics collection is enabled and flag value
+ * is the order id.
+ */
+ String ENABLE_FAST_METRICS_COLLECTION = "enable_fast_metrics_collection";
+ }
+
private static final Object sLock = new Object();
@GuardedBy("sLock")
private static Map<OnPropertyChangedListener, Pair<String, Executor>> sListeners =
@@ -360,6 +347,7 @@
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(READ_DEVICE_CONFIG)
public static String getProperty(String namespace, String name) {
ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 67c8400..0b38420 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -157,10 +157,6 @@
public static final String PARAM_DELETE_DATA = "deletedata";
/** {@hide} */
- public static final String PARAM_PRIMARY = "primary";
- /** {@hide} */
- public static final String PARAM_SECONDARY = "secondary";
- /** {@hide} */
public static final String PARAM_INCLUDE_PENDING = "includePending";
/** {@hide} */
public static final String PARAM_INCLUDE_TRASHED = "includeTrashed";
@@ -543,7 +539,9 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
+ * @removed
*/
+ @Deprecated
public static @NonNull Uri setIncludeTrashed(@NonNull Uri uri) {
return uri.buildUpon().appendQueryParameter(PARAM_INCLUDE_TRASHED, "1").build();
}
@@ -580,14 +578,7 @@
*/
public static @NonNull Uri createPending(@NonNull Context context,
@NonNull PendingParams params) {
- final Uri.Builder builder = params.insertUri.buildUpon();
- if (!TextUtils.isEmpty(params.primaryDirectory)) {
- builder.appendQueryParameter(PARAM_PRIMARY, params.primaryDirectory);
- }
- if (!TextUtils.isEmpty(params.secondaryDirectory)) {
- builder.appendQueryParameter(PARAM_SECONDARY, params.secondaryDirectory);
- }
- return context.getContentResolver().insert(builder.build(), params.insertValues);
+ return context.getContentResolver().insert(params.insertUri, params.insertValues);
}
/**
@@ -610,10 +601,6 @@
public final Uri insertUri;
/** {@hide} */
public final ContentValues insertValues;
- /** {@hide} */
- public String primaryDirectory;
- /** {@hide} */
- public String secondaryDirectory;
/**
* Create parameters that describe a pending media item.
@@ -655,7 +642,11 @@
* @see MediaColumns#PRIMARY_DIRECTORY
*/
public void setPrimaryDirectory(@Nullable String primaryDirectory) {
- this.primaryDirectory = primaryDirectory;
+ if (primaryDirectory == null) {
+ this.insertValues.remove(MediaColumns.PRIMARY_DIRECTORY);
+ } else {
+ this.insertValues.put(MediaColumns.PRIMARY_DIRECTORY, primaryDirectory);
+ }
}
/**
@@ -668,7 +659,11 @@
* @see MediaColumns#SECONDARY_DIRECTORY
*/
public void setSecondaryDirectory(@Nullable String secondaryDirectory) {
- this.secondaryDirectory = secondaryDirectory;
+ if (secondaryDirectory == null) {
+ this.insertValues.remove(MediaColumns.SECONDARY_DIRECTORY);
+ } else {
+ this.insertValues.put(MediaColumns.SECONDARY_DIRECTORY, secondaryDirectory);
+ }
}
/**
@@ -797,7 +792,9 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
+ * @removed
*/
+ @Deprecated
public static void trash(@NonNull Context context, @NonNull Uri uri) {
trash(context, uri, 48 * DateUtils.HOUR_IN_MILLIS);
}
@@ -815,7 +812,9 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
+ * @removed
*/
+ @Deprecated
public static void trash(@NonNull Context context, @NonNull Uri uri,
@DurationMillisLong long timeoutMillis) {
if (timeoutMillis < 0) {
@@ -837,7 +836,9 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
+ * @removed
*/
+ @Deprecated
public static void untrash(@NonNull Context context, @NonNull Uri uri) {
final ContentValues values = new ContentValues();
values.put(MediaColumns.IS_TRASHED, 0);
@@ -884,7 +885,9 @@
* hash is calculated.
* <p>
* Type: BLOB
+ * @removed
*/
+ @Deprecated
public static final String HASH = "_hash";
/**
@@ -921,8 +924,22 @@
public static final String DATE_MODIFIED = "date_modified";
/**
- * The MIME type of the file
- * <P>Type: TEXT</P>
+ * The MIME type of the media item.
+ * <p>
+ * This is typically defined based on the file extension of the media
+ * item. However, it may be the value of the {@code format} attribute
+ * defined by the <em>Dublin Core Media Initiative</em> standard,
+ * extracted from any XMP metadata contained within this media item.
+ * <p class="note">
+ * Note: the {@code format} attribute may be ignored if the top-level
+ * MIME type disagrees with the file extension. For example, it's
+ * reasonable for an {@code image/jpeg} file to declare a {@code format}
+ * of {@code image/vnd.google.panorama360+jpg}, but declaring a
+ * {@code format} of {@code audio/ogg} would be ignored.
+ * <p>
+ * This is a read-only column that is automatically computed.
+ * <p>
+ * Type: TEXT
*/
public static final String MIME_TYPE = "mime_type";
@@ -965,7 +982,9 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
+ * @removed
*/
+ @Deprecated
public static final String IS_TRASHED = "is_trashed";
/**
@@ -974,7 +993,9 @@
* {@link #IS_PENDING} or {@link #IS_TRASHED}.
* <p>
* Type: INTEGER
+ * @removed
*/
+ @Deprecated
public static final String DATE_EXPIRES = "date_expires";
/**
@@ -991,6 +1012,8 @@
* Package name that contributed this media. The value may be
* {@code NULL} if ownership cannot be reliably determined.
* <p>
+ * This is a read-only column that is automatically computed.
+ * <p>
* Type: TEXT
*/
public static final String OWNER_PACKAGE_NAME = "owner_package_name";
@@ -1014,6 +1037,52 @@
* @see PendingParams#setSecondaryDirectory(String)
*/
public static final String SECONDARY_DIRECTORY = "secondary_directory";
+
+ /**
+ * The "document ID" GUID as defined by the <em>XMP Media
+ * Management</em> standard, extracted from any XMP metadata contained
+ * within this media item. The value is {@code null} when no metadata
+ * was found.
+ * <p>
+ * Each "document ID" is created once for each new resource. Different
+ * renditions of that resource are expected to have different IDs.
+ * <p>
+ * This is a read-only column that is automatically computed.
+ * <p>
+ * Type: TEXT
+ */
+ public static final String DOCUMENT_ID = "document_id";
+
+ /**
+ * The "instance ID" GUID as defined by the <em>XMP Media
+ * Management</em> standard, extracted from any XMP metadata contained
+ * within this media item. The value is {@code null} when no metadata
+ * was found.
+ * <p>
+ * This "instance ID" changes with each save operation of a specific
+ * "document ID".
+ * <p>
+ * This is a read-only column that is automatically computed.
+ * <p>
+ * Type: TEXT
+ */
+ public static final String INSTANCE_ID = "instance_id";
+
+ /**
+ * The "original document ID" GUID as defined by the <em>XMP Media
+ * Management</em> standard, extracted from any XMP metadata contained
+ * within this media item.
+ * <p>
+ * This "original document ID" links a resource to its original source.
+ * For example, when you save a PSD document as a JPEG, then convert the
+ * JPEG to GIF format, the "original document ID" of both the JPEG and
+ * GIF files is the "document ID" of the original PSD file.
+ * <p>
+ * This is a read-only column that is automatically computed.
+ * <p>
+ * Type: TEXT
+ */
+ public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
}
/**
@@ -3097,20 +3166,29 @@
final ArrayList<File> res = new ArrayList<>();
if (VOLUME_INTERNAL.equals(volumeName)) {
- res.add(new File(Environment.getRootDirectory(), "media"));
- res.add(new File(Environment.getOemDirectory(), "media"));
- res.add(new File(Environment.getProductDirectory(), "media"));
+ addCanoncialFile(res, new File(Environment.getRootDirectory(), "media"));
+ addCanoncialFile(res, new File(Environment.getOemDirectory(), "media"));
+ addCanoncialFile(res, new File(Environment.getProductDirectory(), "media"));
} else {
- res.add(getVolumePath(volumeName));
+ addCanoncialFile(res, getVolumePath(volumeName));
final UserManager um = AppGlobals.getInitialApplication()
.getSystemService(UserManager.class);
if (VOLUME_EXTERNAL.equals(volumeName) && um.isDemoUser()) {
- res.add(Environment.getDataPreloadsMediaDirectory());
+ addCanoncialFile(res, Environment.getDataPreloadsMediaDirectory());
}
}
return res;
}
+ private static void addCanoncialFile(List<File> list, File file) {
+ try {
+ list.add(file.getCanonicalFile());
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to resolve " + file + ": " + e);
+ list.add(file);
+ }
+ }
+
/**
* Uri for querying the state of the media scanner.
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e95d6046..3747ec6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8289,6 +8289,7 @@
* The value is boolean (1 or 0).
* @hide
*/
+ @TestApi
public static final String NOTIFICATION_BADGING = "notification_badging";
private static final Validator NOTIFICATION_BADGING_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -13284,17 +13285,6 @@
public static final String AUTOFILL_MAX_VISIBLE_DATASETS = "autofill_max_visible_datasets";
/**
- * Used to emulate Smart Suggestion for Augmented Autofill during development
- *
- * <p>Valid values: {@code 0x1} for IME and/or {@code 0x2} for popup window.
- *
- * @hide
- */
- @TestApi
- public static final String AUTOFILL_SMART_SUGGESTION_EMULATION_FLAGS =
- "autofill_smart_suggestion_emulation_flags";
-
- /**
* Exemptions to the hidden API blacklist.
*
* @hide
diff --git a/core/java/android/service/textclassifier/TEST_MAPPING b/core/java/android/service/textclassifier/TEST_MAPPING
new file mode 100644
index 0000000..ccf2631
--- /dev/null
+++ b/core/java/android/service/textclassifier/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/core/java/android/view/textclassifier"
+ }
+ ]
+}
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 03e8a0f..c64386e 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -133,7 +133,7 @@
};
// Enable/disable vsync for animations and drawing.
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769497)
private static final boolean USE_VSYNC = SystemProperties.getBoolean(
"debug.choreographer.vsync", true);
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index e3a6bd7..49bae28 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -32,6 +32,7 @@
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
@@ -495,7 +496,7 @@
* @return True if the display is still valid.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public boolean getDisplayInfo(DisplayInfo outDisplayInfo) {
synchronized (this) {
updateDisplayInfoLocked();
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 43de1f8..ad8fee9 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -27,6 +27,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
@@ -157,8 +158,9 @@
*
* @hide
*/
+ // Remark on @UnsupportedAppUsage: Display.getCutout should be used instead
@Nullable
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public DisplayCutout displayCutout;
/**
@@ -281,7 +283,7 @@
}
};
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769467)
public DisplayInfo() {
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8ae4757..2ef7c4b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -25,6 +25,7 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
+import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
@@ -380,6 +381,16 @@
void getStableInsets(int displayId, out Rect outInsets);
/**
+ * Set the forwarded insets on the display.
+ * <p>
+ * This is only used in case a virtual display is displayed on another display that has insets,
+ * and the bounds of the virtual display is overlapping with the insets from the host display.
+ * In that case, the contents on the virtual display won't be placed over the forwarded insets.
+ * Only the owner of the display is permitted to set the forwarded insets on it.
+ */
+ void setForwardedInsets(int displayId, in Insets insets);
+
+ /**
* Register shortcut key. Shortcut code is packed as:
* (MetaState << Integer.SIZE) | KeyCode
* @hide
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 7295259..868a9de 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
+import android.os.Build;
import android.os.NullVibrator;
import android.os.Parcel;
import android.os.Parcelable;
@@ -54,7 +55,7 @@
private final int mProductId;
private final String mDescriptor;
private final InputDeviceIdentifier mIdentifier;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private final boolean mIsExternal;
private final int mSources;
private final int mKeyboardType;
@@ -608,10 +609,7 @@
* peripheral bus), otherwise it is built-in.
*
* @return True if the device is external.
- *
- * @hide
*/
- @UnsupportedAppUsage
public boolean isExternal() {
return mIsExternal;
}
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 583651d..dd88e3c 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -33,6 +33,7 @@
import android.view.InsetsState.InsetSide;
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
import android.view.WindowInsets.Type.InsetType;
+import android.view.WindowManager.LayoutParams;
import com.android.internal.annotations.VisibleForTesting;
@@ -165,7 +166,8 @@
@Nullable @InsetSide SparseIntArray typeSideMap) {
return state.calculateInsets(frame, false /* isScreenRound */,
false /* alwaysConsumerNavBar */, null /* displayCutout */,
- null /* legacyContentInsets */, null /* legacyStableInsets */, typeSideMap)
+ null /* legacyContentInsets */, null /* legacyStableInsets */,
+ LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/, typeSideMap)
.getInsets(mTypes);
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 7ad97a6..2586000 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -112,6 +112,8 @@
private int mPendingTypesToShow;
+ private int mLastLegacySoftInputMode;
+
public InsetsController(ViewRootImpl viewRoot) {
mViewRoot = viewRoot;
mAnimCallback = () -> {
@@ -126,13 +128,17 @@
}
WindowInsets insets = state.calculateInsets(mFrame, mLastInsets.isRound(),
mLastInsets.shouldAlwaysConsumeNavBar(), mLastInsets.getDisplayCutout(),
- mLastLegacyContentInsets, mLastLegacyStableInsets,
+ mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode,
null /* typeSideMap */);
mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets);
};
}
void onFrameChanged(Rect frame) {
+ if (mFrame.equals(frame)) {
+ return;
+ }
+ mViewRoot.notifyInsetsChanged();
mFrame.set(frame);
}
@@ -160,11 +166,12 @@
@VisibleForTesting
public WindowInsets calculateInsets(boolean isScreenRound,
boolean alwaysConsumeNavBar, DisplayCutout cutout, Rect legacyContentInsets,
- Rect legacyStableInsets) {
+ Rect legacyStableInsets, int legacySoftInputMode) {
mLastLegacyContentInsets.set(legacyContentInsets);
mLastLegacyStableInsets.set(legacyStableInsets);
+ mLastLegacySoftInputMode = legacySoftInputMode;
mLastInsets = mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout,
- legacyContentInsets, legacyStableInsets,
+ legacyContentInsets, legacyStableInsets, legacySoftInputMode,
null /* typeSideMap */);
return mLastInsets;
}
@@ -257,11 +264,21 @@
private void controlWindowInsetsAnimation(@InsetType int types,
WindowInsetsAnimationControlListener listener, boolean fromIme) {
+ // If the frame of our window doesn't span the entire display, the control API makes very
+ // little sense, as we don't deal with negative insets. So just cancel immediately.
+ if (!mState.getDisplayFrame().equals(mFrame)) {
+ listener.onCancelled();
+ return;
+ }
+ controlAnimationUnchecked(types, listener, mFrame, fromIme);
+ }
+
+ private void controlAnimationUnchecked(@InsetType int types,
+ WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme) {
if (types == 0) {
// nothing to animate.
return;
}
-
// TODO: Check whether we already have a controller.
final ArraySet<Integer> internalTypes = mState.toInternalType(types);
final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
@@ -285,7 +302,7 @@
}
final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(consumers,
- mFrame, mState, listener, typesReady,
+ frame, mState, listener, typesReady,
() -> new SyncRtSurfaceTransactionApplier(mViewRoot.mView), this);
mAnimationControls.add(controller);
}
@@ -436,6 +453,7 @@
// nothing to animate.
return;
}
+
WindowInsetsAnimationControlListener listener = new WindowInsetsAnimationControlListener() {
@Override
public void onReady(WindowInsetsAnimationController controller, int types) {
@@ -479,7 +497,10 @@
// TODO: Instead of clearing this here, properly wire up
// InsetsAnimationControlImpl.finish() to remove this from mAnimationControls.
mAnimationControls.clear();
- controlWindowInsetsAnimation(types, listener, fromIme);
+
+ // Show/hide animations always need to be relative to the display frame, in order that shown
+ // and hidden state insets are correct.
+ controlAnimationUnchecked(types, listener, mState.getDisplayFrame(), fromIme);
}
private void hideDirectly(@InsetType int types) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 4f809fe6..69f86aa 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -19,6 +19,7 @@
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
+import static android.view.WindowInsets.Type.IME;
import static android.view.WindowInsets.Type.SIZE;
import static android.view.WindowInsets.Type.indexOf;
@@ -34,11 +35,13 @@
import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetType;
+import android.view.WindowManager.LayoutParams;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Objects;
/**
* Holder for state of system windows that cause window insets for all other windows in the system.
@@ -104,6 +107,11 @@
private final ArrayMap<Integer, InsetsSource> mSources = new ArrayMap<>();
+ /**
+ * The frame of the display these sources are relative to.
+ */
+ private final Rect mDisplayFrame = new Rect();
+
public InsetsState() {
}
@@ -124,7 +132,7 @@
public WindowInsets calculateInsets(Rect frame, boolean isScreenRound,
boolean alwaysConsumeNavBar, DisplayCutout cutout,
@Nullable Rect legacyContentInsets, @Nullable Rect legacyStableInsets,
- @Nullable @InsetSide SparseIntArray typeSideMap) {
+ int legacySoftInputMode, @Nullable @InsetSide SparseIntArray typeSideMap) {
Insets[] typeInsetsMap = new Insets[Type.SIZE];
Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
boolean[] typeVisibilityMap = new boolean[SIZE];
@@ -140,8 +148,12 @@
if (source == null) {
continue;
}
- if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
- && (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR)) {
+
+ boolean skipSystemBars = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
+ && (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR);
+ boolean skipIme = source.getType() == TYPE_IME
+ && (legacySoftInputMode & LayoutParams.SOFT_INPUT_ADJUST_RESIZE) == 0;
+ if (skipSystemBars || skipIme) {
typeVisibilityMap[indexOf(toPublicType(type))] = source.isVisible();
continue;
}
@@ -209,6 +221,14 @@
return mSources.computeIfAbsent(type, InsetsSource::new);
}
+ public void setDisplayFrame(Rect frame) {
+ mDisplayFrame.set(frame);
+ }
+
+ public Rect getDisplayFrame() {
+ return mDisplayFrame;
+ }
+
/**
* Modifies the state of this class to exclude a certain type to make it ready for dispatching
* to the client.
@@ -224,6 +244,7 @@
}
public void set(InsetsState other, boolean copySources) {
+ mDisplayFrame.set(other.mDisplayFrame);
mSources.clear();
if (copySources) {
for (int i = 0; i < other.mSources.size(); i++) {
@@ -323,6 +344,9 @@
InsetsState state = (InsetsState) o;
+ if (!mDisplayFrame.equals(state.mDisplayFrame)) {
+ return false;
+ }
if (mSources.size() != state.mSources.size()) {
return false;
}
@@ -341,7 +365,7 @@
@Override
public int hashCode() {
- return mSources.hashCode();
+ return Objects.hash(mDisplayFrame, mSources);
}
public InsetsState(Parcel in) {
@@ -355,9 +379,10 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mDisplayFrame, flags);
dest.writeInt(mSources.size());
for (int i = 0; i < mSources.size(); i++) {
- dest.writeParcelable(mSources.valueAt(i), 0 /* flags */);
+ dest.writeParcelable(mSources.valueAt(i), flags);
}
}
@@ -374,6 +399,7 @@
public void readFromParcel(Parcel in) {
mSources.clear();
+ mDisplayFrame.set(in.readParcelable(null /* loader */));
final int size = in.readInt();
for (int i = 0; i < size; i++) {
final InsetsSource source = in.readParcelable(null /* loader */);
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 6a290b7..39b6876 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -42,14 +42,16 @@
import com.android.internal.R;
import dalvik.system.PathClassLoader;
-import java.io.File;
-import java.lang.reflect.Method;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
import java.util.HashMap;
+import java.util.Objects;
/**
* Instantiates a layout XML file into its corresponding {@link android.view.View}
@@ -93,7 +95,12 @@
protected final Context mContext;
// these are optional, set by the caller
- @UnsupportedAppUsage
+ /**
+ * If any developer has desire to change this value, they should instead use
+ * {@link #cloneInContext(Context)} and set the new factory in thew newly-created
+ * LayoutInflater.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private boolean mFactorySet;
@UnsupportedAppUsage
private Factory mFactory;
@@ -110,7 +117,12 @@
// The classloader includes the generated compiled_view.dex file.
private ClassLoader mPrecompiledClassLoader;
- @UnsupportedAppUsage
+ /**
+ * This is not a public API. Two APIs are now available to alleviate the need to access
+ * this directly: {@link #createView(Context, String, String, AttributeSet)} and
+ * {@link #onCreateView(Context, View, String, AttributeSet)}.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
final Object[] mConstructorArgs = new Object[2];
@UnsupportedAppUsage
@@ -721,11 +733,11 @@
} while (cl != null);
return false;
}
-
/**
* Low-level function for instantiating a view by name. This attempts to
* instantiate a view class of the given <var>name</var> found in this
- * LayoutInflater's ClassLoader.
+ * LayoutInflater's ClassLoader. To use an explicit Context in the View
+ * constructor, use {@link #createView(Context, String, String, AttributeSet)} instead.
*
* <p>
* There are two things that can happen in an error case: either the
@@ -741,6 +753,37 @@
*/
public final View createView(String name, String prefix, AttributeSet attrs)
throws ClassNotFoundException, InflateException {
+ Context context = (Context) mConstructorArgs[0];
+ if (context == null) {
+ context = mContext;
+ }
+ return createView(context, name, prefix, attrs);
+ }
+
+ /**
+ * Low-level function for instantiating a view by name. This attempts to
+ * instantiate a view class of the given <var>name</var> found in this
+ * LayoutInflater's ClassLoader.
+ *
+ * <p>
+ * There are two things that can happen in an error case: either the
+ * exception describing the error will be thrown, or a null will be
+ * returned. You must deal with both possibilities -- the former will happen
+ * the first time createView() is called for a class of a particular name,
+ * the latter every time there-after for that class name.
+ *
+ * @param viewContext The context used as the context parameter of the View constructor
+ * @param name The full name of the class to be instantiated.
+ * @param attrs The XML attributes supplied for this instance.
+ *
+ * @return View The newly instantiated view, or null.
+ */
+ @Nullable
+ public final View createView(@NonNull Context viewContext, @NonNull String name,
+ @Nullable String prefix, @Nullable AttributeSet attrs)
+ throws ClassNotFoundException, InflateException {
+ Objects.requireNonNull(viewContext);
+ Objects.requireNonNull(name);
Constructor<? extends View> constructor = sConstructorMap.get(name);
if (constructor != null && !verifyClassLoader(constructor)) {
constructor = null;
@@ -787,22 +830,21 @@
}
Object lastContext = mConstructorArgs[0];
- if (mConstructorArgs[0] == null) {
- // Fill in the context if not already within inflation.
- mConstructorArgs[0] = mContext;
- }
+ mConstructorArgs[0] = viewContext;
Object[] args = mConstructorArgs;
args[1] = attrs;
- final View view = constructor.newInstance(args);
- if (view instanceof ViewStub) {
- // Use the same context when inflating ViewStub later.
- final ViewStub viewStub = (ViewStub) view;
- viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
+ try {
+ final View view = constructor.newInstance(args);
+ if (view instanceof ViewStub) {
+ // Use the same context when inflating ViewStub later.
+ final ViewStub viewStub = (ViewStub) view;
+ viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
+ }
+ return view;
+ } finally {
+ mConstructorArgs[0] = lastContext;
}
- mConstructorArgs[0] = lastContext;
- return view;
-
} catch (NoSuchMethodException e) {
final InflateException ie = new InflateException(attrs.getPositionDescription()
+ ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
@@ -871,6 +913,26 @@
}
/**
+ * Version of {@link #onCreateView(View, String, AttributeSet)} that also
+ * takes the inflation context. The default
+ * implementation simply calls {@link #onCreateView(View, String, AttributeSet)}.
+ *
+ * @param viewContext The Context to be used as a constructor parameter for the View
+ * @param parent The future parent of the returned view. <em>Note that
+ * this may be null.</em>
+ * @param name The fully qualified class name of the View to be create.
+ * @param attrs An AttributeSet of attributes to apply to the View.
+ *
+ * @return View The View created.
+ */
+ @Nullable
+ public View onCreateView(@NonNull Context viewContext, @Nullable View parent,
+ @NonNull String name, @Nullable AttributeSet attrs)
+ throws ClassNotFoundException {
+ return onCreateView(parent, name, attrs);
+ }
+
+ /**
* Convenience method for calling through to the five-arg createViewFromTag
* method. This method passes {@code false} for the {@code ignoreThemeAttr}
* argument and should be used for everything except {@code >include>}
@@ -921,9 +983,9 @@
mConstructorArgs[0] = context;
try {
if (-1 == name.indexOf('.')) {
- view = onCreateView(parent, name, attrs);
+ view = onCreateView(context, parent, name, attrs);
} else {
- view = createView(name, null, attrs);
+ view = createView(context, name, null, attrs);
}
} finally {
mConstructorArgs[0] = lastContext;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index b6a4a09..b6c4cbb 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -24,6 +24,7 @@
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -1513,7 +1514,7 @@
}
// Pointer to the native MotionEvent object that contains the actual data.
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private long mNativePtr;
private MotionEvent mNext;
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index dc11d3d..c24b8b2 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -18,7 +18,6 @@
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.content.res.Resources;
import android.os.Build;
import android.os.Handler;
@@ -145,7 +144,7 @@
private boolean mInProgress;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768938)
private int mSpanSlop;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768938)
private int mMinSpan;
private final Handler mHandler;
@@ -200,10 +199,9 @@
Handler handler) {
mContext = context;
mListener = listener;
- mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
-
- final Resources res = context.getResources();
- mMinSpan = res.getDimensionPixelSize(com.android.internal.R.dimen.config_minScalingSpan);
+ final ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
+ mSpanSlop = viewConfiguration.getScaledTouchSlop() * 2;
+ mMinSpan = viewConfiguration.getScaledMinScalingSpan();
mHandler = handler;
// Quick scale is enabled by default after JB_MR2
final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 8028715..1212df0 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -62,6 +62,7 @@
import java.io.Closeable;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
/**
* Handle to an on-screen Surface managed by the system compositor. The SurfaceControl is
@@ -711,8 +712,10 @@
for (int i = 0; i < metadata.size(); ++i) {
metaParcel.writeInt(metadata.keyAt(i));
metaParcel.writeByteArray(
- ByteBuffer.allocate(4).putInt(metadata.valueAt(i)).array());
+ ByteBuffer.allocate(4).order(ByteOrder.nativeOrder())
+ .putInt(metadata.valueAt(i)).array());
}
+ metaParcel.setDataPosition(0);
}
mNativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, metaParcel);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c641552..83df33e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4030,8 +4030,24 @@
/**
* {@hide}
+ *
+ * Not available for general use. If you need help, hang up and then dial one of the following
+ * public APIs:
+ *
+ * @see #isAttachedToWindow() for current attach state
+ * @see #onAttachedToWindow() for subclasses performing work when becoming attached
+ * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
+ * @see OnAttachStateChangeListener for other code performing work on attach/detach
+ * @see #getHandler() for posting messages to this view's UI thread/looper
+ * @see #getParent() for interacting with the parent chain
+ * @see #getWindowToken() for the current window token
+ * @see #getRootView() for the view at the root of the attached hierarchy
+ * @see #getDisplay() for the Display this view is presented on
+ * @see #getRootWindowInsets() for the current insets applied to the whole attached window
+ * @see #hasWindowFocus() for whether the attached window is currently focused
+ * @see #getWindowVisibility() for checking the visibility of the attached window
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
AttachInfo mAttachInfo;
/**
@@ -23429,7 +23445,7 @@
/**
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
protected void internalSetPadding(int left, int top, int right, int bottom) {
mUserPaddingLeft = left;
mUserPaddingRight = right;
@@ -28193,18 +28209,6 @@
View mViewRequestingLayout;
/**
- * Used to track views that need (at least) a partial relayout at their current size
- * during the next traversal.
- */
- List<View> mPartialLayoutViews = new ArrayList<>();
-
- /**
- * Swapped with mPartialLayoutViews during layout to avoid concurrent
- * modification. Lazily assigned during ViewRootImpl layout.
- */
- List<View> mEmptyPartialLayoutViews;
-
- /**
* Used to track the identity of the current drag operation.
*/
IBinder mDragToken;
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 6beae37..bb29ed6 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -293,12 +293,14 @@
*/
private static final float AMBIGUOUS_GESTURE_MULTIPLIER = 2f;
+ private final boolean mConstructedWithContext;
private final int mEdgeSlop;
private final int mFadingEdgeLength;
private final int mMinimumFlingVelocity;
private final int mMaximumFlingVelocity;
private final int mScrollbarSize;
private final int mTouchSlop;
+ private final int mMinScalingSpan;
private final int mHoverSlop;
private final int mMinScrollbarTouchTarget;
private final int mDoubleTapTouchSlop;
@@ -329,6 +331,7 @@
*/
@Deprecated
public ViewConfiguration() {
+ mConstructedWithContext = false;
mEdgeSlop = EDGE_SLOP;
mFadingEdgeLength = FADING_EDGE_LENGTH;
mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY;
@@ -350,6 +353,10 @@
mHorizontalScrollFactor = HORIZONTAL_SCROLL_FACTOR;
mVerticalScrollFactor = VERTICAL_SCROLL_FACTOR;
mShowMenuShortcutsWhenKeyboardPresent = false;
+
+ // Getter throws if mConstructedWithContext is false so doesn't matter what
+ // this value is.
+ mMinScalingSpan = 0;
}
/**
@@ -363,6 +370,7 @@
* @see android.util.DisplayMetrics
*/
private ViewConfiguration(Context context) {
+ mConstructedWithContext = true;
final Resources res = context.getResources();
final DisplayMetrics metrics = res.getDisplayMetrics();
final Configuration config = res.getConfiguration();
@@ -447,6 +455,8 @@
mShowMenuShortcutsWhenKeyboardPresent = res.getBoolean(
com.android.internal.R.bool.config_showMenuShortcutsWhenKeyboardPresent);
+ mMinScalingSpan = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.config_minScalingSpan);
}
/**
@@ -959,6 +969,26 @@
}
/**
+ * Retrieves the distance in pixels between touches that must be reached for a gesture to be
+ * interpreted as scaling.
+ *
+ * In general, scaling shouldn't start until this distance has been met or surpassed, and
+ * scaling should end when the distance in pixels between touches drops below this distance.
+ *
+ * @return The distance in pixels
+ * @throws IllegalStateException if this method is called on a ViewConfiguration that was
+ * instantiated using a constructor with no Context parameter.
+ */
+ public int getScaledMinScalingSpan() {
+ if (!mConstructedWithContext) {
+ throw new IllegalStateException("Min scaling span cannot be determined when this "
+ + "method is called on a ViewConfiguration that was instantiated using a "
+ + "constructor with no Context parameter");
+ }
+ return mMinScalingSpan;
+ }
+
+ /**
* @hide
* @return Whether or not marquee should use fading edges.
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 156972f..1a782ee 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1887,7 +1887,7 @@
mLastWindowInsets = mInsetsController.calculateInsets(
mContext.getResources().getConfiguration().isScreenRound(),
mAttachInfo.mAlwaysConsumeNavBar, displayCutout,
- contentInsets, stableInsets);
+ contentInsets, stableInsets, mWindowAttributes.softInputMode);
} else {
mLastWindowInsets = new WindowInsets(contentInsets, stableInsets,
mContext.getResources().getConfiguration().isScreenRound(),
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 46aea80..e3833c0 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -520,7 +520,7 @@
return false;
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public void trimMemory(int level) {
if (ThreadedRenderer.isAvailable()) {
if (shouldDestroyEglContext(level)) {
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index dfd9a2e..e095094 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.RectF;
+import android.os.Build;
import android.os.Handler;
import android.os.SystemProperties;
import android.util.AttributeSet;
@@ -30,9 +31,6 @@
import dalvik.system.CloseGuard;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Abstraction for an Animation that can be applied to Views, Surfaces, or
* other objects. See the {@link android.view.animation animation package
@@ -187,15 +185,12 @@
/**
* An animation listener to be notified when the animation starts, ends or repeats.
*/
- @UnsupportedAppUsage
+ // If you need to chain the AnimationListener, wrap the existing Animation into an AnimationSet
+ // and add your new listener to that set
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 117519981)
private AnimationListener mListener;
/**
- * A list of animation listeners to be notified when the animation starts, ends or repeats.
- */
- private List<AnimationListener> mListeners;
-
- /**
* Desired Z order mode during animation.
*/
private int mZAdjustment;
@@ -833,7 +828,7 @@
}
private boolean hasAnimationListener() {
- return mListener != null || (mListeners != null && !mListeners.isEmpty());
+ return mListener != null;
}
/**
@@ -848,32 +843,6 @@
}
/**
- * <p>Adds an animation listener to this animation. The animation listener
- * is notified of animation events such as the end of the animation or the
- * repetition of the animation.</p>
- *
- * @param listener the animation listener to be notified
- */
- public void addAnimationListener(AnimationListener listener) {
- if (mListeners == null) {
- mListeners = new ArrayList<>(1);
- }
- mListeners.add(listener);
- }
-
- /**
- * <p>Removes an animation listener that has been added with
- * {@link #addAnimationListener(AnimationListener)}.</p>
- *
- * @param listener the animation listener to be removed
- */
- public void removeAnimationListener(AnimationListener listener) {
- if (mListeners != null) {
- mListeners.remove(listener);
- }
- }
-
- /**
* Gurantees that this animation has an interpolator. Will use
* a AccelerateDecelerateInterpolator is nothing else was specified.
*/
@@ -1003,33 +972,18 @@
if (mListener != null) {
mListener.onAnimationStart(this);
}
- if (mListeners != null && !mListeners.isEmpty()) {
- for (AnimationListener listener : mListeners) {
- listener.onAnimationStart(this);
- }
- }
}
void dispatchAnimationRepeat() {
if (mListener != null) {
mListener.onAnimationRepeat(this);
}
- if (mListeners != null && !mListeners.isEmpty()) {
- for (AnimationListener listener : mListeners) {
- listener.onAnimationRepeat(this);
- }
- }
}
void dispatchAnimationEnd() {
if (mListener != null) {
mListener.onAnimationEnd(this);
}
- if (mListeners != null && !mListeners.isEmpty()) {
- for (AnimationListener listener : mListeners) {
- listener.onAnimationEnd(this);
- }
- }
}
/**
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 83fc0173..397fc66 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -17,7 +17,6 @@
package android.view.autofill;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
-import static android.util.DebugUtils.flagsToString;
import static android.view.autofill.Helper.sDebug;
import static android.view.autofill.Helper.sVerbose;
@@ -354,6 +353,15 @@
public @interface SmartSuggestionMode {}
/**
+ * Used to emulate Smart Suggestion for Augmented Autofill during development
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES =
+ "smart_suggestion_supported_modes";
+
+ /**
* Makes an authentication id from a request id and a dataset id.
*
* @param requestId The request id.
@@ -2347,7 +2355,7 @@
/** @hide */
public static String getSmartSuggestionModeToString(@SmartSuggestionMode int flags) {
- return flagsToString(AutofillManager.class, "FLAG_SMART_SUGGESTION_", flags);
+ return (flags == FLAG_SMART_SUGGESTION_SYSTEM) ? "1-SYSTEM" : flags + "-UNSUPPORTED";
}
@GuardedBy("mLock")
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 2512b95..634443d 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -66,6 +66,25 @@
*/
private static final int SYNC_CALLS_TIMEOUT_MS = 5000;
+ /**
+ * DeviceConfig property used by {@code com.android.server.SystemServer} on start to decide
+ * whether the Content Capture service should be created or not
+ *
+ * <p>By default it should *NOT* be set (or set to {@code "default"}, so the decision is based
+ * on whether the OEM provides an implementation for the service), but it can be overridden to:
+ *
+ * <ul>
+ * <li>Provide a "kill switch" so OEMs can disable it remotely in case of emergency (when
+ * it's set to {@code "false"}).
+ * <li>Enable the CTS tests to be run on AOSP builds (when it's set to {@code "true"}).
+ * </ul>
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED =
+ "service_explicitly_enabled";
+
private final Object mLock = new Object();
@NonNull
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index eb945b5..810c967 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -303,6 +303,7 @@
Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
+ getSanitizedString(event.getText()));
}
+ // TODO(b/124107816): should call lastEvent.merge(event) instead
lastEvent.setText(event.getText());
addEvent = false;
}
@@ -316,7 +317,7 @@
Log.v(TAG, "Buffering TYPE_VIEW_DISAPPEARED events for session "
+ lastEvent.getSessionId());
}
- lastEvent.addAutofillId(event.getId());
+ mergeViewsDisappearedEvent(lastEvent, event);
addEvent = false;
}
}
@@ -364,6 +365,30 @@
flush(flushReason);
}
+ // TODO(b/124107816): should be ContentCaptureEvent Event.merge(event) instead (which would
+ // replace the addAutofillId() method - we would also need unit tests on ContentCaptureEventTest
+ // to check these scenarios)
+ private void mergeViewsDisappearedEvent(@NonNull ContentCaptureEvent lastEvent,
+ @NonNull ContentCaptureEvent event) {
+ final List<AutofillId> ids = event.getIds();
+ final AutofillId id = event.getId();
+ if (ids != null) {
+ if (id != null) {
+ Log.w(TAG, "got TYPE_VIEW_DISAPPEARED event with both id and ids: " + event);
+ }
+ for (int i = 0; i < ids.size(); i++) {
+ lastEvent.addAutofillId(ids.get(i));
+ }
+ return;
+ }
+ if (id != null) {
+ lastEvent.addAutofillId(id);
+ return;
+ }
+ throw new IllegalArgumentException(
+ "got TYPE_VIEW_DISAPPEARED event with neither id or ids: " + event);
+ }
+
@UiThread
private boolean hasStarted() {
return mState != UNKNOWN_STATE;
diff --git a/core/java/android/view/textclassifier/ConversationAction.java b/core/java/android/view/textclassifier/ConversationAction.java
index 1a6e5d8..ae6a645 100644
--- a/core/java/android/view/textclassifier/ConversationAction.java
+++ b/core/java/android/view/textclassifier/ConversationAction.java
@@ -92,6 +92,9 @@
*/
public static final String TYPE_SHARE_LOCATION = "share_location";
+ /** @hide **/
+ public static final String TYPE_ADD_CONTACT = "add_contact";
+
public static final Creator<ConversationAction> CREATOR =
new Creator<ConversationAction>() {
@Override
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
index 602455c..b0e7ad5 100644
--- a/core/java/android/view/textclassifier/ExtrasUtils.java
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -85,15 +85,16 @@
}
/**
- * Returns the first "translate" action found in the {@code classification} object.
+ * Returns the first action found in the {@code classification} object with an intent
+ * action string, {@code intentAction}.
*/
@Nullable
- public static RemoteAction findTranslateAction(TextClassification classification) {
+ public static RemoteAction findAction(TextClassification classification, String intentAction) {
final ArrayList<Intent> actionIntents = getActionsIntents(classification);
if (actionIntents != null) {
final int size = actionIntents.size();
for (int i = 0; i < size; i++) {
- if (Intent.ACTION_TRANSLATE.equals(actionIntents.get(i).getAction())) {
+ if (intentAction.equals(actionIntents.get(i).getAction())) {
return classification.getActions().get(i);
}
}
@@ -102,6 +103,14 @@
}
/**
+ * Returns the first "translate" action found in the {@code classification} object.
+ */
+ @Nullable
+ public static RemoteAction findTranslateAction(TextClassification classification) {
+ return findAction(classification, Intent.ACTION_TRANSLATE);
+ }
+
+ /**
* Returns the entity type contained in the {@code extra}.
*/
@Nullable
diff --git a/core/java/android/view/textclassifier/LegacyIntentFactory.java b/core/java/android/view/textclassifier/LegacyIntentFactory.java
index b6e5b3e2..2d0d032 100644
--- a/core/java/android/view/textclassifier/LegacyIntentFactory.java
+++ b/core/java/android/view/textclassifier/LegacyIntentFactory.java
@@ -182,7 +182,8 @@
actions.add(new LabeledIntent(
context.getString(com.android.internal.R.string.browse),
context.getString(com.android.internal.R.string.browse_desc),
- new Intent(Intent.ACTION_VIEW, Uri.parse(text))
+ new Intent(Intent.ACTION_VIEW)
+ .setDataAndNormalize(Uri.parse(text))
.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()),
LabeledIntent.DEFAULT_REQUEST_CODE));
return actions;
diff --git a/core/java/android/view/textclassifier/TEST_MAPPING b/core/java/android/view/textclassifier/TEST_MAPPING
new file mode 100644
index 0000000..0d3c346
--- /dev/null
+++ b/core/java/android/view/textclassifier/TEST_MAPPING
@@ -0,0 +1,23 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.view.textclassifier"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsViewTestCases",
+ "options": [
+ {
+ "include-filter": "android.view.textclassifier.cts"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/view/textclassifier/TemplateIntentFactory.java b/core/java/android/view/textclassifier/TemplateIntentFactory.java
index 5278843..95f88c7 100644
--- a/core/java/android/view/textclassifier/TemplateIntentFactory.java
+++ b/core/java/android/view/textclassifier/TemplateIntentFactory.java
@@ -49,20 +49,18 @@
}
final List<TextClassifierImpl.LabeledIntent> labeledIntents = new ArrayList<>();
for (RemoteActionTemplate remoteActionTemplate : remoteActionTemplates) {
- Intent intent = createIntent(remoteActionTemplate);
- if (intent == null) {
+ if (!isValidTemplate(remoteActionTemplate)) {
+ Log.w(TAG, "Invalid RemoteActionTemplate skipped.");
continue;
}
- TextClassifierImpl.LabeledIntent
- labeledIntent = new TextClassifierImpl.LabeledIntent(
- remoteActionTemplate.title,
- remoteActionTemplate.description,
- intent,
- remoteActionTemplate.requestCode == null
- ? TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE
- : remoteActionTemplate.requestCode
- );
- labeledIntents.add(labeledIntent);
+ labeledIntents.add(
+ new TextClassifierImpl.LabeledIntent(
+ remoteActionTemplate.title,
+ remoteActionTemplate.description,
+ createIntent(remoteActionTemplate),
+ remoteActionTemplate.requestCode == null
+ ? TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE
+ : remoteActionTemplate.requestCode));
}
labeledIntents.forEach(
action -> action.getIntent()
@@ -70,29 +68,43 @@
return labeledIntents;
}
- @Nullable
- private static Intent createIntent(RemoteActionTemplate remoteActionTemplate) {
- Intent intent = new Intent();
+ private static boolean isValidTemplate(@Nullable RemoteActionTemplate remoteActionTemplate) {
+ if (remoteActionTemplate == null) {
+ Log.w(TAG, "Invalid RemoteActionTemplate: is null");
+ return false;
+ }
+ if (TextUtils.isEmpty(remoteActionTemplate.title)) {
+ Log.w(TAG, "Invalid RemoteActionTemplate: title is null");
+ return false;
+ }
+ if (TextUtils.isEmpty(remoteActionTemplate.description)) {
+ Log.w(TAG, "Invalid RemoteActionTemplate: description is null");
+ return false;
+ }
if (!TextUtils.isEmpty(remoteActionTemplate.packageName)) {
- Log.w(TAG, "A RemoteActionTemplate is skipped as package name is set.");
- return null;
+ Log.w(TAG, "Invalid RemoteActionTemplate: package name is set");
+ return false;
}
- if (!TextUtils.isEmpty(remoteActionTemplate.action)) {
- intent.setAction(remoteActionTemplate.action);
+ if (TextUtils.isEmpty(remoteActionTemplate.action)) {
+ Log.w(TAG, "Invalid RemoteActionTemplate: intent action not set");
+ return false;
}
- Uri data = null;
- if (!TextUtils.isEmpty(remoteActionTemplate.data)) {
- data = Uri.parse(remoteActionTemplate.data);
- }
- if (data != null || !TextUtils.isEmpty(remoteActionTemplate.type)) {
- intent.setDataAndType(data, remoteActionTemplate.type);
- }
- if (remoteActionTemplate.flags != null) {
- intent.setFlags(remoteActionTemplate.flags);
- }
+ return true;
+ }
+
+ private static Intent createIntent(RemoteActionTemplate remoteActionTemplate) {
+ final Intent intent = new Intent(remoteActionTemplate.action);
+ final Uri uri = TextUtils.isEmpty(remoteActionTemplate.data)
+ ? null : Uri.parse(remoteActionTemplate.data).normalizeScheme();
+ final String type = TextUtils.isEmpty(remoteActionTemplate.type)
+ ? null : Intent.normalizeMimeType(remoteActionTemplate.type);
+ intent.setDataAndType(uri, type);
+ intent.setFlags(remoteActionTemplate.flags == null ? 0 : remoteActionTemplate.flags);
if (remoteActionTemplate.category != null) {
for (String category : remoteActionTemplate.category) {
- intent.addCategory(category);
+ if (category != null) {
+ intent.addCategory(category);
+ }
}
}
intent.putExtras(createExtras(remoteActionTemplate.extras));
@@ -105,6 +117,9 @@
}
Bundle bundle = new Bundle();
for (NamedVariant namedVariant : namedVariants) {
+ if (namedVariant == null) {
+ continue;
+ }
switch (namedVariant.getType()) {
case NamedVariant.TYPE_INT:
bundle.putInt(namedVariant.getName(), namedVariant.getInt());
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index ee9e04e..2ef8d04 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -131,6 +131,7 @@
.add(ConversationAction.TYPE_TRACK_FLIGHT)
.add(ConversationAction.TYPE_VIEW_CALENDAR)
.add(ConversationAction.TYPE_VIEW_MAP)
+ .add(ConversationAction.TYPE_ADD_CONTACT)
.toString();
/**
* < 0 : Not set. Use value from LangId model.
diff --git a/core/java/android/webkit/OWNERS b/core/java/android/webkit/OWNERS
index 00e540a..b33da57 100644
--- a/core/java/android/webkit/OWNERS
+++ b/core/java/android/webkit/OWNERS
@@ -1,3 +1,4 @@
changwan@google.com
+ntfschr@google.com
tobiasjs@google.com
torne@google.com
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6039350..2171fc5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -61,6 +61,7 @@
import android.view.autofill.AutofillValue;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
+import android.view.inspector.InspectableProperty;
import android.view.textclassifier.TextClassifier;
import android.widget.AbsoluteLayout;
@@ -1239,6 +1240,7 @@
*
* @return the URL for the current page
*/
+ @InspectableProperty(hasAttributeId = false)
@ViewDebug.ExportedProperty(category = "webview")
public String getUrl() {
checkThread();
@@ -1254,6 +1256,7 @@
*
* @return the URL that was originally requested for the current page
*/
+ @InspectableProperty(hasAttributeId = false)
@ViewDebug.ExportedProperty(category = "webview")
public String getOriginalUrl() {
checkThread();
@@ -1266,6 +1269,7 @@
*
* @return the title for the current page
*/
+ @InspectableProperty(hasAttributeId = false)
@ViewDebug.ExportedProperty(category = "webview")
public String getTitle() {
checkThread();
@@ -1278,6 +1282,7 @@
*
* @return the favicon for the current page
*/
+ @InspectableProperty(hasAttributeId = false)
public Bitmap getFavicon() {
checkThread();
return mProvider.getFavicon();
@@ -1300,6 +1305,7 @@
*
* @return the progress for the current page between 0 and 100
*/
+ @InspectableProperty(hasAttributeId = false)
public int getProgress() {
checkThread();
return mProvider.getProgress();
@@ -1310,6 +1316,7 @@
*
* @return the height of the HTML content
*/
+ @InspectableProperty(hasAttributeId = false)
@ViewDebug.ExportedProperty(category = "webview")
public int getContentHeight() {
checkThread();
@@ -2276,6 +2283,11 @@
*
* @return the requested renderer priority policy.
*/
+ @InspectableProperty(hasAttributeId = false, enumMapping = {
+ @InspectableProperty.EnumMap(name = "waived", value = RENDERER_PRIORITY_WAIVED),
+ @InspectableProperty.EnumMap(name = "bound", value = RENDERER_PRIORITY_BOUND),
+ @InspectableProperty.EnumMap(name = "important", value = RENDERER_PRIORITY_IMPORTANT)
+ })
@RendererPriority
public int getRendererRequestedPriority() {
return mProvider.getRendererRequestedPriority();
@@ -2288,6 +2300,7 @@
* @return whether this WebView requests a priority of
* {@link #RENDERER_PRIORITY_WAIVED} when not visible.
*/
+ @InspectableProperty(hasAttributeId = false)
public boolean getRendererPriorityWaivedWhenNotVisible() {
return mProvider.getRendererPriorityWaivedWhenNotVisible();
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6de6054..4b7c393 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -338,7 +338,7 @@
* The data set used to store unused views that should be reused during the next layout
* to avoid creating new ones
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769398)
final RecycleBin mRecycler = new RecycleBin();
/**
@@ -421,7 +421,7 @@
* One of TOUCH_MODE_REST, TOUCH_MODE_DOWN, TOUCH_MODE_TAP, TOUCH_MODE_SCROLL, or
* TOUCH_MODE_DONE_WAITING
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769413)
int mTouchMode = TOUCH_MODE_REST;
/**
@@ -634,7 +634,7 @@
/**
* Helper object that renders and controls the fast scroll thumb.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768941)
private FastScroller mFastScroll;
/**
@@ -657,7 +657,7 @@
private Runnable mClearScrollingCache;
Runnable mPositionScrollAfterLayout;
private int mMinimumVelocity;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051740)
private int mMaximumVelocity;
private float mVelocityScale = 1.0f;
@@ -700,7 +700,7 @@
/**
* Maximum distance to overfling during edge effects
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769379)
int mOverflingDistance;
// These two EdgeGlows are always set and used together.
@@ -4615,7 +4615,7 @@
*
* @param newState The new scroll state.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769710)
void reportScrollStateChange(int newState) {
if (newState != mLastScrollState) {
if (mOnScrollListener != null) {
@@ -5158,7 +5158,7 @@
* @param incrementalDeltaY Change in deltaY from the previous event.
* @return true if we're already at the beginning/end of the list and have nothing to do.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051739)
boolean trackMotionScroll(int deltaY, int incrementalDeltaY) {
final int childCount = getChildCount();
if (childCount == 0) {
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index ddff858..c55f7d6 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -21,6 +21,7 @@
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.database.DataSetObserver;
+import android.os.Build;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -152,7 +153,7 @@
/**
* True if the data has changed since the last layout
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768524)
boolean mDataChanged;
/**
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 7905c2e..904a862 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -126,7 +126,7 @@
private boolean mDropDownDismissedOnCompletion = true;
private int mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN;
- private boolean mOpenBefore;
+ private MyWatcher mAutoCompleteTextWatcher;
private Validator mValidator = null;
@@ -306,7 +306,8 @@
setFocusable(true);
- addTextChangedListener(new MyWatcher());
+ mAutoCompleteTextWatcher = new MyWatcher();
+ addTextChangedListener(mAutoCompleteTextWatcher);
mPassThroughClickListener = new PassThroughClickListener();
super.setOnClickListener(mPassThroughClickListener);
@@ -876,45 +877,66 @@
return getText().length() >= mThreshold;
}
- /**
- * This is used to watch for edits to the text view. Note that we call
- * to methods on the auto complete text view class so that we can access
- * private vars without going through thunks.
- */
+
+
+ /** This is used to watch for edits to the text view. */
private class MyWatcher implements TextWatcher {
- public void afterTextChanged(Editable s) {
- doAfterTextChanged();
- }
+ private boolean mOpenBefore;
+
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- doBeforeTextChanged();
+ if (mBlockCompletion) return;
+
+ // when text is changed, inserted or deleted, we attempt to show
+ // the drop down
+ mOpenBefore = isPopupShowing();
+ if (DEBUG) Log.v(TAG, "before text changed: open=" + mOpenBefore);
}
+
+ public void afterTextChanged(Editable s) {
+ if (mBlockCompletion) return;
+
+ // if the list was open before the keystroke, but closed afterwards,
+ // then something in the keystroke processing (an input filter perhaps)
+ // called performCompletion() and we shouldn't do any more processing.
+ if (DEBUG) {
+ Log.v(TAG, "after text changed: openBefore=" + mOpenBefore
+ + " open=" + isPopupShowing());
+ }
+
+ if (mOpenBefore && !isPopupShowing()) return;
+
+ refreshAutoCompleteResults();
+ }
+
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
- @UnsupportedAppUsage
+ /**
+ * This function is deprecated. Please use {@link #refreshAutoCompleteResults} instead.
+ * Note: Remove {@link #mAutoCompleteTextWatcher} after removing this function.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
void doBeforeTextChanged() {
- if (mBlockCompletion) return;
-
- // when text is changed, inserted or deleted, we attempt to show
- // the drop down
- mOpenBefore = isPopupShowing();
- if (DEBUG) Log.v(TAG, "before text changed: open=" + mOpenBefore);
+ mAutoCompleteTextWatcher.beforeTextChanged(null, 0, 0, 0);
}
- @UnsupportedAppUsage
+ /**
+ * This function is deprecated. Please use {@link #refreshAutoCompleteResults} instead.
+ * Note: Remove {@link #mAutoCompleteTextWatcher} after removing this function.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
void doAfterTextChanged() {
- if (mBlockCompletion) return;
+ mAutoCompleteTextWatcher.afterTextChanged(null);
+ }
- // if the list was open before the keystroke, but closed afterwards,
- // then something in the keystroke processing (an input filter perhaps)
- // called performCompletion() and we shouldn't do any more processing.
- if (DEBUG) Log.v(TAG, "after text changed: openBefore=" + mOpenBefore
- + " open=" + isPopupShowing());
- if (mOpenBefore && !isPopupShowing()) {
- return;
- }
-
+ /**
+ * Refreshes the auto complete results. You usually shouldn't have to manually refresh the
+ * AutoCompleteResults as this is done automatically whenever the text changes. However if the
+ * results are not available and have to be fetched, you can call this function after fetching
+ * the results.
+ */
+ public final void refreshAutoCompleteResults() {
// the drop down is shown only when a minimum number of characters
// was typed in the text view
if (enoughToFilter()) {
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 5175b14..25cfdc7 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -80,10 +81,24 @@
private final Rect mTempRect = new Rect();
@UnsupportedAppUsage
private OverScroller mScroller;
- @UnsupportedAppUsage
- private EdgeEffect mEdgeGlowLeft;
- @UnsupportedAppUsage
- private EdgeEffect mEdgeGlowRight;
+ /**
+ * Tracks the state of the left edge glow.
+ *
+ * Even though this field is practically final, we cannot make it final because there are apps
+ * setting it via reflection and they need to keep working until they target Q.
+ */
+ @NonNull
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124053130)
+ private EdgeEffect mEdgeGlowLeft = new EdgeEffect(getContext());
+
+ /**
+ * Tracks the state of the bottom edge glow.
+ *
+ * Even though this field is practically final, we cannot make it final because there are apps
+ * setting it via reflection and they need to keep working until they target Q.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124052619)
+ private EdgeEffect mEdgeGlowRight = new EdgeEffect(getContext());
/**
* Position of the last motion event.
@@ -218,6 +233,74 @@
}
/**
+ * Sets the edge effect color for both left and right edge effects.
+ *
+ * @param color The color for the edge effects.
+ * @see #setLeftEdgeEffectColor(int)
+ * @see #setRightEdgeEffectColor(int)
+ * @see #getLeftEdgeEffectColor()
+ * @see #getRightEdgeEffectColor()
+ */
+ public void setEdgeEffectColor(@ColorInt int color) {
+ setLeftEdgeEffectColor(color);
+ setRightEdgeEffectColor(color);
+ }
+
+ /**
+ * Sets the right edge effect color.
+ *
+ * @param color The color for the right edge effect.
+ * @see #setLeftEdgeEffectColor(int)
+ * @see #setEdgeEffectColor(int)
+ * @see #getLeftEdgeEffectColor()
+ * @see #getRightEdgeEffectColor()
+ */
+ public void setRightEdgeEffectColor(@ColorInt int color) {
+ mEdgeGlowRight.setColor(color);
+ }
+
+ /**
+ * Sets the left edge effect color.
+ *
+ * @param color The color for the left edge effect.
+ * @see #setRightEdgeEffectColor(int)
+ * @see #setEdgeEffectColor(int)
+ * @see #getLeftEdgeEffectColor()
+ * @see #getRightEdgeEffectColor()
+ */
+ public void setLeftEdgeEffectColor(@ColorInt int color) {
+ mEdgeGlowLeft.setColor(color);
+ }
+
+ /**
+ * Returns the left edge effect color.
+ *
+ * @return The left edge effect color.
+ * @see #setEdgeEffectColor(int)
+ * @see #setLeftEdgeEffectColor(int)
+ * @see #setRightEdgeEffectColor(int)
+ * @see #getRightEdgeEffectColor()
+ */
+ @ColorInt
+ public int getLeftEdgeEffectColor() {
+ return mEdgeGlowLeft.getColor();
+ }
+
+ /**
+ * Returns the right edge effect color.
+ *
+ * @return The right edge effect color.
+ * @see #setEdgeEffectColor(int)
+ * @see #setLeftEdgeEffectColor(int)
+ * @see #setRightEdgeEffectColor(int)
+ * @see #getLeftEdgeEffectColor()
+ */
+ @ColorInt
+ public int getRightEdgeEffectColor() {
+ return mEdgeGlowRight.getColor();
+ }
+
+ /**
* @return The maximum amount this scroll view will scroll in response to
* an arrow event.
*/
@@ -667,7 +750,7 @@
mEdgeGlowLeft.onRelease();
}
}
- if (mEdgeGlowLeft != null
+ if (shouldDisplayEdgeEffects()
&& (!mEdgeGlowLeft.isFinished() || !mEdgeGlowRight.isFinished())) {
postInvalidateOnAnimation();
}
@@ -695,7 +778,7 @@
mIsBeingDragged = false;
recycleVelocityTracker();
- if (mEdgeGlowLeft != null) {
+ if (shouldDisplayEdgeEffects()) {
mEdgeGlowLeft.onRelease();
mEdgeGlowRight.onRelease();
}
@@ -710,7 +793,7 @@
mIsBeingDragged = false;
recycleVelocityTracker();
- if (mEdgeGlowLeft != null) {
+ if (shouldDisplayEdgeEffects()) {
mEdgeGlowLeft.onRelease();
mEdgeGlowRight.onRelease();
}
@@ -1652,26 +1735,15 @@
}
}
- @Override
- public void setOverScrollMode(int mode) {
- if (mode != OVER_SCROLL_NEVER) {
- if (mEdgeGlowLeft == null) {
- Context context = getContext();
- mEdgeGlowLeft = new EdgeEffect(context);
- mEdgeGlowRight = new EdgeEffect(context);
- }
- } else {
- mEdgeGlowLeft = null;
- mEdgeGlowRight = null;
- }
- super.setOverScrollMode(mode);
+ private boolean shouldDisplayEdgeEffects() {
+ return getOverScrollMode() != OVER_SCROLL_NEVER;
}
@SuppressWarnings({"SuspiciousNameCombination"})
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
- if (mEdgeGlowLeft != null) {
+ if (shouldDisplayEdgeEffects()) {
final int scrollX = mScrollX;
if (!mEdgeGlowLeft.isFinished()) {
final int restoreCount = canvas.save();
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 1c8d5c2..9ae62ef 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -138,7 +138,7 @@
private int mDrawableWidth;
@UnsupportedAppUsage
private int mDrawableHeight;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051687)
private Matrix mDrawMatrix = null;
// Avoid allocations...
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index f9564b4..25e5dd3 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -471,11 +471,24 @@
* Specifies the anchor-relative bounds of the popup's transition
* epicenter.
*
- * @param bounds anchor-relative bounds
- * @hide
+ * @param bounds anchor-relative bounds, or {@code null} to use default epicenter
+ *
+ * @see #getEpicenterBounds()
*/
- public void setEpicenterBounds(Rect bounds) {
- mEpicenterBounds = bounds;
+ public void setEpicenterBounds(@Nullable Rect bounds) {
+ mEpicenterBounds = bounds != null ? new Rect(bounds) : null;
+ }
+
+ /**
+ * Returns bounds which are used as a popup's epicenter
+ * of the enter and exit transitions.
+ *
+ * @return bounds relative to anchor view, or {@code null} if not set
+ * @see #setEpicenterBounds(Rect)
+ */
+ @Nullable
+ public Rect getEpicenterBounds() {
+ return mEpicenterBounds != null ? new Rect(mEpicenterBounds) : null;
}
/**
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 705a371..2798296 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -264,7 +264,7 @@
private WeakReference<View> mAnchorRoot;
private boolean mIsAnchorRootAttached;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private final OnScrollChangedListener mOnScrollChangedListener = this::alignToAnchor;
private final View.OnLayoutChangeListener mOnLayoutChangeListener =
@@ -476,23 +476,40 @@
}
/**
- * Sets the bounds used as the epicenter of the enter and exit transitions.
- * <p>
- * Transitions use a point or Rect, referred to as the epicenter, to orient
+ * <p>Returns bounds which are used as a center of the enter and exit transitions.<p/>
+ *
+ * <p>Transitions use Rect, referred to as the epicenter, to orient
* the direction of travel. For popup windows, the anchor view bounds are
- * used as the default epicenter.
- * <p>
- * See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
- * information about how transition epicenters.
+ * used as the default epicenter.</p>
+ *
+ * <p>See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
+ * information about how transition epicenters work.</p>
+ *
+ * @return bounds relative to anchor view, or {@code null} if not set
+ * @see #setEpicenterBounds(Rect)
+ */
+ @Nullable
+ public Rect getEpicenterBounds() {
+ return mEpicenterBounds != null ? new Rect(mEpicenterBounds) : null;
+ }
+
+ /**
+ * <p>Sets the bounds used as the epicenter of the enter and exit transitions.</p>
+ *
+ * <p>Transitions use Rect, referred to as the epicenter, to orient
+ * the direction of travel. For popup windows, the anchor view bounds are
+ * used as the default epicenter.</p>
+ *
+ * <p>See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
+ * information about how transition epicenters work.</p>
*
* @param bounds the epicenter bounds relative to the anchor view, or
* {@code null} to use the default epicenter
- * @see #getTransitionEpicenter()
- * @hide
+ *
+ * @see #getEpicenterBounds()
*/
- @UnsupportedAppUsage
- public void setEpicenterBounds(Rect bounds) {
- mEpicenterBounds = bounds;
+ public void setEpicenterBounds(@Nullable Rect bounds) {
+ mEpicenterBounds = bounds != null ? new Rect(bounds) : null;
}
private Transition getTransition(int resId) {
@@ -865,12 +882,28 @@
}
/**
- * Clip this popup window to the screen, but not to the containing window.
+ * <p>Indicates whether this popup will be clipped to the screen and not to the
+ * containing window<p/>
*
- * @param enabled True to clip to the screen.
- * @hide
+ * @return true if popup will be clipped to the screen instead of the window, false otherwise
+ *
+ * @see #setClipToScreenEnabled(boolean)
*/
- @UnsupportedAppUsage
+ public boolean isClipToScreenEnabled() {
+ return mClipToScreen;
+ }
+
+ /**
+ * <p>Clip this popup window to the screen, but not to the containing window.</p>
+ *
+ * <p>If the popup is showing, calling this method will take effect only
+ * the next time the popup is shown or through a manual call to one of
+ * the {@link #update()} methods.</p>
+ *
+ * @param enabled true to clip to the screen.
+ *
+ * @see #isClipToScreenEnabled()
+ */
public void setClipToScreenEnabled(boolean enabled) {
mClipToScreen = enabled;
}
@@ -927,7 +960,8 @@
* for positioning.</p>
*
* @return true if the window will always be positioned in screen coordinates.
- * @hide
+ *
+ * @see #setLayoutInScreenEnabled(boolean)
*/
public boolean isLayoutInScreenEnabled() {
return mLayoutInScreen;
@@ -939,9 +973,9 @@
* This will cause the popup to be positioned in absolute screen coordinates.</p>
*
* @param enabled true if the popup should always be positioned in screen coordinates
- * @hide
+ *
+ * @see #isLayoutInScreenEnabled()
*/
- @UnsupportedAppUsage
public void setLayoutInScreenEnabled(boolean enabled) {
mLayoutInScreen = enabled;
}
@@ -1021,11 +1055,30 @@
}
/**
- * Set whether this window is touch modal or if outside touches will be sent to
- * other windows behind it.
- * @hide
+ * <p>Indicates whether outside touches will be sent to this window
+ * or other windows behind it<p/>
+ *
+ * @return true if touches will be sent to this window, false otherwise
+ *
+ * @see #setTouchModal(boolean)
*/
- @UnsupportedAppUsage
+ public boolean isTouchModal() {
+ return !mNotTouchModal;
+ }
+
+ /**
+ * <p>Set whether this window is touch modal or if outside touches will be sent to
+ * other windows behind it.<p/>
+ *
+ * <p>If the popup is showing, calling this method will take effect only
+ * the next time the popup is shown or through a manual call to one of
+ * the {@link #update()} methods.</p>
+ *
+ * @param touchModal true to sent all outside touches to this window,
+ * false to other windows behind it
+ *
+ * @see #isTouchModal()
+ */
public void setTouchModal(boolean touchModal) {
mNotTouchModal = !touchModal;
}
@@ -1454,7 +1507,7 @@
*
* @param p the layout parameters of the popup's content view
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private void invokePopup(WindowManager.LayoutParams p) {
if (mContext != null) {
p.packageName = mContext.getPackageName();
@@ -2060,6 +2113,8 @@
* <li>{@link #setInputMethodMode(int)}</li>
* <li>{@link #setTouchable(boolean)}</li>
* <li>{@link #setAnimationStyle(int)}</li>
+ * <li>{@link #setTouchModal(boolean)} (boolean)}</li>
+ * <li>{@link #setClipToScreenEnabled(boolean)}</li>
* </ul>
*/
public void update() {
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 45d4c70..29f070e 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -203,7 +203,7 @@
private int mDuration;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private boolean mIndeterminate;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 124049927)
private boolean mOnlyIndeterminate;
private Transformation mTransformation;
private AlphaAnimation mAnimation;
@@ -211,7 +211,12 @@
private Drawable mIndeterminateDrawable;
private Drawable mProgressDrawable;
- @UnsupportedAppUsage
+ /**
+ * Outside the framework, instead of accessing this directly, please use
+ * {@link #getCurrentDrawable()}, {@link #setProgressDrawable(Drawable)},
+ * {@link #setIndeterminateDrawable(Drawable)} and their tiled versions.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private Drawable mCurrentDrawable;
private ProgressTintInfo mProgressTintInfo;
@@ -1300,9 +1305,14 @@
}
/**
- * @return The drawable currently used to draw the progress bar
+ * Returns the drawable currently used to draw the progress bar. This will be
+ * either {@link #getProgressDrawable()} or {@link #getIndeterminateDrawable()}
+ * depending on whether the progress bar is in determinate or indeterminate mode.
+ *
+ * @return the drawable currently used to draw the progress bar
*/
- Drawable getCurrentDrawable() {
+ @Nullable
+ public Drawable getCurrentDrawable() {
return mCurrentDrawable;
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 123943c..7e72c6a 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -89,10 +90,25 @@
private final Rect mTempRect = new Rect();
@UnsupportedAppUsage
private OverScroller mScroller;
- @UnsupportedAppUsage
- private EdgeEffect mEdgeGlowTop;
- @UnsupportedAppUsage
- private EdgeEffect mEdgeGlowBottom;
+ /**
+ * Tracks the state of the top edge glow.
+ *
+ * Even though this field is practically final, we cannot make it final because there are apps
+ * setting it via reflection and they need to keep working until they target Q.
+ */
+ @NonNull
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768600)
+ private EdgeEffect mEdgeGlowTop = new EdgeEffect(getContext());
+
+ /**
+ * Tracks the state of the bottom edge glow.
+ *
+ * Even though this field is practically final, we cannot make it final because there are apps
+ * setting it via reflection and they need to keep working until they target Q.
+ */
+ @NonNull
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769386)
+ private EdgeEffect mEdgeGlowBottom = new EdgeEffect(getContext());
/**
* Position of the last motion event.
@@ -141,13 +157,13 @@
private boolean mSmoothScrollingEnabled = true;
private int mTouchSlop;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051125)
private int mMinimumVelocity;
private int mMaximumVelocity;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.P, trackingBug = 124050903)
private int mOverscrollDistance;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.P, trackingBug = 124050903)
private int mOverflingDistance;
private float mVerticalScrollFactor;
@@ -249,6 +265,74 @@
}
/**
+ * Sets the edge effect color for both top and bottom edge effects.
+ *
+ * @param color The color for the edge effects.
+ * @see #setTopEdgeEffectColor(int)
+ * @see #setBottomEdgeEffectColor(int)
+ * @see #getTopEdgeEffectColor()
+ * @see #getBottomEdgeEffectColor()
+ */
+ public void setEdgeEffectColor(@ColorInt int color) {
+ setTopEdgeEffectColor(color);
+ setBottomEdgeEffectColor(color);
+ }
+
+ /**
+ * Sets the bottom edge effect color.
+ *
+ * @param color The color for the bottom edge effect.
+ * @see #setTopEdgeEffectColor(int)
+ * @see #setEdgeEffectColor(int)
+ * @see #getTopEdgeEffectColor()
+ * @see #getBottomEdgeEffectColor()
+ */
+ public void setBottomEdgeEffectColor(@ColorInt int color) {
+ mEdgeGlowBottom.setColor(color);
+ }
+
+ /**
+ * Sets the top edge effect color.
+ *
+ * @param color The color for the top edge effect.
+ * @see #setBottomEdgeEffectColor(int)
+ * @see #setEdgeEffectColor(int)
+ * @see #getTopEdgeEffectColor()
+ * @see #getBottomEdgeEffectColor()
+ */
+ public void setTopEdgeEffectColor(@ColorInt int color) {
+ mEdgeGlowTop.setColor(color);
+ }
+
+ /**
+ * Returns the top edge effect color.
+ *
+ * @return The top edge effect color.
+ * @see #setEdgeEffectColor(int)
+ * @see #setTopEdgeEffectColor(int)
+ * @see #setBottomEdgeEffectColor(int)
+ * @see #getBottomEdgeEffectColor()
+ */
+ @ColorInt
+ public int getTopEdgeEffectColor() {
+ return mEdgeGlowTop.getColor();
+ }
+
+ /**
+ * Returns the bottom edge effect color.
+ *
+ * @return The bottom edge effect color.
+ * @see #setEdgeEffectColor(int)
+ * @see #setTopEdgeEffectColor(int)
+ * @see #setBottomEdgeEffectColor(int)
+ * @see #getTopEdgeEffectColor()
+ */
+ @ColorInt
+ public int getBottomEdgeEffectColor() {
+ return mEdgeGlowBottom.getColor();
+ }
+
+ /**
* @return The maximum amount this scroll view will scroll in response to
* an arrow event.
*/
@@ -626,6 +710,10 @@
return mIsBeingDragged;
}
+ private boolean shouldDisplayEdgeEffects() {
+ return getOverScrollMode() != OVER_SCROLL_NEVER;
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
initVelocityTrackerIfNotExists();
@@ -734,7 +822,7 @@
mEdgeGlowTop.onRelease();
}
}
- if (mEdgeGlowTop != null
+ if (shouldDisplayEdgeEffects()
&& (!mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished())) {
postInvalidateOnAnimation();
}
@@ -1672,7 +1760,7 @@
recycleVelocityTracker();
- if (mEdgeGlowTop != null) {
+ if (shouldDisplayEdgeEffects()) {
mEdgeGlowTop.onRelease();
mEdgeGlowBottom.onRelease();
}
@@ -1702,21 +1790,6 @@
}
@Override
- public void setOverScrollMode(int mode) {
- if (mode != OVER_SCROLL_NEVER) {
- if (mEdgeGlowTop == null) {
- Context context = getContext();
- mEdgeGlowTop = new EdgeEffect(context);
- mEdgeGlowBottom = new EdgeEffect(context);
- }
- } else {
- mEdgeGlowTop = null;
- mEdgeGlowBottom = null;
- }
- super.setOverScrollMode(mode);
- }
-
- @Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return (nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0;
}
@@ -1760,7 +1833,7 @@
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
- if (mEdgeGlowTop != null) {
+ if (shouldDisplayEdgeEffects()) {
final int scrollY = mScrollY;
final boolean clipToPadding = getClipToPadding();
if (!mEdgeGlowTop.isFinished()) {
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index a3a92d3..616c4b5 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -612,8 +612,16 @@
resolver.registerContentObserver(uri, true,
mFormatChangeObserver, UserHandle.USER_ALL);
} else {
+ // UserHandle.myUserId() is needed. This class is supported by the
+ // remote views mechanism and as a part of that the remote views
+ // can be inflated by a context for another user without the app
+ // having interact users permission - just for loading resources.
+ // For example, when adding widgets from a managed profile to the
+ // home screen. Therefore, we register the ContentObserver with the user
+ // the app is running (e.g. the launcher) and not the user of the
+ // context (e.g. the widget's profile).
resolver.registerContentObserver(uri, true,
- mFormatChangeObserver);
+ mFormatChangeObserver, UserHandle.myUserId());
}
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d876001..51eaa12 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -664,7 +664,7 @@
@UnsupportedAppUsage
private CharWrapper mCharWrapper;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 124050217)
private Marquee mMarquee;
@UnsupportedAppUsage
private boolean mRestartMarquee;
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java
index c171fa6..258d081 100644
--- a/core/java/com/android/internal/colorextraction/ColorExtractor.java
+++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java
@@ -22,7 +22,6 @@
import android.app.WallpaperManager;
import android.content.Context;
import android.os.Trace;
-import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArray;
@@ -32,7 +31,6 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Iterator;
/**
* Class to process wallpaper colors and generate a tonal palette based on them.
@@ -222,6 +220,7 @@
public static class GradientColors {
private int mMainColor;
private int mSecondaryColor;
+ private int[] mColorPalette;
private boolean mSupportsDarkText;
public void setMainColor(int mainColor) {
@@ -232,6 +231,10 @@
mSecondaryColor = secondaryColor;
}
+ public void setColorPalette(int[] colorPalette) {
+ mColorPalette = colorPalette;
+ }
+
public void setSupportsDarkText(boolean supportsDarkText) {
mSupportsDarkText = supportsDarkText;
}
@@ -239,6 +242,7 @@
public void set(GradientColors other) {
mMainColor = other.mMainColor;
mSecondaryColor = other.mSecondaryColor;
+ mColorPalette = other.mColorPalette;
mSupportsDarkText = other.mSupportsDarkText;
}
@@ -250,6 +254,10 @@
return mSecondaryColor;
}
+ public int[] getColorPalette() {
+ return mColorPalette;
+ }
+
public boolean supportsDarkText() {
return mSupportsDarkText;
}
@@ -283,4 +291,4 @@
public interface OnColorsChangedListener {
void onColorsChanged(ColorExtractor colorExtractor, int which);
}
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/colorextraction/types/Tonal.java b/core/java/com/android/internal/colorextraction/types/Tonal.java
index 3fd88db..d6a8934 100644
--- a/core/java/com/android/internal/colorextraction/types/Tonal.java
+++ b/core/java/com/android/internal/colorextraction/types/Tonal.java
@@ -173,6 +173,7 @@
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);
+ int[] colorPalette = getColorPalette(h, s, l);
if (DEBUG) {
StringBuilder builder = new StringBuilder("Tonal Palette - index: " + fitIndex +
@@ -209,6 +210,7 @@
// Normal colors:
outColorsNormal.setMainColor(mainColor);
outColorsNormal.setSecondaryColor(mainColor);
+ outColorsNormal.setColorPalette(colorPalette);
// Dark colors:
// Stops at 4th color, only lighter if dark text is supported
@@ -222,6 +224,7 @@
mainColor = getColorInt(primaryIndex, h, s, l);
outColorsDark.setMainColor(mainColor);
outColorsDark.setSecondaryColor(mainColor);
+ outColorsDark.setColorPalette(colorPalette);
// Extra Dark:
// Stay close to dark colors until dark text is supported
@@ -235,6 +238,7 @@
mainColor = getColorInt(primaryIndex, h, s, l);
outColorsExtraDark.setMainColor(mainColor);
outColorsExtraDark.setSecondaryColor(mainColor);
+ outColorsExtraDark.setColorPalette(colorPalette);
outColorsNormal.setSupportsDarkText(supportsDarkText);
outColorsDark.setSupportsDarkText(supportsDarkText);
@@ -262,16 +266,19 @@
* @param inWallpaperColors Colors to read.
* @param outGradientColors Destination.
*/
- public static void applyFallback(@Nullable WallpaperColors inWallpaperColors,
+ public void applyFallback(@Nullable WallpaperColors inWallpaperColors,
@NonNull GradientColors outGradientColors) {
boolean light = inWallpaperColors != null
&& (inWallpaperColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT)
!= 0;
final int color = light ? MAIN_COLOR_LIGHT : MAIN_COLOR_DARK;
+ final float[] hsl = new float[3];
+ ColorUtils.colorToHSL(color, hsl);
outGradientColors.setMainColor(color);
outGradientColors.setSecondaryColor(color);
outGradientColors.setSupportsDarkText(light);
+ outGradientColors.setColorPalette(getColorPalette(findTonalPalette(hsl[0], hsl[1])));
}
private int getColorInt(int fitIndex, float[] h, float[] s, float[] l) {
@@ -281,6 +288,19 @@
return ColorUtils.HSLToColor(mTmpHSL);
}
+ private int[] getColorPalette(float[] h, float[] s, float[] l) {
+ int[] colorPalette = new int[h.length];
+ for (int i = 0; i < colorPalette.length; i++) {
+ colorPalette[i] = getColorInt(i, h, s, l);
+ }
+ return colorPalette;
+ }
+
+ private int[] getColorPalette(TonalPalette palette) {
+ return getColorPalette(palette.h, palette.s, palette.l);
+ }
+
+
/**
* Checks if a given color exists in the blacklist
* @param hsl float array with 3 components (H 0..360, S 0..1 and L 0..1)
@@ -598,4 +618,4 @@
return numbers;
}
}
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 650a194..52e1748 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -6117,8 +6117,6 @@
for (int i=0; i<N; i++) {
final int uid = mapUid(ws.get(i));
noteFullWifiLockAcquiredLocked(uid);
- StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
- StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -6127,9 +6125,6 @@
final WorkChain workChain = workChains.get(i);
final int uid = mapUid(workChain.getAttributionUid());
noteFullWifiLockAcquiredLocked(uid);
- StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
- workChain.getUids(), workChain.getTags(),
- StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
}
}
}
@@ -6139,8 +6134,6 @@
for (int i=0; i<N; i++) {
final int uid = mapUid(ws.get(i));
noteFullWifiLockReleasedLocked(uid);
- StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
- StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -6149,9 +6142,6 @@
final WorkChain workChain = workChains.get(i);
final int uid = mapUid(workChain.getAttributionUid());
noteFullWifiLockReleasedLocked(uid);
- StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
- workChain.getUids(), workChain.getTags(),
- StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
}
}
}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 2c272de..7f4d8a2 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -52,6 +52,8 @@
public static final boolean ENABLED_DEFAULT = true;
public static final boolean DETAILED_TRACKING_DEFAULT = true;
public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 100;
+ public static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false;
+ public static final boolean DEFAULT_TRACK_DIRECT_CALLING_UID = true;
public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 5000;
private static final String DEBUG_ENTRY_PREFIX = "__DEBUG_";
@@ -85,6 +87,8 @@
private long mStartElapsedTime = SystemClock.elapsedRealtime();
private long mCallStatsCount = 0;
private boolean mAddDebugEntries = false;
+ private boolean mTrackDirectCallingUid = DEFAULT_TRACK_DIRECT_CALLING_UID;
+ private boolean mTrackScreenInteractive = DEFAULT_TRACK_SCREEN_INTERACTIVE;
private CachedDeviceState.Readonly mDeviceState;
private CachedDeviceState.TimeInStateStopwatch mBatteryStopwatch;
@@ -160,7 +164,12 @@
duration = 0;
latencyDuration = 0;
}
- final int callingUid = getCallingUid();
+ final boolean screenInteractive = mTrackScreenInteractive
+ ? mDeviceState.isScreenInteractive()
+ : OVERFLOW_SCREEN_INTERACTIVE;
+ final int callingUid = mTrackDirectCallingUid
+ ? getCallingUid()
+ : OVERFLOW_DIRECT_CALLING_UID;
synchronized (mLock) {
// This was already checked in #callStart but check again while synchronized.
@@ -177,7 +186,7 @@
final CallStat callStat = uidEntry.getOrCreate(
callingUid, s.binderClass, s.transactionCode,
- mDeviceState.isScreenInteractive(),
+ screenInteractive,
mCallStatsCount >= mMaxBinderCallStatsCount);
final boolean isNewCallStat = callStat.callCount == 0;
if (isNewCallStat) {
@@ -484,6 +493,30 @@
}
}
+ /**
+ * Whether to track the screen state.
+ */
+ public void setTrackScreenInteractive(boolean enabled) {
+ synchronized (mLock) {
+ if (enabled != mTrackScreenInteractive) {
+ mTrackScreenInteractive = enabled;
+ reset();
+ }
+ }
+ }
+
+ /**
+ * Whether to track direct caller uid.
+ */
+ public void setTrackDirectCallerUid(boolean enabled) {
+ synchronized (mLock) {
+ if (enabled != mTrackDirectCallingUid) {
+ mTrackDirectCallingUid = enabled;
+ reset();
+ }
+ }
+ }
+
public void setAddDebugEntries(boolean addDebugEntries) {
mAddDebugEntries = addDebugEntries;
}
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index b3d9ca7..c059721 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -39,6 +39,7 @@
public class LooperStats implements Looper.Observer {
public static final String DEBUG_ENTRY_PREFIX = "__DEBUG_";
private static final int SESSION_POOL_SIZE = 50;
+ private static final boolean DISABLED_SCREEN_STATE_TRACKING_VALUE = false;
@GuardedBy("mLock")
private final SparseArray<Entry> mEntries = new SparseArray<>(512);
@@ -54,6 +55,7 @@
private long mStartCurrentTime = System.currentTimeMillis();
private long mStartElapsedTime = SystemClock.elapsedRealtime();
private boolean mAddDebugEntries = false;
+ private boolean mTrackScreenInteractive = false;
public LooperStats(int samplingInterval, int entriesSizeCap) {
this.mSamplingInterval = samplingInterval;
@@ -218,9 +220,15 @@
mSamplingInterval = samplingInterval;
}
+ public void setTrackScreenInteractive(boolean enabled) {
+ mTrackScreenInteractive = enabled;
+ }
+
@Nullable
private Entry findEntry(Message msg, boolean allowCreateNew) {
- final boolean isInteractive = mDeviceState.isScreenInteractive();
+ final boolean isInteractive = mTrackScreenInteractive
+ ? mDeviceState.isScreenInteractive()
+ : DISABLED_SCREEN_STATE_TRACKING_VALUE;
final int id = Entry.idFor(msg, isInteractive);
Entry entry;
synchronized (mLock) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 8b669d5..40d7868 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -254,14 +254,14 @@
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
- String packageName, String[] packagesForUID, String[] visibleVolIDs) {
+ String packageName, String[] packagesForUID, String[] visibleVolIDs, String sandboxId) {
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, packageName,
- packagesForUID, visibleVolIDs);
+ packagesForUID, visibleVolIDs, sandboxId);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
@@ -276,7 +276,8 @@
private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
- String appDataDir, String packageName, String[] packagesForUID, String[] visibleVolIDs);
+ String appDataDir, String packageName, String[] packagesForUID, String[] visibleVolIDs,
+ String sandboxId);
/**
* Specialize a Blastula instance. The current VM must have been started
@@ -302,11 +303,11 @@
public static void specializeBlastula(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
- String[] packagesForUID, String[] visibleVolIDs) {
+ String[] packagesForUID, String[] visibleVolIDs, String sandboxId) {
nativeSpecializeBlastula(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
niceName, startChildZygote, instructionSet, appDataDir,
- packageName, packagesForUID, visibleVolIDs);
+ packageName, packagesForUID, visibleVolIDs, sandboxId);
// Enable tracing as soon as possible for the child process.
Trace.setTracingEnabled(true, runtimeFlags);
@@ -326,7 +327,7 @@
private static native void nativeSpecializeBlastula(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
- String[] packagesForUID, String[] visibleVolIDs);
+ String[] packagesForUID, String[] visibleVolIDs, String sandboxId);
/**
* Called to do any initialization before starting an application.
@@ -638,7 +639,7 @@
args.mRuntimeFlags, rlimits, args.mMountExternal,
args.mSeInfo, args.mNiceName, args.mStartChildZygote,
args.mInstructionSet, args.mAppDataDir, args.mPackageName,
- args.mPackagesForUid, args.mVisibleVolIds);
+ args.mPackagesForUid, args.mVisibleVolIds, args.mSandboxId);
if (args.mNiceName != null) {
Process.setArgV0(args.mNiceName);
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 24a08ca..e6bcd37 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -119,6 +119,9 @@
/** from --visible-vols */
String[] mVisibleVolIds;
+ /** from --sandbox-id */
+ String mSandboxId;
+
/**
* Any args after and including the first non-option arg (or after a '--')
*/
@@ -385,6 +388,11 @@
mPackagesForUid = arg.substring(arg.indexOf('=') + 1).split(",");
} else if (arg.startsWith("--visible-vols=")) {
mVisibleVolIds = arg.substring(arg.indexOf('=') + 1).split(",");
+ } else if (arg.startsWith("--sandbox-id=")) {
+ if (mSandboxId != null) {
+ throw new IllegalArgumentException("Duplicate arg specified");
+ }
+ mSandboxId = arg.substring(arg.indexOf('=') + 1);
} else {
break;
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 4ac7f50..9cf7e27 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -258,7 +258,7 @@
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mPackageName,
- parsedArgs.mPackagesForUid, parsedArgs.mVisibleVolIds);
+ parsedArgs.mPackagesForUid, parsedArgs.mVisibleVolIds, parsedArgs.mSandboxId);
try {
if (pid == 0) {
diff --git a/core/jni/android_opengl_EGL15.cpp b/core/jni/android_opengl_EGL15.cpp
index b52f137..2abd950 100644
--- a/core/jni/android_opengl_EGL15.cpp
+++ b/core/jni/android_opengl_EGL15.cpp
@@ -194,6 +194,7 @@
if (obj == NULL){
jniThrowException(_env, "java/lang/IllegalArgumentException",
"Object is set to null.");
+ return nullptr;
}
jlong handle = _env->CallLongMethod(obj, mid);
@@ -254,6 +255,7 @@
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
+ return nullptr;
}
return toEGLHandle(_env, eglsyncClass, eglsyncConstructor, _returnValue);
}
@@ -335,6 +337,7 @@
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
+ return false;
}
return (jboolean)_returnValue;
}
@@ -381,6 +384,7 @@
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
+ return nullptr;
}
return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
}
@@ -448,6 +452,7 @@
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
+ return nullptr;
}
return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
}
@@ -456,8 +461,11 @@
static jobject
android_eglCreatePlatformPixmapSurface
(JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject native_pixmap_buf, jlongArray attrib_list_ref, jint offset) {
- jniThrowException(_env, "java/lang/UnsupportedOperationException",
- "eglCreatePlatformPixmapSurface");
+ if ((true)) {
+ jniThrowException(_env, "java/lang/UnsupportedOperationException",
+ "eglCreatePlatformPixmapSurface");
+ return nullptr;
+ }
return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, (EGLSurface) 0);
}
@@ -523,6 +531,7 @@
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
+ return nullptr;
}
return toEGLHandle(_env, eglimageClass, eglimageConstructor, _returnValue);
}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index d493ddf..a212f47 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -104,6 +104,12 @@
jfieldID mScreenHeightDpOffset;
} gConfigurationOffsets;
+static struct arraymap_offsets_t {
+ jclass classObject;
+ jmethodID constructor;
+ jmethodID put;
+} gArrayMapOffsets;
+
jclass g_stringClass = nullptr;
// ----------------------------------------------------------------------------
@@ -326,6 +332,50 @@
return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr));
}
+static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr,
+ jstring package_name) {
+ ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+ const ScopedUtfChars package_name_utf8(env, package_name);
+ CHECK(package_name_utf8.c_str() != nullptr);
+ const std::string std_package_name(package_name_utf8.c_str());
+ const std::unordered_map<std::string, std::string>* map = nullptr;
+
+ assetmanager->ForEachPackage([&](const std::string& this_package_name, uint8_t package_id) {
+ if (this_package_name == std_package_name) {
+ map = assetmanager->GetOverlayableMapForPackage(package_id);
+ }
+ });
+
+ if (map == nullptr) {
+ return nullptr;
+ }
+
+ jobject array_map = env->NewObject(gArrayMapOffsets.classObject, gArrayMapOffsets.constructor);
+ if (array_map == nullptr) {
+ return nullptr;
+ }
+
+ for (const auto& iter : *map) {
+ jstring name = env->NewStringUTF(iter.first.c_str());
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
+
+ jstring actor = env->NewStringUTF(iter.second.c_str());
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(name);
+ return nullptr;
+ }
+
+ env->CallObjectMethod(array_map, gArrayMapOffsets.put, name, actor);
+
+ env->DeleteLocalRef(name);
+ env->DeleteLocalRef(actor);
+ }
+
+ return array_map;
+}
+
static jobject ReturnParcelFileDescriptor(JNIEnv* env, std::unique_ptr<Asset> asset,
jlongArray out_offsets) {
off64_t start_offset, length;
@@ -1524,6 +1574,8 @@
{"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
{"nativeCreateIdmapsForStaticOverlaysTargetingAndroid", "()[Ljava/lang/String;",
(void*)NativeCreateIdmapsForStaticOverlaysTargetingAndroid},
+ {"nativeGetOverlayableMap", "(JLjava/lang/String;)Ljava/util/Map;",
+ (void*)NativeGetOverlayableMap},
// Global management/debug methods.
{"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount},
@@ -1575,6 +1627,14 @@
gConfigurationOffsets.mScreenHeightDpOffset =
GetFieldIDOrDie(env, configurationClass, "screenHeightDp", "I");
+ jclass arrayMapClass = FindClassOrDie(env, "android/util/ArrayMap");
+ gArrayMapOffsets.classObject = MakeGlobalRefOrDie(env, arrayMapClass);
+ gArrayMapOffsets.constructor =
+ GetMethodIDOrDie(env, gArrayMapOffsets.classObject, "<init>", "()V");
+ gArrayMapOffsets.put =
+ GetMethodIDOrDie(env, gArrayMapOffsets.classObject, "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+
return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
NELEM(gAssetManagerMethods));
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 0ef4f87..d04db92 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -598,72 +598,80 @@
return 0;
}
+static void CreateDir(const std::string& dir,
+ mode_t mode, uid_t uid, gid_t gid,
+ fail_fn_t fail_fn) {
+ if (TEMP_FAILURE_RETRY(access(dir.c_str(), F_OK)) == 0) {
+ return;
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to stat %s: %s", dir.c_str(), strerror(errno)));
+ }
+ if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
+ fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s: %s",
+ dir.c_str(), strerror(errno)));
+ }
+}
+
static void CreatePkgSandbox(uid_t uid, const std::string& package_name, fail_fn_t fail_fn) {
// Create /mnt/user/0/package/<package-name>
userid_t user_id = multiuser_get_user_id(uid);
std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
- if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0751, AID_ROOT, AID_ROOT) != 0) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()));
- }
+ CreateDir(pkg_sandbox_dir, 0751, AID_ROOT, AID_ROOT, fail_fn);
StringAppendF(&pkg_sandbox_dir, "/package");
- if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()));
- }
+ CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn);
StringAppendF(&pkg_sandbox_dir, "/%s", package_name.c_str());
- if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0755, uid, uid) != 0) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()));
- }
+ CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn);
}
static void BindMount(const std::string& sourceDir, const std::string& targetDir,
fail_fn_t fail_fn) {
if (TEMP_FAILURE_RETRY(mount(sourceDir.c_str(), targetDir.c_str(), nullptr,
- MS_BIND | MS_REC, nullptr)) == -1) {
+ MS_BIND, nullptr)) == -1) {
fail_fn(CREATE_ERROR("Failed to mount %s to %s: %s",
sourceDir.c_str(), targetDir.c_str(), strerror(errno)));
}
-
- if (TEMP_FAILURE_RETRY(mount(nullptr, targetDir.c_str(), nullptr,
- MS_SLAVE | MS_REC, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to set MS_SLAVE for %s", targetDir.c_str()));
- }
}
static void MountPkgSpecificDir(const std::string& mntSourceRoot,
const std::string& mntTargetRoot,
const std::string& packageName,
+ uid_t uid,
const char* dirName,
fail_fn_t fail_fn) {
std::string mntSourceDir = StringPrintf("%s/Android/%s/%s",
mntSourceRoot.c_str(), dirName, packageName.c_str());
+ CreateDir(mntSourceDir, 0755, uid, uid, fail_fn);
+
std::string mntTargetDir = StringPrintf("%s/Android/%s/%s",
mntTargetRoot.c_str(), dirName, packageName.c_str());
+ CreateDir(mntTargetDir, 0755, uid, uid, fail_fn);
BindMount(mntSourceDir, mntTargetDir, fail_fn);
}
+
+static void createPkgSpecificDirRoots(const std::string& parentDir,
+ bool createSandbox,
+ mode_t mode, uid_t uid, gid_t gid,
+ fail_fn_t fail_fn) {
+ std::string androidDir = StringPrintf("%s/Android", parentDir.c_str());
+ CreateDir(androidDir, mode, uid, gid, fail_fn);
+ std::vector<std::string> dirs = {"data", "media", "obb"};
+ if (createSandbox) {
+ dirs.push_back("sandbox");
+ }
+ for (auto& dir : dirs) {
+ std::string path = StringPrintf("%s/%s", androidDir.c_str(), dir.c_str());
+ CreateDir(path, mode, uid, gid, fail_fn);
+ }
+}
+
static void PreparePkgSpecificDirs(const std::vector<std::string>& packageNames,
const std::vector<std::string>& volumeLabels,
- bool mountAllObbs, userid_t userId, fail_fn_t fail_fn) {
- if (volumeLabels.size() > 0) {
- std::string sandboxDataDir = StringPrintf("/storage/%s", volumeLabels[0].c_str());
- if (volumeLabels[0] == "emulated") {
- StringAppendF(&sandboxDataDir, "/%d", userId);
- }
- StringAppendF(&sandboxDataDir, "/Android/data/%s", packageNames[0].c_str());
- struct stat sb;
- if (TEMP_FAILURE_RETRY(lstat(sandboxDataDir.c_str(), &sb)) == -1) {
- if (errno == ENOENT) {
- ALOGD("Sandbox not fully prepared for %s", sandboxDataDir.c_str());
- return;
- } else {
- fail_fn(CREATE_ERROR("Failed to lstat %s: %s",
- sandboxDataDir.c_str(), strerror(errno)));
- }
- }
- }
+ bool mountAllObbs, const std::string& sandboxId,
+ userid_t userId, uid_t uid, fail_fn_t fail_fn) {
for (auto& label : volumeLabels) {
std::string mntSource = StringPrintf("/mnt/runtime/write/%s", label.c_str());
std::string mntTarget = StringPrintf("/storage/%s", label.c_str());
@@ -672,11 +680,26 @@
StringAppendF(&mntTarget, "/%d", userId);
}
+ if (TEMP_FAILURE_RETRY(access(mntSource.c_str(), F_OK)) < 0) {
+ ALOGE("Can't access %s: %s", mntSource.c_str(), strerror(errno));
+ continue;
+ }
+
+ // Create /mnt/runtime/write/emulated/0/Android/{data,media,obb,sandbox}
+ createPkgSpecificDirRoots(mntSource, true, 0700, AID_ROOT, AID_ROOT, fail_fn);
+
+ std::string sandboxSource = StringPrintf("%s/Android/sandbox/%s",
+ mntSource.c_str(), sandboxId.c_str());
+ CreateDir(sandboxSource, 0755, uid, uid, fail_fn);
+ BindMount(sandboxSource, mntTarget, fail_fn);
+
+ // Create /storage/emulated/0/Android/{data,media,obb}
+ createPkgSpecificDirRoots(mntTarget, false, 0755, uid, uid, fail_fn);
for (auto& package : packageNames) {
- MountPkgSpecificDir(mntSource, mntTarget, package, "data", fail_fn);
- MountPkgSpecificDir(mntSource, mntTarget, package, "media", fail_fn);
+ MountPkgSpecificDir(mntSource, mntTarget, package, uid, "data", fail_fn);
+ MountPkgSpecificDir(mntSource, mntTarget, package, uid, "media", fail_fn);
if (!mountAllObbs) {
- MountPkgSpecificDir(mntSource, mntTarget, package, "obb", fail_fn);
+ MountPkgSpecificDir(mntSource, mntTarget, package, uid, "obb", fail_fn);
}
}
@@ -693,7 +716,8 @@
static void MountEmulatedStorage(uid_t uid, jint mount_mode,
bool force_mount_namespace, const std::string& package_name,
const std::vector<std::string>& packages_for_uid,
- const std::vector<std::string>& visible_vol_ids, fail_fn_t fail_fn) {
+ const std::vector<std::string>& visible_vol_ids, const std::string& sandbox_id,
+ fail_fn_t fail_fn) {
// See storage config details at http://source.android.com/tech/storage/
String8 storageSource;
@@ -744,7 +768,7 @@
strerror(errno)));
}
} else {
- if (package_name.empty()) {
+ if (package_name.empty() || sandbox_id.empty()) {
return;
}
@@ -790,7 +814,7 @@
// care of by vold later.
if (sandboxAlreadyCreated) {
PreparePkgSpecificDirs(packages_for_uid, visible_vol_ids,
- mount_mode == MOUNT_EXTERNAL_INSTALLER, user_id, fail_fn);
+ mount_mode == MOUNT_EXTERNAL_INSTALLER, sandbox_id, user_id, uid, fail_fn);
}
}
} else {
@@ -1127,7 +1151,7 @@
bool is_child_zygote, jstring managed_instruction_set,
jstring managed_app_data_dir, jstring managed_package_name,
jobjectArray managed_pacakges_for_uid,
- jobjectArray managed_visible_vol_ids) {
+ jobjectArray managed_visible_vol_ids, jstring managed_sandbox_id) {
const char* process_name = is_system_server ? "system_server" : "zygote";
auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1137,6 +1161,7 @@
auto instruction_set = extract_fn(managed_instruction_set);
auto app_data_dir = extract_fn(managed_app_data_dir);
auto package_name = extract_fn(managed_package_name);
+ auto sandbox_id = extract_fn(managed_sandbox_id);
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
@@ -1179,7 +1204,7 @@
value_or(std::vector<std::string>());
MountEmulatedStorage(uid, mount_external, use_native_bridge, package_name.value(),
- packages_for_uid, visible_vol_ids, fail_fn);
+ packages_for_uid, visible_vol_ids, sandbox_id.value_or(""), fail_fn);
// If this zygote isn't root, it won't be able to create a process group,
// since the directory is owned by root.
@@ -1479,7 +1504,7 @@
jint mount_external, jstring se_info, jstring nice_name,
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
jstring instruction_set, jstring app_data_dir, jstring package_name,
- jobjectArray packages_for_uid, jobjectArray visible_vol_ids) {
+ jobjectArray packages_for_uid, jobjectArray visible_vol_ids, jstring sandbox_id) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -1511,7 +1536,7 @@
capabilities, capabilities,
mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
- package_name, packages_for_uid, visible_vol_ids);
+ package_name, packages_for_uid, visible_vol_ids, sandbox_id);
}
return pid;
}
@@ -1537,7 +1562,7 @@
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
permitted_capabilities, effective_capabilities,
MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
- false, nullptr, nullptr, nullptr, nullptr, nullptr);
+ false, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -1691,14 +1716,15 @@
jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring nice_name,
jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir,
- jstring package_name, jobjectArray packages_for_uid, jobjectArray visible_vol_ids) {
+ jstring package_name, jobjectArray packages_for_uid, jobjectArray visible_vol_ids,
+ jstring sandbox_id) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
capabilities, capabilities,
mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
- package_name, packages_for_uid, visible_vol_ids);
+ package_name, packages_for_uid, visible_vol_ids, sandbox_id);
}
/**
@@ -1789,7 +1815,7 @@
{ "nativeSecurityInit", "()V",
(void *) com_android_internal_os_Zygote_nativeSecurityInit },
{ "nativeForkAndSpecialize",
- "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)I",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
(void *) com_android_internal_os_Zygote_nativeForkSystemServer },
@@ -1804,7 +1830,7 @@
{ "nativeForkBlastula", "(II[I)I",
(void *) com_android_internal_os_Zygote_nativeForkBlastula },
{ "nativeSpecializeBlastula",
- "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V",
(void *) com_android_internal_os_Zygote_nativeSpecializeBlastula },
{ "nativeGetSocketFDs", "(Z)V",
(void *) com_android_internal_os_Zygote_nativeGetSocketFDs },
diff --git a/core/jni/runtime_native_boot-flags-test.sh b/core/jni/runtime_native_boot-flags-test.sh
new file mode 100755
index 0000000..66e18bb
--- /dev/null
+++ b/core/jni/runtime_native_boot-flags-test.sh
@@ -0,0 +1,244 @@
+#!/bin/bash
+
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Test Android Runtime (Boot) device configuration flags (living in namespace
+# `runtime_native_boot`).
+
+me=$(basename $0)
+
+# Namespace containing the tested flag.
+namespace=runtime_native_boot
+# Default set of checked zygote processes.
+zygotes=
+
+# Status of whole test script.
+exit_status=0
+
+function say {
+ echo "$me: $*"
+}
+
+function banner {
+ local separator=$(echo "$@" | sed s/./=/g )
+ say "$separator"
+ say "$@"
+ say "$separator"
+}
+
+function fail {
+ say "FAILED: $@"
+ exit_status=1
+}
+
+function reboot_and_wait_for_device {
+ say "Rebooting device..."
+ adb reboot
+ adb wait-for-device >/dev/null
+ # Wait until the device has finished booting. Give the device 60 iterations
+ # (~60 seconds) to try and finish booting before declaring defeat.
+ local niters=60
+ for i in $(seq $niters); do
+ [[ $(adb shell getprop sys.boot_completed) -eq 1 ]] && return 0
+ sleep 1
+ done
+ fail "Device did not finish booting before timeout (~$niters seconds)"
+}
+
+# check_device_config_flag CONTEXT FLAG VALUE
+# -------------------------------------------
+# Check that the device configuration flag FLAG is set to VALUE. Use CONTEXT in
+# logging.
+function check_device_config_flag {
+ local context=$1
+ local flag=$2
+ local value=$3
+
+ say "[$context] Check that the device configuration flag is set..."
+ local flag_value=$(adb shell device_config get "$namespace" "$flag")
+ [[ "$flag_value" = "$value" ]] \
+ || fail "Device configuration flag \`$flag\` set to \`$flag_value\` (expected \`$value\`)"
+}
+
+# check_no_device_config_flag CONTEXT FLAG
+# ----------------------------------------
+# Check that the device configuration flag FLAG is not set. Use CONTEXT in
+# logging.
+function check_no_device_config_flag {
+ local context=$1
+ local flag=$2
+
+ say "[$context] Check that the device configuration flag is not set..."
+ local flag_value=$(adb shell device_config get "$namespace" "$flag")
+ [[ "$flag_value" = null ]] \
+ || fail "Device configuration flag \`$flag\` set to \`$flag_value\` (expected `null`)"
+}
+
+# get_system_property PROP
+# ------------------------
+# Get system property PROP associated with a device configuration flag.
+function get_system_property {
+ local prop=$1
+
+ # Note that we need to be root to read that system property.
+ adb root >/dev/null
+ local prop_value=$(adb shell getprop "$prop")
+ adb unroot >/dev/null
+ echo "$prop_value"
+}
+
+# check_system_property CONTEXT PROP VALUE
+# ----------------------------------------
+# Check that the system property PROP associated with a device configuration
+# flag is set to VALUE. Use CONTEXT in logging.
+function check_system_property {
+ local context=$1
+ local prop=$2
+ local value=$3
+
+ say "[$context] Check that the persistent system property is set..."
+ local prop_value=$(get_system_property "$prop")
+ [[ "$prop_value" = "$value" ]] \
+ || fail "System property \`$prop\` set to \`$prop_value\` (expected \`$value\`)"
+}
+
+# check_no_system_property CONTEXT PROP
+# -------------------------------------
+# Check that the system property PROP associated with a device configuration
+# flag is not set. Use CONTEXT in logging.
+function check_no_system_property {
+ local context=$1
+ local prop=$2
+
+ say "[$context] Check that the persistent system property is not set..."
+ local prop_value=$(get_system_property "$prop")
+ [[ -z "$prop_value" ]] \
+ || fail "System property \`$prop\` set to \`$prop_value\` (expected unset property)"
+}
+
+# find_zygote_runtime_option ZYGOTE RUNTIME_OPTION
+# ------------------------------------------------
+# Return whether ZYGOTE is passed RUNTIME_OPTION.
+function find_zygote_runtime_option {
+ local zygote=$1
+ local runtime_option=$2
+
+ adb logcat -d -s "$zygote" | grep -q -e "option\[[0-9]\+\]=$runtime_option"
+}
+
+# check_zygote_gc_runtime_option CONTEXT VALUE
+# --------------------------------------------
+# Check that all zygote processes are passed device configuration flag VALUE as
+# GC runtime option. Use CONTEXT in logging.
+function check_zygote_gc_runtime_option {
+ local context=$1
+ local value=$2
+
+ say \
+ "[$context] Check that all zygote processes are passed the flag value as a GC runtime option..."
+ local runtime_option="-Xgc:$value"
+ for zygote in $zygotes; do
+ find_zygote_runtime_option "$zygote" "$runtime_option"\
+ || fail "Found no \`$runtime_option\` among runtime options passed to \`$zygote\`"
+ done
+}
+
+# check_no_zygote_gc_runtime_option CONTEXT VALUE
+# -----------------------------------------------
+# Check that no zygote process is passed device configuration flag VALUE as GC
+# runtime option. Use CONTEXT in logging.
+function check_no_zygote_gc_runtime_option {
+ local context=$1
+ local value=$2
+
+ say "[$context] Check no zygote process is passed the flag value as a GC runtime option..."
+ local runtime_option="-Xgc:$value"
+ for zygote in $zygotes; do
+ find_zygote_runtime_option "$zygote" "$runtime_option"\
+ && fail "Found \`$runtime_option\` among runtime options passed to \`$zygote\`"
+ done
+}
+
+# test_android_runtime_flag FLAG VALUE
+# ------------------------------------
+# Test device configuration FLAG with VALUE.
+function test_android_runtime_flag {
+ local flag=$1
+ local value=$2
+
+ # Persistent system property (set after a reboot) associated with the device
+ # configuration flag.
+ local prop="persist.device_config.$namespace.$flag"
+
+ banner "Testing \`$flag\` value \`$value\`."
+
+ say "Setting device configuration flag..."
+ adb shell device_config put "$namespace" "$flag" "$value"
+ # Give some time to the device to digest this change before rebooting.
+ sleep 3
+
+ # Check that both the device configuration flag and the associated system
+ # property are set, but that the zygote hasn't had the flag passed to it as a
+ # GC runtime option (as we haven't rebooted yet).
+ local context="Flag set, before reboot"
+ check_device_config_flag "$context" "$flag" "$value"
+ check_system_property "$context" "$prop" "$value"
+ check_no_zygote_gc_runtime_option "$context" "$value"
+
+ # Reboot device for the flag value to take effect.
+ reboot_and_wait_for_device
+ context="Flag set, after 1st reboot"
+ check_device_config_flag "$context" "$flag" "$value"
+ check_system_property "$context" "$prop" "$value"
+ check_zygote_gc_runtime_option "$context" "$value"
+
+ # Reboot device a second time and check that the state has persisted.
+ reboot_and_wait_for_device
+ context="Flag set, after 2nd reboot"
+ check_device_config_flag "$context" "$flag" "$value"
+ check_system_property "$context" "$prop" "$value"
+ check_zygote_gc_runtime_option "$context" "$value"
+
+ say "Unsetting device configuration flag..."
+ adb shell device_config delete "$namespace" "$flag" >/dev/null
+ # Give some time to the device to digest this change before rebooting.
+ sleep 3
+
+ # Reboot and check that the device is back to its default state.
+ reboot_and_wait_for_device
+ context="Flag unset, after 3rd reboot"
+ check_no_device_config_flag "$context" "$flag"
+ check_no_system_property "$context" "$prop"
+ check_no_zygote_gc_runtime_option "$context" "$value"
+}
+
+# Enumerate Zygote processes.
+case $(adb shell getprop ro.zygote) in
+ (zygote32) zygotes="zygote";;
+ (zygote64) zygotes="zygote64";;
+ (zygote32_64|zygote64_32) zygotes="zygote zygote64";;
+esac
+
+# Test "gctype" flag values.
+test_android_runtime_flag gctype nogenerational_cc
+test_android_runtime_flag gctype generational_cc
+
+if [[ "$exit_status" -eq 0 ]]; then
+ banner "All tests passed."
+else
+ banner "Test(s) failed."
+fi
+exit $exit_status
diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto
index 5b5c9c2..b4f3d1e 100644
--- a/core/proto/android/bluetooth/enums.proto
+++ b/core/proto/android/bluetooth/enums.proto
@@ -132,3 +132,9 @@
// This socket is closed
SOCKET_CONNECTION_STATE_DISCONNECTED = 5;
}
+
+enum SocketRoleEnum {
+ SOCKET_ROLE_UNKNOWN = 0;
+ SOCKET_ROLE_LISTEN = 1;
+ SOCKET_ROLE_CONNECTION = 2;
+}
diff --git a/core/proto/android/hardware/biometrics/enums.proto b/core/proto/android/hardware/biometrics/enums.proto
index 91f2acb..973e3e6 100644
--- a/core/proto/android/hardware/biometrics/enums.proto
+++ b/core/proto/android/hardware/biometrics/enums.proto
@@ -43,4 +43,16 @@
ACTION_AUTHENTICATE = 2;
ACTION_ENUMERATE = 3;
ACTION_REMOVE = 4;
+}
+
+enum IssueEnum {
+ ISSUE_UNKNOWN = 0;
+ // When a biometric HAL has crashed.
+ ISSUE_HAL_DEATH = 1;
+ // When Android Framework has a template that doesn't exist in the HAL. The framework
+ // is expected to remove its template to stay in sync with the HAL.
+ ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK = 2;
+ // When the HAL has a template that doesn't exist in Android Framework. The framework
+ // is expected to notify the HAL to remove this template to stay in sync with the framework.
+ ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL = 3;
}
\ No newline at end of file
diff --git a/core/proto/android/wifi/enums.proto b/core/proto/android/wifi/enums.proto
new file mode 100644
index 0000000..315c579
--- /dev/null
+++ b/core/proto/android/wifi/enums.proto
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.net.wifi;
+
+option java_outer_classname = "WifiProtoEnums";
+option java_multiple_files = true;
+
+/**
+ * Wifi Lock modes, primarily used in
+ * frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiLockManager.java.
+ */
+enum WifiModeEnum {
+ /**
+ * Deprecated.
+ * Wi-Fi will be kept active, and will behave normally.
+ */
+ WIFI_MODE_FULL = 1 [deprecated=true];
+
+ /**
+ * Deprecated.
+ * Wi-Fi will be kept active, but the only operation that will be supported is initiation of
+ * scans, and the subsequent reporting of scan results.
+ */
+ WIFI_MODE_SCAN_ONLY = 2 [deprecated=true];
+
+ /**
+ * Wi-Fi will not go to power save.
+ */
+ WIFI_MODE_FULL_HIGH_PERF = 3;
+
+ /**
+ * Wi-Fi will operate with a priority to achieve low latency.
+ */
+ WIFI_MODE_FULL_LOW_LATENCY = 4;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 07dd26e..34ec92e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2267,7 +2267,7 @@
<!-- Allows an application to start activities from background
@hide -->
<permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"
- android:protectionLevel="signature|privileged|vendorPrivileged|oem" />
+ android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier" />
<!-- @SystemApi Must be required by activities that handle the intent action
{@link Intent#ACTION_SEND_SHOW_SUSPENDED_APP_DETAILS}. This is for use by apps that
diff --git a/core/res/res/drawable/ic_action_open.xml b/core/res/res/drawable/ic_action_open.xml
new file mode 100644
index 0000000..3d3d36e
--- /dev/null
+++ b/core/res/res/drawable/ic_action_open.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF737373"
+ android:pathData="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 53cae63..1053184 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -118,7 +118,7 @@
<attr name="manageSpaceActivity" format="string" />
<!-- Option to let applications specify that user data can/cannot be
- cleared. This flag is turned on by default.
+ cleared by the user in Settings. This flag is turned on by default.
<em>This attribute is usable only by applications
included in the system image. Third-party apps cannot use it.</em> -->
<attr name="allowClearUserData" format="boolean" />
@@ -1661,7 +1661,12 @@
<!-- If {@code true} the user is prompted to keep the app's data on uninstall -->
<attr name="hasFragileUserData" />
- <attr name="zygotePreloadName" />
+ <attr name="zygotePreloadName" />
+
+ <!-- If {@code true} the system will clear app's data if a restore operation fails.
+ This flag is turned on by default. <em>This attribute is usable only by system apps.
+ </em> -->
+ <attr name="allowClearUserDataOnFailedRestore"/>
</declare-styleable>
<!-- The <code>permission</code> tag declares a security permission that can be
used to control access from other packages to specific components or
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ec53811..130f629 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1921,8 +1921,6 @@
cell broadcasting sms, and MMS. -->
<bool name="config_sms_capable">true</bool>
- <!-- TODO: STOPSHIP(b/110557011): Remove this from framework and overlays as we use
- config_defaultRoleHolders now. -->
<!-- Default SMS Application. This will be the default SMS application when
the phone first boots. The user can then change the default app to one
of their choosing.
@@ -1930,15 +1928,33 @@
application is desired.
If this string is empty or the specified package does not exist, then
- the platform will search for an SMS app and use that (if there is one)-->
+ the platform will search for an SMS app and use that (if there is one)
+
+ Note: This config is deprecated, please use config_defaultSms instead. -->
<string name="default_sms_application" translatable="false">com.android.messaging</string>
- <!-- Default role holders. This will be an array of roles and package names of their default
- holders, with each item in the format of "ROLE_NAME: PACKAGE_NAME_1, PACKAGE_NAME_2". -->
- <string-array name="config_defaultRoleHolders" translatable="false">
- <item>android.app.role.SMS: com.android.messaging</item>
- <item>android.app.role.DIALER: com.android.phone</item>
- </string-array>
+ <!-- Default web browser. This is the package name of the application that will
+ be the default browser when the device first boots. Afterwards the user
+ can select whatever browser app they wish to use as the default.
+
+ If this string is empty or the specified package does not exist, then
+ the behavior will be as though no app was named as an explicit default.
+
+ Note: This config is deprecated, please use config_defaultBrowser instead. -->
+ <string name="default_browser" translatable="false"></string>
+
+ <!-- The name of the package that will hold the assistant role by default. -->
+ <string name="config_defaultAssistant" translatable="false" />
+ <!-- The name of the package that will hold the browser role by default. -->
+ <string name="config_defaultBrowser" translatable="false">@string/default_browser</string>
+ <!-- The name of the package that will hold the dialer role by default. -->
+ <string name="config_defaultDialer" translatable="false">com.android.phone</string>
+ <!-- The name of the package that will hold the SMS role by default. -->
+ <string name="config_defaultSms" translatable="false">@string/default_sms_application</string>
+ <!-- The name of the package that will hold the music role by default. -->
+ <string name="config_defaultMusic" translatable="false">com.android.music</string>
+ <!-- The name of the package that will hold the gallery role by default. -->
+ <string name="config_defaultGallery" translatable="false">com.android.gallery3d</string>
<!-- Enable/disable default bluetooth profiles:
HSP_AG, ObexObjectPush, Audio, NAP -->
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index bbe3ff9..ce7995a 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -193,4 +193,7 @@
<!-- A tag used to save the notification action object -->
<item type="id" name="notification_action_index_tag" />
+
+ <!-- A tag used to save the index where the custom view is stored -->
+ <item type="id" name="notification_custom_view_index_tag" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e6d478a..5e65605 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2939,6 +2939,8 @@
<public name="zygotePreloadName" />
<public name="useEmbeddedDex" />
<public name="forceUriPermissions" />
+ <!-- @hide @SystemApi -->
+ <public name="allowClearUserDataOnFailedRestore"/>
</public-group>
<public-group type="drawable" first-id="0x010800b4">
@@ -2971,6 +2973,18 @@
<public name="config_feedbackIntentExtraKey" />
<!-- @hide @SystemApi -->
<public name="config_feedbackIntentNameKey" />
+ <!-- @hide @SystemApi @TestApi -->
+ <public name="config_defaultAssistant" />
+ <!-- @hide @SystemApi -->
+ <public name="config_defaultBrowser" />
+ <!-- @hide @SystemApi @TestApi -->
+ <public name="config_defaultDialer" />
+ <!-- @hide @SystemApi -->
+ <public name="config_defaultSms" />
+ <!-- @hide @SystemApi -->
+ <public name="config_defaultMusic" />
+ <!-- @hide @SystemApi -->
+ <public name="config_defaultGallery" />
</public-group>
<public-group type="bool" first-id="0x01110000">
@@ -2990,11 +3004,6 @@
<public name="system_notification_accent_color" />
</public-group>
- <public-group type="array" first-id="0x01070006">
- <!-- @hide @TestApi @SystemApi -->
- <public name="config_defaultRoleHolders" />
- </public-group>
-
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fadb28f..6d5bd4b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1471,6 +1471,8 @@
<string name="biometric_not_recognized">Not recognized</string>
<!-- Message shown when biometric authentication has been canceled [CHAR LIMIT=50] -->
<string name="biometric_error_canceled">Authentication canceled</string>
+ <!-- Message returned to applications if BiometricPrompt setAllowDeviceCredentials is enabled but no pin, pattern, or password is set. [CHAR LIMIT=NONE] -->
+ <string name="biometric_error_device_not_secured">No pin, pattern, or password set</string>
<!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
<string name="fingerprint_acquired_partial">Partial fingerprint detected. Please try again.</string>
@@ -1512,7 +1514,7 @@
<!-- Generic error message shown when the user has no enrolled fingerprints -->
<string name="fingerprint_error_no_fingerprints">No fingerprints enrolled.</string>
<!-- Generic error message shown when the app requests fingerprint authentication on a device without a sensor -->
- <string name="fingerprint_error_hw_not_present">This device does not have a fingerprint sensor</string>
+ <string name="fingerprint_error_hw_not_present">This device does not have a fingerprint sensor.</string>
<!-- Template to be used to name enrolled fingerprints by default. -->
<string name="fingerprint_name_template">Finger <xliff:g id="fingerId" example="1">%d</xliff:g></string>
@@ -1555,8 +1557,22 @@
<string name="face_acquired_poor_gaze">Please look at the sensor.</string>
<!-- Message shown during face acquisition when the user is not detected [CHAR LIMIT=50] -->
<string name="face_acquired_not_detected">No face detected.</string>
- <!-- Message shown during face acquisition when the face is not kept steady infront of device [CHAR LIMIT=50] -->
- <string name="face_acquired_not_steady">Keep face steady infront of device.</string>
+ <!-- Message shown during face acquisition when the device is not steady [CHAR LIMIT=50] -->
+ <string name="face_acquired_too_much_motion">Too much motion.</string>
+ <!-- Message shown during face acquisition when the sensor needs to be recalibrated [CHAR LIMIT=50] -->
+ <string name="face_acquired_recalibrate">Please re-enroll your face.</string>
+ <!-- Message shown during face enrollment when a different person's face is detected [CHAR LIMIT=50] -->
+ <string name="face_acquired_too_different">Different face detected.</string>
+ <!-- Message shown during face enrollment when the face is too similar to a previous acquisition [CHAR LIMIT=50] -->
+ <string name="face_acquired_too_similar">Too similar, please change your pose.</string>
+ <!-- Message shown during acqusition when the user's face is turned too far left or right [CHAR LIMIT=50] -->
+ <string name="face_acquired_pan_too_extreme">Please look more directly at the camera.</string>
+ <!-- Message shown during acqusition when the user's face is tilted too high or too low [CHAR LIMIT=50] -->
+ <string name="face_acquired_tilt_too_extreme">Please look more directly at the camera.</string>
+ <!-- Message shown during acquisiton when the user's face is tilted too far left or right [CHAR LIMIT=50] -->
+ <string name="face_acquired_roll_too_extreme">Please straighten your head vertically.</string>
+ <!-- Message shown during acquisition when the user's face is obscured [CHAR LIMIT=50] -->
+ <string name="face_acquired_obscured">Please uncover your face.</string>
<!-- Array containing custom messages shown during face acquisition from vendor. Vendor is expected to add and translate these strings -->
<string-array name="face_acquired_vendor">
</string-array>
@@ -1580,7 +1596,7 @@
<!-- Generic error message shown when the user has no enrolled face. [CHAR LIMIT=50] -->
<string name="face_error_not_enrolled">No face enrolled.</string>
<!-- Generic error message shown when the app requests face authentication on a device without a sensor. [CHAR LIMIT=60] -->
- <string name="face_error_hw_not_present">This device does not have a face authentication sensor</string>
+ <string name="face_error_hw_not_present">This device does not have a face authentication sensor.</string>
<!-- Template to be used to name enrolled faces by default. [CHAR LIMIT=10] -->
<string name="face_name_template">Face <xliff:g id="faceId" example="1">%d</xliff:g></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1da9149..8e251fd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1034,6 +1034,7 @@
<java-symbol type="string" name="sipAddressTypeOther" />
<java-symbol type="string" name="sipAddressTypeWork" />
<java-symbol type="string" name="default_sms_application" />
+ <java-symbol type="string" name="default_browser" />
<java-symbol type="string" name="sms_control_message" />
<java-symbol type="string" name="sms_control_title" />
<java-symbol type="string" name="sms_control_no" />
@@ -2472,6 +2473,7 @@
<java-symbol type="string" name="biometric_error_user_canceled" />
<java-symbol type="string" name="biometric_not_recognized" />
<java-symbol type="string" name="biometric_error_canceled" />
+ <java-symbol type="string" name="biometric_error_device_not_secured" />
<!-- Fingerprint messages -->
<java-symbol type="string" name="fingerprint_error_unable_to_process" />
@@ -2521,6 +2523,14 @@
<java-symbol type="string" name="face_acquired_too_left" />
<java-symbol type="string" name="face_acquired_poor_gaze" />
<java-symbol type="string" name="face_acquired_not_detected" />
+ <java-symbol type="string" name="face_acquired_too_much_motion" />
+ <java-symbol type="string" name="face_acquired_recalibrate" />
+ <java-symbol type="string" name="face_acquired_too_different" />
+ <java-symbol type="string" name="face_acquired_too_similar" />
+ <java-symbol type="string" name="face_acquired_pan_too_extreme" />
+ <java-symbol type="string" name="face_acquired_tilt_too_extreme" />
+ <java-symbol type="string" name="face_acquired_roll_too_extreme" />
+ <java-symbol type="string" name="face_acquired_obscured" />
<java-symbol type="array" name="face_acquired_vendor" />
<java-symbol type="string" name="face_name_template" />
<java-symbol type="string" name="face_authenticated_no_confirmation_required" />
@@ -3585,6 +3595,7 @@
<java-symbol type="bool" name="config_useSmsAppService" />
<java-symbol type="id" name="transition_overlay_view_tag" />
+ <java-symbol type="id" name="notification_custom_view_index_tag" />
<java-symbol type="dimen" name="rounded_corner_radius" />
<java-symbol type="dimen" name="rounded_corner_radius_top" />
@@ -3632,4 +3643,6 @@
<java-symbol type="array" name="config_displayWhiteBalanceDecreaseThresholds" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientBrightnessThreshold" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientColorTemperature" />
+
+ <java-symbol type="drawable" name="ic_action_open" />
</resources>
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index 300394d..aa0e0cd 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -162,14 +162,13 @@
}
private void verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename,
- boolean isPlatformReleased, int expectedTargetSdk, boolean forceCurrentDev) {
+ boolean isPlatformReleased, int expectedTargetSdk) {
final String[] outError = new String[1];
final int result = PackageParser.computeTargetSdkVersion(
targetSdkVersion,
targetSdkCodename,
isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE,
- outError,
- forceCurrentDev);
+ outError);
assertEquals(result, expectedTargetSdk);
@@ -185,28 +184,23 @@
// Do allow older release targetSdkVersion on pre-release platform.
// APP: Released API 10
// DEV: Pre-release API 20
- verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION);
// Do allow same release targetSdkVersion on pre-release platform.
// APP: Released API 20
// DEV: Pre-release API 20
- verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION);
// Do allow newer release targetSdkVersion on pre-release platform.
// APP: Released API 30
// DEV: Pre-release API 20
- verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, NEWER_VERSION,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, NEWER_VERSION);
// Don't allow older pre-release targetSdkVersion on pre-release platform.
// APP: Pre-release API 10
// DEV: Pre-release API 20
- verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1,
- false /* forceCurrentDev */);
- verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1);
+ verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
// Do allow same pre-release targetSdkVersion on pre-release platform,
@@ -214,27 +208,16 @@
// APP: Pre-release API 20
// DEV: Pre-release API 20
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false,
- Build.VERSION_CODES.CUR_DEVELOPMENT, false /* forceCurrentDev */);
+ Build.VERSION_CODES.CUR_DEVELOPMENT);
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false,
- Build.VERSION_CODES.CUR_DEVELOPMENT, false /* forceCurrentDev */);
+ Build.VERSION_CODES.CUR_DEVELOPMENT);
// Don't allow newer pre-release targetSdkVersion on pre-release platform.
// APP: Pre-release API 30
// DEV: Pre-release API 20
- verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1,
- false /* forceCurrentDev */);
- verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1,
- false /* forceCurrentDev */);
-
-
- // Force newer pre-release targetSdkVersion to current pre-release platform.
- // APP: Pre-release API 30
- // DEV: Pre-release API 20
- verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false,
- Build.VERSION_CODES.CUR_DEVELOPMENT, true /* forceCurrentDev */);
- verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false,
- Build.VERSION_CODES.CUR_DEVELOPMENT, true /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1);
+ verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
}
@Test
@@ -242,45 +225,36 @@
// Do allow older release targetSdkVersion on released platform.
// APP: Released API 10
// DEV: Released API 20
- verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION);
// Do allow same release targetSdkVersion on released platform.
// APP: Released API 20
// DEV: Released API 20
- verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION);
// Do allow newer release targetSdkVersion on released platform.
// APP: Released API 30
// DEV: Released API 20
- verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, NEWER_VERSION,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, NEWER_VERSION);
// Don't allow older pre-release targetSdkVersion on released platform.
// APP: Pre-release API 10
// DEV: Released API 20
- verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1,
- false /* forceCurrentDev */);
- verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1);
+ verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
// Don't allow same pre-release targetSdkVersion on released platform.
// APP: Pre-release API 20
// DEV: Released API 20
- verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1,
- false /* forceCurrentDev */);
- verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1);
+ verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1);
// Don't allow newer pre-release targetSdkVersion on released platform.
// APP: Pre-release API 30
// DEV: Released API 20
- verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1,
- false /* forceCurrentDev */);
- verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1,
- false /* forceCurrentDev */);
+ verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1);
+ verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
}
/**
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ec57f79..206682a 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -128,7 +128,6 @@
Settings.Global.AUTOFILL_LOGGING_LEVEL,
Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
- Settings.Global.AUTOFILL_SMART_SUGGESTION_EMULATION_FLAGS,
Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED,
Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index da81d17..80b1f9c 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -19,6 +19,7 @@
import static android.view.ImeInsetsSourceConsumer.areEditorsSimilar;
import static android.view.InsetsState.TYPE_IME;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -73,7 +74,7 @@
false,
new DisplayCutout(
Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
- rect, rect);
+ rect, rect, SOFT_INPUT_ADJUST_RESIZE);
mImeConsumer = new ImeInsetsSourceConsumer(
new InsetsState(), Transaction::new, mController);
});
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 6dad6a2..731d564 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -20,10 +20,16 @@
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.Insets;
@@ -73,7 +79,7 @@
false,
new DisplayCutout(
Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
- rect, rect);
+ rect, rect, SOFT_INPUT_ADJUST_RESIZE);
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -95,6 +101,17 @@
}
@Test
+ public void testFrameDoesntMatchDisplay() {
+ mController.onFrameChanged(new Rect(0, 0, 100, 100));
+ mController.getState().setDisplayFrame(new Rect(0, 0, 200, 200));
+ WindowInsetsAnimationControlListener controlListener =
+ mock(WindowInsetsAnimationControlListener.class);
+ mController.controlWindowInsetsAnimation(0, controlListener);
+ verify(controlListener).onCancelled();
+ verify(controlListener, never()).onReady(any(), anyInt());
+ }
+
+ @Test
public void testAnimationEndState() {
InsetsSourceControl[] controls = prepareControls();
InsetsSourceControl navBar = controls[0];
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 03af67d..bd036b0 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -25,6 +25,8 @@
import static android.view.InsetsState.TYPE_SIDE_BAR_3;
import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -37,6 +39,7 @@
import android.platform.test.annotations.Presubmit;
import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
+import android.view.test.InsetsModeSession;
import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
@@ -53,49 +56,70 @@
private InsetsState mState2 = new InsetsState();
@Test
- public void testCalculateInsets() {
+ public void testCalculateInsets() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ SparseIntArray typeSideMap = new SparseIntArray();
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, typeSideMap);
+ assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
+ assertEquals(INSET_SIDE_TOP, typeSideMap.get(TYPE_TOP_BAR));
+ assertEquals(INSET_SIDE_BOTTOM, typeSideMap.get(TYPE_IME));
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.ime()));
+ }
+ }
+
+ @Test
+ public void testCalculateInsets_imeAndNav() throws Exception{
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, null);
+ assertEquals(100, insets.getStableInsetBottom());
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.systemBars()));
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.sideBars()));
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.ime()));
+ }
+ }
+
+ @Test
+ public void testCalculateInsets_navRightStatusTop() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+ mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT, null, null, 0, null);
+ assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
+ assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.sideBars()));
+ }
+ }
+
+ @Test
+ public void testCalculateInsets_imeIgnoredWithoutAdjustResize() {
mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
mState.getSource(TYPE_TOP_BAR).setVisible(true);
mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
mState.getSource(TYPE_IME).setVisible(true);
- SparseIntArray typeSideMap = new SparseIntArray();
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT, null, null, typeSideMap);
- assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
- assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
- assertEquals(INSET_SIDE_TOP, typeSideMap.get(TYPE_TOP_BAR));
- assertEquals(INSET_SIDE_BOTTOM, typeSideMap.get(TYPE_IME));
- assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
- assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.ime()));
- }
-
- @Test
- public void testCalculateInsets_imeAndNav() {
- mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
- mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
- mState.getSource(TYPE_IME).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT, null, null, null);
- assertEquals(100, insets.getStableInsetBottom());
- assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.all()));
- assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
- assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
- assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.sideBars()));
- assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.ime()));
- }
-
- @Test
- public void testCalculateInsets_navRightStatusTop() {
- mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(TYPE_TOP_BAR).setVisible(true);
- mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
- mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT, null, null, null);
- assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
- assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
- assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.sideBars()));
+ DisplayCutout.NO_CUTOUT, null, null, 0, null);
+ assertEquals(0, insets.getSystemWindowInsetBottom());
+ assertTrue(insets.isVisible(ime()));
}
@Test
@@ -106,7 +130,7 @@
mState.getSource(TYPE_IME).setVisible(true);
mState.removeSource(TYPE_IME);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT, null, null, null);
+ DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, null);
assertEquals(0, insets.getSystemWindowInsetBottom());
}
@@ -114,14 +138,14 @@
public void testEquals_differentRect() {
mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 10, 10));
- assertNotEquals(mState, mState2);
+ assertNotEqualsAndHashCode();
}
@Test
public void testEquals_differentSource() {
mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
- assertNotEquals(mState, mState2);
+ assertNotEqualsAndHashCode();
}
@Test
@@ -130,7 +154,7 @@
mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
- assertEquals(mState, mState2);
+ assertEqualsAndHashCode();
}
@Test
@@ -138,7 +162,21 @@
mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
mState.getSource(TYPE_IME).setVisible(true);
mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
- assertNotEquals(mState, mState2);
+ assertNotEqualsAndHashCode();
+ }
+
+ @Test
+ public void testEquals_differentFrame() {
+ mState.setDisplayFrame(new Rect(0, 1, 2, 3));
+ mState.setDisplayFrame(new Rect(4, 5, 6, 7));
+ assertNotEqualsAndHashCode();
+ }
+
+ @Test
+ public void testEquals_sameFrame() {
+ mState.setDisplayFrame(new Rect(0, 1, 2, 3));
+ mState2.setDisplayFrame(new Rect(0, 1, 2, 3));
+ assertEqualsAndHashCode();
}
@Test
@@ -148,6 +186,7 @@
mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
Parcel p = Parcel.obtain();
mState.writeToParcel(p, 0 /* flags */);
+ p.setDataPosition(0);
mState2.readFromParcel(p);
p.recycle();
assertEquals(mState, mState2);
@@ -161,4 +200,14 @@
assertTrue(InsetsState.getDefaultVisibility(TYPE_SIDE_BAR_3));
assertFalse(InsetsState.getDefaultVisibility(TYPE_IME));
}
+
+ private void assertEqualsAndHashCode() {
+ assertEquals(mState, mState2);
+ assertEquals(mState.hashCode(), mState2.hashCode());
+ }
+
+ private void assertNotEqualsAndHashCode() {
+ assertNotEquals(mState, mState2);
+ assertNotEquals(mState.hashCode(), mState2.hashCode());
+ }
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java
index 08ad62a..d9dac31 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java
@@ -41,6 +41,7 @@
private static final String TEXT = "text";
private static final String TITLE = "Map";
+ private static final String DESCRIPTION = "Opens in Maps";
private static final String ACTION = Intent.ACTION_VIEW;
@Mock
@@ -57,19 +58,6 @@
@Test
public void create_foreignText() {
- RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
- TITLE,
- null,
- ACTION,
- null,
- null,
- null,
- null,
- null,
- null,
- null
- );
-
AnnotatorModel.ClassificationResult classificationResult =
new AnnotatorModel.ClassificationResult(
TextClassifier.TYPE_ADDRESS,
@@ -81,7 +69,7 @@
null,
null,
null,
- new RemoteActionTemplate[]{remoteActionTemplate});
+ createRemoteActionTemplates());
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateClassificationIntentFactory.create(
@@ -106,19 +94,6 @@
@Test
public void create_notForeignText() {
- RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
- TITLE,
- null,
- ACTION,
- null,
- null,
- null,
- null,
- null,
- null,
- null
- );
-
AnnotatorModel.ClassificationResult classificationResult =
new AnnotatorModel.ClassificationResult(
TextClassifier.TYPE_ADDRESS,
@@ -130,7 +105,7 @@
null,
null,
null,
- new RemoteActionTemplate[]{remoteActionTemplate});
+ createRemoteActionTemplates());
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateClassificationIntentFactory.create(
@@ -147,4 +122,21 @@
assertThat(intent.getAction()).isEqualTo(ACTION);
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
}
+
+ private static RemoteActionTemplate[] createRemoteActionTemplates() {
+ return new RemoteActionTemplate[]{
+ new RemoteActionTemplate(
+ TITLE,
+ DESCRIPTION,
+ ACTION,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ )
+ };
+ }
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java
index 0d364a3..a1158a7 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java
@@ -81,7 +81,6 @@
REQUEST_CODE
);
-
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
@@ -97,14 +96,79 @@
assertThat(intent.getFlags()).isEqualTo(FLAG);
assertThat(intent.getCategories()).containsExactly((Object[]) CATEGORY);
assertThat(intent.getPackage()).isNull();
- assertThat(
- intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
+ assertThat(intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
assertThat(intent.getIntExtra(KEY_TWO, 0)).isEqualTo(VALUE_TWO);
assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
}
@Test
- public void create_packageIsNotNull() {
+ public void normalizesScheme() {
+ RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
+ TITLE,
+ DESCRIPTION,
+ ACTION,
+ "HTTp://www.android.com",
+ TYPE,
+ FLAG,
+ CATEGORY,
+ /* packageName */ null,
+ NAMED_VARIANTS,
+ REQUEST_CODE
+ );
+
+ List<TextClassifierImpl.LabeledIntent> intents =
+ mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
+
+ String data = intents.get(0).getIntent().getData().toString();
+ assertThat(data).isEqualTo("http://www.android.com");
+ }
+
+ @Test
+ public void create_minimal() {
+ RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
+ TITLE,
+ DESCRIPTION,
+ ACTION,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ );
+
+ List<TextClassifierImpl.LabeledIntent> intents =
+ mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
+
+ assertThat(intents).hasSize(1);
+ TextClassifierImpl.LabeledIntent labeledIntent = intents.get(0);
+ assertThat(labeledIntent.getTitle()).isEqualTo(TITLE);
+ assertThat(labeledIntent.getDescription()).isEqualTo(DESCRIPTION);
+ assertThat(labeledIntent.getRequestCode()).isEqualTo(
+ TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE);
+ Intent intent = labeledIntent.getIntent();
+ assertThat(intent.getAction()).isEqualTo(ACTION);
+ assertThat(intent.getData()).isNull();
+ assertThat(intent.getType()).isNull();
+ assertThat(intent.getFlags()).isEqualTo(0);
+ assertThat(intent.getCategories()).isNull();
+ assertThat(intent.getPackage()).isNull();
+ assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
+ }
+
+ @Test
+ public void invalidTemplate_nullTemplate() {
+ RemoteActionTemplate remoteActionTemplate = null;
+
+ List<TextClassifierImpl.LabeledIntent> intents =
+ mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
+
+ assertThat(intents).isEmpty();
+ }
+
+ @Test
+ public void invalidTemplate_nonEmptyPackageName() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
TITLE,
DESCRIPTION,
@@ -121,41 +185,69 @@
List<TextClassifierImpl.LabeledIntent> intents =
mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
- assertThat(intents).hasSize(0);
+ assertThat(intents).isEmpty();
}
@Test
- public void create_minimal() {
+ public void invalidTemplate_emptyTitle() {
RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
null,
+ DESCRIPTION,
+ ACTION,
null,
null,
null,
null,
null,
null,
+ null
+ );
+
+ List<TextClassifierImpl.LabeledIntent> intents =
+ mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
+
+ assertThat(intents).isEmpty();
+ }
+
+ @Test
+ public void invalidTemplate_emptyDescription() {
+ RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
+ TITLE,
+ null,
+ ACTION,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ );
+
+ List<TextClassifierImpl.LabeledIntent> intents =
+ mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
+
+ assertThat(intents).isEmpty();
+ }
+
+ @Test
+ public void invalidTemplate_emptyIntentAction() {
+ RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
+ TITLE,
+ DESCRIPTION,
+ null,
+ null,
+ null,
+ null,
+ null,
null,
null,
null
);
List<TextClassifierImpl.LabeledIntent> intents =
- mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
+ mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
-
- assertThat(intents).hasSize(1);
- TextClassifierImpl.LabeledIntent labeledIntent = intents.get(0);
- assertThat(labeledIntent.getTitle()).isNull();
- assertThat(labeledIntent.getDescription()).isNull();
- assertThat(labeledIntent.getRequestCode()).isEqualTo(
- TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE);
- Intent intent = labeledIntent.getIntent();
- assertThat(intent.getAction()).isNull();
- assertThat(intent.getData()).isNull();
- assertThat(intent.getType()).isNull();
- assertThat(intent.getFlags()).isEqualTo(0);
- assertThat(intent.getCategories()).isNull();
- assertThat(intent.getPackage()).isNull();
- assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
+ assertThat(intents).isEmpty();
}
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
index 32bafec..fe2a660 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
@@ -195,11 +195,13 @@
assertWithMessage("in_app_conversation_action_types_default")
.that(constants.getInAppConversationActionTypes())
.containsExactly("text_reply", "create_reminder", "call_phone", "open_url",
- "send_email", "send_sms", "track_flight", "view_calendar", "view_map");
+ "send_email", "send_sms", "track_flight", "view_calendar", "view_map",
+ "add_contact");
assertWithMessage("notification_conversation_action_types_default")
.that(constants.getNotificationConversationActionTypes())
.containsExactly("text_reply", "create_reminder", "call_phone", "open_url",
- "send_email", "send_sms", "track_flight", "view_calendar", "view_map");
+ "send_email", "send_sms", "track_flight", "view_calendar", "view_map",
+ "add_contact");
assertWithMessage("lang_id_threshold_override")
.that(constants.getLangIdThresholdOverride()).isWithin(EPSILON).of(-1f);
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index 582be9d..d2d03e56 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -176,6 +176,7 @@
TextClassification classification = mClassifier.classifyText(request);
assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
+ assertThat(classification, containsIntentWithAction(Intent.ACTION_VIEW));
}
@Test
@@ -207,6 +208,7 @@
TextClassification classification = mClassifier.classifyText(request);
assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
+ assertThat(classification, containsIntentWithAction(Intent.ACTION_VIEW));
}
@Test
@@ -380,7 +382,6 @@
assertThat(textLanguage, isTextLanguage("ja"));
}
- /* DISABLED: b/122467291
@Test
public void testSuggestConversationActions_textReplyOnly_maxThree() {
if (isTextClassifierDisabled()) return;
@@ -408,7 +409,7 @@
assertThat(conversationAction,
isConversationAction(ConversationAction.TYPE_TEXT_REPLY));
}
- }*/
+ }
@Test
public void testSuggestConversationActions_textReplyOnly_noMax() {
@@ -517,6 +518,24 @@
};
}
+ private static Matcher<TextClassification> containsIntentWithAction(final String action) {
+ return new BaseMatcher<TextClassification>() {
+ @Override
+ public boolean matches(Object o) {
+ if (o instanceof TextClassification) {
+ TextClassification result = (TextClassification) o;
+ return ExtrasUtils.findAction(result, action) != null;
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("intent action=").appendValue(action);
+ }
+ };
+ }
+
private static Matcher<TextLanguage> isTextLanguage(final String languageTag) {
return new BaseMatcher<TextLanguage>() {
@Override
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
index 73af5674..1980a60 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
@@ -91,8 +91,8 @@
.isEqualTo(ConversationAction.TYPE_CALL_PHONE);
assertThat((float) logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_SCORE))
.isWithin(0.00001f).of(0.5f);
- assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME))
- .isEqualTo(EVENT_TIME);
+ // Never write event time.
+ assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME)).isNull();
assertThat(logMaker.getPackageName()).isEqualTo(PACKAGE_NAME);
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_WIDGET_TYPE))
.isEqualTo(WIDGET_TYPE);
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 1d35143..e375af3 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -658,6 +658,67 @@
assertTrue(debugEntry3.latencyMicros >= 0);
}
+ @Test
+ public void testTrackScreenInteractiveDisabled() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setTrackScreenInteractive(false);
+ Binder binder = new Binder();
+
+ mDeviceState.setScreenInteractive(false);
+ CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID);
+ bcs.time += 10;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+ mDeviceState.setScreenInteractive(true);
+ callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID);
+ bcs.time += 1000; // shoud be ignored.
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+ SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+ assertEquals(1, uidEntries.size());
+ BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
+ Assert.assertNotNull(uidEntry);
+ assertEquals(2, uidEntry.callCount);
+
+ List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+ assertEquals(1, callStatsList.size());
+ BinderCallsStats.CallStat callStats = callStatsList.get(0);
+ assertEquals(false, callStats.screenInteractive);
+ assertEquals(2, callStats.callCount);
+ assertEquals(2, callStats.recordedCallCount);
+ }
+
+ @Test
+ public void testTrackCallingUidDisabled() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setTrackDirectCallerUid(false);
+ Binder binder = new Binder();
+
+ bcs.setCallingUid(1);
+ CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID);
+ bcs.time += 10;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+ bcs.setCallingUid(2);
+ callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID);
+ bcs.time += 1000; // shoud be ignored.
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+ SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+ assertEquals(1, uidEntries.size());
+ BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
+ Assert.assertNotNull(uidEntry);
+ assertEquals(2, uidEntry.callCount);
+
+ List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+ assertEquals(1, callStatsList.size());
+ BinderCallsStats.CallStat callStats = callStatsList.get(0);
+ assertEquals(-1, callStats.callingUid);
+ assertEquals(2, callStats.callCount);
+ assertEquals(2, callStats.recordedCallCount);
+ }
+
+
class TestBinderCallsStats extends BinderCallsStats {
public int callingUid = CALLING_UID;
public long time = 1234;
@@ -682,6 +743,8 @@
});
setSamplingInterval(1);
setAddDebugEntries(false);
+ setTrackScreenInteractive(true);
+ setTrackDirectCallerUid(true);
if (deviceState != null) {
setDeviceState(deviceState.getReadonlyClient());
}
@@ -701,6 +764,10 @@
protected int getCallingUid() {
return callingUid;
}
+
+ protected void setCallingUid(int uid) {
+ callingUid = uid;
+ }
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index 79b8477..3edf5f8 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -476,6 +476,33 @@
assertThat(debugEntry3.totalLatencyMicros).isAtLeast(0L);
}
+ @Test
+ public void testScreenStateTrackingDisabled() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+ looperStats.setTrackScreenInteractive(false);
+
+ Message message = mHandlerFirst.obtainMessage(1000);
+ message.workSourceUid = 1000;
+ message.when = looperStats.getSystemUptimeMillis();
+
+ looperStats.tickUptime(30);
+ mDeviceState.setScreenInteractive(false);
+ Object token = looperStats.messageDispatchStarting();
+ looperStats.messageDispatched(token, message);
+
+ looperStats.tickUptime(30);
+ mDeviceState.setScreenInteractive(true);
+ token = looperStats.messageDispatchStarting();
+ looperStats.messageDispatched(token, message);
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(1);
+ LooperStats.ExportedEntry entry = entries.get(0);
+ assertThat(entry.isInteractive).isEqualTo(false);
+ assertThat(entry.messageCount).isEqualTo(2);
+ assertThat(entry.recordedMessageCount).isEqualTo(2);
+ }
+
private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
try {
r.run();
@@ -501,6 +528,7 @@
super(samplingInterval, sizeCap);
mSamplingInterval = samplingInterval;
setAddDebugEntries(false);
+ setTrackScreenInteractive(true);
if (deviceState != null) {
setDeviceState(deviceState.getReadonlyClient());
}
diff --git a/graphics/java/android/graphics/Insets.aidl b/graphics/java/android/graphics/Insets.aidl
new file mode 100644
index 0000000..e65e72d
--- /dev/null
+++ b/graphics/java/android/graphics/Insets.aidl
@@ -0,0 +1,20 @@
+/* //device/java/android/android/graphics/Insets.aidl
+**
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** 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.graphics;
+
+parcelable Insets;
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index 8258b57..c64c789 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
/**
* An Insets instance holds four integer offsets which describe changes to the four
@@ -27,7 +29,7 @@
* Insets are immutable so may be treated as values.
*
*/
-public final class Insets {
+public final class Insets implements Parcelable {
public static final Insets NONE = new Insets(0, 0, 0, 0);
public final int left;
@@ -73,7 +75,7 @@
}
/**
- * Returns a Rect intance with the appropriate values.
+ * Returns a Rect instance with the appropriate values.
*
* @hide
*/
@@ -168,4 +170,29 @@
", bottom=" + bottom +
'}';
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(left);
+ out.writeInt(top);
+ out.writeInt(right);
+ out.writeInt(bottom);
+ }
+
+ public static final Parcelable.Creator<Insets> CREATOR = new Parcelable.Creator<Insets>() {
+ @Override
+ public Insets createFromParcel(Parcel in) {
+ return new Insets(in.readInt(), in.readInt(), in.readInt(), in.readInt());
+ }
+
+ @Override
+ public Insets[] newArray(int size) {
+ return new Insets[size];
+ }
+ };
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 7c9529b..56be05b 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -175,7 +175,12 @@
private int[] mSupportedAxes;
private static final int[] EMPTY_AXES = {};
- @UnsupportedAppUsage
+ /**
+ * Please use font in xml and also your application global theme to change the default Typeface.
+ * android:textViewStyle and its attribute android:textAppearance can be used in order to change
+ * typeface and other text related properties.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private static void setDefault(Typeface t) {
sDefaultTypeface = t;
nativeSetDefault(t.native_instance);
diff --git a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
index c0c6a4f..5181d89 100644
--- a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
@@ -157,28 +157,22 @@
@Override
public void invalidateDrawable(Drawable who) {
- final Callback callback = getCallback();
-
- if (callback != null) {
- callback.invalidateDrawable(who);
+ if (who == mColorDrawable && getCallback() != null) {
+ getCallback().invalidateDrawable(this);
}
}
@Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
- final Callback callback = getCallback();
-
- if (callback != null) {
- callback.scheduleDrawable(who, what, when);
+ if (who == mColorDrawable && getCallback() != null) {
+ getCallback().scheduleDrawable(this, what, when);
}
}
@Override
public void unscheduleDrawable(Drawable who, Runnable what) {
- final Callback callback = getCallback();
-
- if (callback != null) {
- callback.unscheduleDrawable(who, what);
+ if (who == mColorDrawable && getCallback() != null) {
+ getCallback().unscheduleDrawable(this, what);
}
}
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 5d5e40f..eb169be 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
-import android.annotation.WorkerThread;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.Service;
@@ -29,7 +29,6 @@
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Binder;
-import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
@@ -38,6 +37,8 @@
import android.security.keystore.AndroidKeyStoreProvider;
import android.security.keystore.KeyProperties;
+import com.android.org.conscrypt.TrustedCertificateStore;
+
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.Serializable;
@@ -58,8 +59,6 @@
import javax.security.auth.x500.X500Principal;
-import com.android.org.conscrypt.TrustedCertificateStore;
-
/**
* The {@code KeyChain} class provides access to private keys and
* their corresponding certificate chains in credential storage.
@@ -214,8 +213,8 @@
*
* @deprecated Use {@link #ACTION_KEYCHAIN_CHANGED}, {@link #ACTION_TRUST_STORE_CHANGED} or
* {@link #ACTION_KEY_ACCESS_CHANGED}. Apps that target a version higher than
- * {@link Build.VERSION_CODES#N_MR1} will only receive this broadcast if they register for it
- * at runtime.
+ * {@link android.os.Build.VERSION_CODES#N_MR1} will only receive this broadcast if they
+ * register for it at runtime.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_STORAGE_CHANGED = "android.security.STORAGE_CHANGED";
@@ -532,8 +531,8 @@
}
/**
- * Returns the {@code PrivateKey} for the requested alias, or null
- * if there is no result.
+ * Returns the {@code PrivateKey} for the requested alias, or null if the alias does not exist
+ * or the caller has no permission to access it (see note on exceptions below).
*
* <p> This method may block while waiting for a connection to another process, and must never
* be called from the main thread.
@@ -541,6 +540,15 @@
* at any time from the main thread, it is safer to rely on a long-lived context such as one
* returned from {@link Context#getApplicationContext()}.
*
+ * <p> If the caller provides a valid alias to which it was not granted access, then the
+ * caller must invoke {@link #choosePrivateKeyAlias} again to get another valid alias
+ * or a grant to access the same alias.
+ * <p>On Android versions prior to Q, when a key associated with the specified alias is
+ * unavailable, the method will throw a {@code KeyChainException} rather than return null.
+ * If the exception's cause (as obtained by calling {@code KeyChainException.getCause()})
+ * is a throwable of type {@code IllegalStateException} then the caller lacks a grant
+ * to access the key and certificates associated with this alias.
+ *
* @param alias The alias of the desired private key, typically returned via
* {@link KeyChainAliasCallback#alias}.
* @throws KeyChainException if the alias was valid but there was some problem accessing it.
@@ -591,8 +599,10 @@
}
/**
- * Returns the {@code X509Certificate} chain for the requested
- * alias, or null if there is no result.
+ * Returns the {@code X509Certificate} chain for the requested alias, or null if the alias
+ * does not exist or the caller has no permission to access it (see note on exceptions
+ * in {@link #getPrivateKey}).
+ *
* <p>
* <strong>Note:</strong> If a certificate chain was explicitly specified when the alias was
* installed, this method will return that chain. If only the client certificate was specified
@@ -604,6 +614,9 @@
* <p> As {@link Activity} and {@link Service} contexts are short-lived and can be destroyed
* at any time from the main thread, it is safer to rely on a long-lived context such as one
* returned from {@link Context#getApplicationContext()}.
+ * <p> In case the caller specifies an alias for which it lacks a grant, it must call
+ * {@link #choosePrivateKeyAlias} again. See {@link #getPrivateKey} for more details on
+ * coping with this scenario.
*
* @param alias The alias of the desired certificate chain, typically
* returned via {@link KeyChainAliasCallback#alias}.
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 81afd93..66d8542 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -203,6 +203,27 @@
return nullptr;
}
+const std::unordered_map<std::string, std::string>*
+ AssetManager2::GetOverlayableMapForPackage(uint32_t package_id) const {
+
+ if (package_id >= package_ids_.size()) {
+ return nullptr;
+ }
+
+ const size_t idx = package_ids_[package_id];
+ if (idx == 0xff) {
+ return nullptr;
+ }
+
+ const PackageGroup& package_group = package_groups_[idx];
+ if (package_group.packages_.size() == 0) {
+ return nullptr;
+ }
+
+ const auto loaded_package = package_group.packages_[0].loaded_package_;
+ return &loaded_package->GetOverlayableMap();
+}
+
void AssetManager2::SetConfiguration(const ResTable_config& configuration) {
const int diff = configuration_.diff(configuration);
configuration_ = configuration;
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index bdd4706..72873ab 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -598,6 +598,13 @@
std::string actor;
util::ReadUtf16StringFromDevice(header->actor, arraysize(header->actor), &actor);
+ if (loaded_package->overlayable_map_.find(name) !=
+ loaded_package->overlayable_map_.end()) {
+ LOG(ERROR) << "Multiple <overlayable> blocks with the same name '" << name << "'.";
+ return {};
+ }
+ loaded_package->overlayable_map_.emplace(name, actor);
+
// Iterate over the overlayable policy chunks contained within the overlayable chunk data
ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size());
while (overlayable_iter.HasNext()) {
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index d862182..fc5aa9c7 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -124,6 +124,9 @@
// This may be nullptr if the APK represented by `cookie` has no resource table.
const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
+ const std::unordered_map<std::string, std::string>*
+ GetOverlayableMapForPackage(uint32_t package_id) const;
+
// Sets/resets the configuration for this AssetManager. This will cause all
// caches that are related to the configuration change to be invalidated.
void SetConfiguration(const ResTable_config& configuration);
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index b5f4006..950f541 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -20,6 +20,7 @@
#include <memory>
#include <set>
#include <vector>
+#include <unordered_map>
#include <unordered_set>
#include "android-base/macros.h"
@@ -242,6 +243,10 @@
return defines_overlayable_;
}
+ const std::unordered_map<std::string, std::string>& GetOverlayableMap() const {
+ return overlayable_map_;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
@@ -261,6 +266,7 @@
ByteBucketArray<uint32_t> resource_ids_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
std::vector<const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>> overlayable_infos_;
+ std::unordered_map<std::string, std::string> overlayable_map_;
};
// Read-only view into a resource table. This class validates all data
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 447fdf5..40c8e46 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -71,6 +71,9 @@
app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk");
ASSERT_THAT(app_assets_, NotNull());
+
+ overlayable_assets_ = ApkAssets::Load(GetTestDataPath() + "/overlayable/overlayable.apk");
+ ASSERT_THAT(overlayable_assets_, NotNull());
}
protected:
@@ -83,6 +86,7 @@
std::unique_ptr<const ApkAssets> appaslib_assets_;
std::unique_ptr<const ApkAssets> system_assets_;
std::unique_ptr<const ApkAssets> app_assets_;
+ std::unique_ptr<const ApkAssets> overlayable_assets_;
};
TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
@@ -703,4 +707,20 @@
EXPECT_EQ("", resultDisabled);
}
+TEST_F(AssetManager2Test, GetOverlayableMap) {
+ ResTable_config desired_config;
+ memset(&desired_config, 0, sizeof(desired_config));
+
+ AssetManager2 assetmanager;
+ assetmanager.SetResourceResolutionLoggingEnabled(true);
+ assetmanager.SetConfiguration(desired_config);
+ assetmanager.SetApkAssets({overlayable_assets_.get()});
+
+ const auto map = assetmanager.GetOverlayableMapForPackage(0x7f);
+ ASSERT_NE(nullptr, map);
+ ASSERT_EQ(2, map->size());
+ ASSERT_EQ(map->at("OverlayableResources1"), "overlay://theme");
+ ASSERT_EQ(map->at("OverlayableResources2"), "overlay://com.android.overlayable");
+}
+
} // namespace android
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index b8d3c6b..d58e8d2 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -331,7 +331,7 @@
const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
ASSERT_EQ(1u, packages.size());
- EXPECT_EQ(std::string("com.android.basic"), packages[0]->GetPackageName());
+ ASSERT_EQ(std::string("com.android.basic"), packages[0]->GetPackageName());
const auto& loaded_package = packages[0];
auto iter = loaded_package->begin();
@@ -369,6 +369,24 @@
ASSERT_EQ(end, iter);
}
+TEST(LoadedArscTest, GetOverlayableMap) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlayable/overlayable.apk",
+ "resources.arsc", &contents));
+
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
+ ASSERT_EQ(1u, packages.size());
+ ASSERT_EQ(std::string("com.android.overlayable"), packages[0]->GetPackageName());
+
+ const auto map = packages[0]->GetOverlayableMap();
+ ASSERT_EQ(2, map.size());
+ ASSERT_EQ(map.at("OverlayableResources1"), "overlay://theme");
+ ASSERT_EQ(map.at("OverlayableResources2"), "overlay://com.android.overlayable");
+}
+
// structs with size fields (like Res_value, ResTable_entry) should be
// backwards and forwards compatible (aka checking the size field against
// sizeof(Res_value) might not be backwards compatible.
diff --git a/libs/incident/Android.bp b/libs/incident/Android.bp
index 0619a9c..905e303 100644
--- a/libs/incident/Android.bp
+++ b/libs/incident/Android.bp
@@ -36,7 +36,6 @@
srcs: [
":libincident_aidl",
- "proto/android/os/header.proto",
"proto/android/os/metadata.proto",
"src/IncidentReportArgs.cpp",
],
@@ -47,4 +46,4 @@
},
export_include_dirs: ["include"],
-}
+}
\ No newline at end of file
diff --git a/libs/incident/include/android/os/IncidentReportArgs.h b/libs/incident/include/android/os/IncidentReportArgs.h
index ee1e33c..5e8eac1 100644
--- a/libs/incident/include/android/os/IncidentReportArgs.h
+++ b/libs/incident/include/android/os/IncidentReportArgs.h
@@ -24,8 +24,6 @@
#include <set>
#include <vector>
-#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
-
namespace android {
namespace os {
@@ -49,7 +47,7 @@
void setAll(bool all);
void setDest(int dest);
void addSection(int section);
- void addHeader(const IncidentHeaderProto& headerProto);
+ void addHeader(const vector<uint8_t>& headerProto);
inline bool all() const { return mAll; }
bool containsSection(int section) const;
diff --git a/libs/incident/src/IncidentReportArgs.cpp b/libs/incident/src/IncidentReportArgs.cpp
index 26261ef..06b7a5b 100644
--- a/libs/incident/src/IncidentReportArgs.cpp
+++ b/libs/incident/src/IncidentReportArgs.cpp
@@ -161,15 +161,9 @@
}
void
-IncidentReportArgs::addHeader(const IncidentHeaderProto& headerProto)
+IncidentReportArgs::addHeader(const vector<uint8_t>& headerProto)
{
- vector<uint8_t> header;
- auto serialized = headerProto.SerializeAsString();
- if (serialized.empty()) return;
- for (auto it = serialized.begin(); it != serialized.end(); it++) {
- header.push_back((uint8_t)*it);
- }
- mHeaders.push_back(header);
+ mHeaders.push_back(headerProto);
}
bool
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index 5f6686a..c038f36 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -17,6 +17,7 @@
package android.media;
import android.media.AudioAttributes;
+import android.media.VolumeShaper;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
@@ -27,6 +28,8 @@
interface IRingtonePlayer {
/** Used for Ringtone.java playback */
oneway void play(IBinder token, in Uri uri, in AudioAttributes aa, float volume, boolean looping);
+ oneway void playWithVolumeShaping(IBinder token, in Uri uri, in AudioAttributes aa,
+ float volume, boolean looping, in @nullable VolumeShaper.Configuration volumeShaperConfig);
oneway void stop(IBinder token);
boolean isPlaying(IBinder token);
oneway void setPlaybackProperties(IBinder token, float volume, boolean looping);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 751d57b..4bc3897 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1614,29 +1614,59 @@
}
/**
- * Video performance points are a set of standard performance points defined by pixel rate.
+ * Video performance points are a set of standard performance points defined by number of
+ * pixels, pixel rate and frame rate. Performance point represents an upper bound. This
+ * means that it covers all performance points with fewer pixels, pixel rate and frame
+ * rate.
*/
public static final class PerformancePoint {
/**
- * Frame width in pixels.
+ * (Maximum) number of macroblocks in the frame.
+ *
+ * Video frames are conceptually divided into 16-by-16 pixel blocks called macroblocks.
+ * Most coding standards operate on these 16-by-16 pixel blocks; thus, codec performance
+ * is characterized using such blocks.
*/
- public final int width;
+ public final int macroBlocks;
/**
- * Frame height in pixels.
- */
- public final int height;
-
- /**
- * Frame rate in frames per second.
+ * (Maximum) frame rate in frames per second.
*/
public final int frameRate;
+ /**
+ * (Maximum) number of macroblocks processed per second.
+ */
+ public final long macroBlockRate;
+
/* package private */
- PerformancePoint(int width_, int height_, int frameRate_) {
- width = width_;
- height = height_;
- frameRate = frameRate_;
+ PerformancePoint(int width_, int height_, int frameRate_, int maxFrameRate_) {
+ macroBlocks = saturateLongToInt(
+ ((Math.max(1, (long)width_) + 15) / 16)
+ * ((Math.max(1, (long)height_) + 15) / 16));
+ frameRate = Math.max(1, frameRate_);
+ macroBlockRate = Math.max(maxFrameRate_, frameRate) * macroBlocks;
+ }
+
+ /**
+ * Create a performance point for a given frame size and frame rate.
+ *
+ * @param width_ width of the frame in pixels
+ * @param height_ height of the frame in pixels
+ * @param frameRate_ frame rate in frames per second
+ */
+ public PerformancePoint(int width_, int height_, int frameRate_) {
+ this(width_, height_, frameRate_, frameRate_ /* maxFrameRate */);
+ }
+
+ private int saturateLongToInt(long value) {
+ if (value < Integer.MIN_VALUE) {
+ return Integer.MIN_VALUE;
+ } else if (value > Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ } else {
+ return (int)value;
+ }
}
/**
@@ -1647,26 +1677,40 @@
* @return {@code true} if the performance point covers the format.
*/
public boolean covers(@NonNull MediaFormat format) {
- // for simplicity, this code assumes a 16x16 block size.
- long macroBlocks = ((width + 15) / 16) * (long)((height + 15) / 16);
- long mbps = macroBlocks * frameRate;
-
- long formatMacroBlocks =
- (long)((format.getInteger(MediaFormat.KEY_WIDTH, 0) + 15) / 16)
- * ((format.getInteger(MediaFormat.KEY_HEIGHT, 0) + 15) / 16);
- double formatMbps =
- Math.ceil(formatMacroBlocks
- * format.getNumber(MediaFormat.KEY_FRAME_RATE, 0).doubleValue());
- return formatMacroBlocks > 0 && formatMacroBlocks <= macroBlocks
- && formatMbps <= mbps;
+ PerformancePoint other = new PerformancePoint(
+ format.getInteger(MediaFormat.KEY_WIDTH, 0),
+ format.getInteger(MediaFormat.KEY_HEIGHT, 0),
+ // safely convert ceil(double) to int through float case and Math.round
+ Math.round((float)(
+ Math.ceil(format.getNumber(MediaFormat.KEY_FRAME_RATE, 0)
+ .doubleValue()))));
+ return covers(other);
}
+ /**
+ * Checks whether the performance point covers another performance point. Use this
+ * method to determine if a performance point advertised by a codec covers the
+ * performance point required. This method can also be used for lose ordering as this
+ * method is transitive.
+ *
+ * @param other other performance point considered
+ *
+ * @return {@code true} if the performance point covers the other.
+ */
+ public boolean covers(@NonNull PerformancePoint other) {
+ return (macroBlocks >= other.macroBlocks
+ && frameRate >= other.frameRate
+ && macroBlockRate >= other.macroBlockRate);
+ }
+
+
@Override
public boolean equals(Object o) {
if (o instanceof PerformancePoint) {
PerformancePoint other = (PerformancePoint)o;
- return ((long)width * height) == ((long)other.width * other.height)
- && frameRate == other.frameRate;
+ return (macroBlocks == other.macroBlocks
+ && frameRate == other.frameRate
+ && macroBlockRate == other.macroBlockRate);
}
return false;
}
@@ -1931,7 +1975,8 @@
continue;
}
ret.add(new PerformancePoint(
- size.getWidth(), size.getHeight(), range.getLower().intValue()));
+ size.getWidth(), size.getHeight(), range.getLower().intValue(),
+ range.getUpper().intValue()));
}
// check if the component specified no performance point indication
if (ret.size() == 0) {
@@ -1939,9 +1984,12 @@
}
// sort reversed by area first, then by frame rate
- ret.sort((a, b) -> (a.width * a.height != b.width * b.height ?
- (b.width * b.height - a.width * a.height) :
- (b.frameRate - a.frameRate)));
+ ret.sort((a, b) -> -((a.macroBlocks != b.macroBlocks) ?
+ (a.macroBlocks < b.macroBlocks ? -1 : 1) :
+ (a.macroBlockRate != b.macroBlockRate) ?
+ (a.macroBlockRate < b.macroBlockRate ? -1 : 1) :
+ (a.frameRate != b.frameRate) ?
+ (a.frameRate < b.frameRate ? -1 : 1) : 0));
return ret;
}
@@ -2363,39 +2411,45 @@
boolean supported = true;
switch (profileLevel.level) {
case CodecProfileLevel.AVCLevel1:
- MBPS = 1485; FS = 99; BR = 64; DPB = 396; break;
+ MBPS = 1485; FS = 99; BR = 64; DPB = 396; break;
case CodecProfileLevel.AVCLevel1b:
- MBPS = 1485; FS = 99; BR = 128; DPB = 396; break;
+ MBPS = 1485; FS = 99; BR = 128; DPB = 396; break;
case CodecProfileLevel.AVCLevel11:
- MBPS = 3000; FS = 396; BR = 192; DPB = 900; break;
+ MBPS = 3000; FS = 396; BR = 192; DPB = 900; break;
case CodecProfileLevel.AVCLevel12:
- MBPS = 6000; FS = 396; BR = 384; DPB = 2376; break;
+ MBPS = 6000; FS = 396; BR = 384; DPB = 2376; break;
case CodecProfileLevel.AVCLevel13:
- MBPS = 11880; FS = 396; BR = 768; DPB = 2376; break;
+ MBPS = 11880; FS = 396; BR = 768; DPB = 2376; break;
case CodecProfileLevel.AVCLevel2:
- MBPS = 11880; FS = 396; BR = 2000; DPB = 2376; break;
+ MBPS = 11880; FS = 396; BR = 2000; DPB = 2376; break;
case CodecProfileLevel.AVCLevel21:
- MBPS = 19800; FS = 792; BR = 4000; DPB = 4752; break;
+ MBPS = 19800; FS = 792; BR = 4000; DPB = 4752; break;
case CodecProfileLevel.AVCLevel22:
- MBPS = 20250; FS = 1620; BR = 4000; DPB = 8100; break;
+ MBPS = 20250; FS = 1620; BR = 4000; DPB = 8100; break;
case CodecProfileLevel.AVCLevel3:
- MBPS = 40500; FS = 1620; BR = 10000; DPB = 8100; break;
+ MBPS = 40500; FS = 1620; BR = 10000; DPB = 8100; break;
case CodecProfileLevel.AVCLevel31:
- MBPS = 108000; FS = 3600; BR = 14000; DPB = 18000; break;
+ MBPS = 108000; FS = 3600; BR = 14000; DPB = 18000; break;
case CodecProfileLevel.AVCLevel32:
- MBPS = 216000; FS = 5120; BR = 20000; DPB = 20480; break;
+ MBPS = 216000; FS = 5120; BR = 20000; DPB = 20480; break;
case CodecProfileLevel.AVCLevel4:
- MBPS = 245760; FS = 8192; BR = 20000; DPB = 32768; break;
+ MBPS = 245760; FS = 8192; BR = 20000; DPB = 32768; break;
case CodecProfileLevel.AVCLevel41:
- MBPS = 245760; FS = 8192; BR = 50000; DPB = 32768; break;
+ MBPS = 245760; FS = 8192; BR = 50000; DPB = 32768; break;
case CodecProfileLevel.AVCLevel42:
- MBPS = 522240; FS = 8704; BR = 50000; DPB = 34816; break;
+ MBPS = 522240; FS = 8704; BR = 50000; DPB = 34816; break;
case CodecProfileLevel.AVCLevel5:
- MBPS = 589824; FS = 22080; BR = 135000; DPB = 110400; break;
+ MBPS = 589824; FS = 22080; BR = 135000; DPB = 110400; break;
case CodecProfileLevel.AVCLevel51:
- MBPS = 983040; FS = 36864; BR = 240000; DPB = 184320; break;
+ MBPS = 983040; FS = 36864; BR = 240000; DPB = 184320; break;
case CodecProfileLevel.AVCLevel52:
- MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break;
+ MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break;
+ case CodecProfileLevel.AVCLevel6:
+ MBPS = 4177920; FS = 139264; BR = 240000; DPB = 696320; break;
+ case CodecProfileLevel.AVCLevel61:
+ MBPS = 8355840; FS = 139264; BR = 480000; DPB = 696320; break;
+ case CodecProfileLevel.AVCLevel62:
+ MBPS = 16711680; FS = 139264; BR = 800000; DPB = 696320; break;
default:
Log.w(TAG, "Unrecognized level "
+ profileLevel.level + " for " + mime);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index a76cf1f..12e02e7 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1520,6 +1520,7 @@
* Create a copy of a media format object.
*/
public MediaFormat(@NonNull MediaFormat other) {
+ this();
mMap.putAll(other.mMap);
}
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 73d3d88..eb680c8 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -381,7 +381,8 @@
volume = mVolume;
}
try {
- mRemotePlayer.play(mRemoteToken, canonicalUri, mAudioAttributes, volume, looping);
+ mRemotePlayer.playWithVolumeShaping(mRemoteToken, canonicalUri, mAudioAttributes,
+ volume, looping, mVolumeShaperConfig);
} catch (RemoteException e) {
if (!playFallbackRingtone()) {
Log.w(TAG, "Problem playing ringtone: " + e);
diff --git a/media/java/android/media/VolumeShaper.aidl b/media/java/android/media/VolumeShaper.aidl
new file mode 100644
index 0000000..e99c13f
--- /dev/null
+++ b/media/java/android/media/VolumeShaper.aidl
@@ -0,0 +1,19 @@
+/* Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.media;
+
+parcelable VolumeShaper;
+parcelable VolumeShaper.Configuration;
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index e08dab4..4906695 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -17,8 +17,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SoundPool"
+#include <chrono>
#include <inttypes.h>
-
+#include <thread>
#include <utils/Log.h>
#define USE_SHARED_MEM_BUFFER
@@ -967,6 +968,12 @@
if (mState != IDLE) {
setVolume_l(0, 0);
ALOGV("stop");
+ // Since we're forcibly halting the previously playing content,
+ // we sleep here to ensure the volume is ramped down before we stop the track.
+ // Ideally the sleep time is the mixer period, or an approximation thereof
+ // (Fast vs Normal tracks are different).
+ // TODO: consider pausing instead of stop here.
+ std::this_thread::sleep_for(std::chrono::milliseconds(20));
mAudioTrack->stop();
mPrevSampleID = mSample->sampleID();
mSample.clear();
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 51afbc7..730c409 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -230,6 +230,7 @@
ASurfaceTransaction_reparent; # introduced=29
ASurfaceTransaction_setBuffer; # introduced=29
ASurfaceTransaction_setBufferAlpha; # introduced=29
+ ASurfaceTransaction_setBufferDataSpace; # introduced=29
ASurfaceTransaction_setBufferTransparency; # introduced=29
ASurfaceTransaction_setColor; # introduced=29
ASurfaceTransaction_setDamageRegion; # introduced=29
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 7d2934b..d07052b 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -440,6 +440,20 @@
transaction->setAlpha(surfaceControl, alpha);
}
+void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* aSurfaceTransaction,
+ ASurfaceControl* aSurfaceControl,
+ ADataSpace aDataSpace) {
+ CHECK_NOT_NULL(aSurfaceTransaction);
+ CHECK_NOT_NULL(aSurfaceControl);
+
+ sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+ LOG_ALWAYS_FATAL_IF(!isDataSpaceValid(surfaceControl, aDataSpace), "invalid dataspace");
+
+ Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+ transaction->setDataspace(surfaceControl, static_cast<ui::Dataspace>(aDataSpace));
+}
+
void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
struct AHdrMetadata_smpte2086* metadata) {
diff --git a/packages/CaptivePortalLogin/res/values-gl/strings.xml b/packages/CaptivePortalLogin/res/values-gl/strings.xml
index f6f4aea..6419516 100644
--- a/packages/CaptivePortalLogin/res/values-gl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-gl/strings.xml
@@ -13,7 +13,7 @@
<string name="ssl_error_mismatch" msgid="3060364165934822383">"O nome do sitio non coincide co nome que aparece no certificado."</string>
<string name="ssl_error_expired" msgid="1501588340716182495">"Este certificado caducou."</string>
<string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Este certificado aínda non é válido."</string>
- <string name="ssl_error_date_invalid" msgid="88425990680059223">"Este certificado ten unha data non-válida."</string>
+ <string name="ssl_error_date_invalid" msgid="88425990680059223">"Este certificado ten unha data non válida."</string>
<string name="ssl_error_invalid" msgid="2540546515565633432">"Este certificado non é válido."</string>
<string name="ssl_error_unknown" msgid="4405203446079465859">"Produciuse un erro descoñecido relacionado co certificado."</string>
<string name="ssl_security_warning_title" msgid="8768539813847504404">"Advertencia de seguranza"</string>
diff --git a/packages/CarSystemUI/res/values/colors_car.xml b/packages/CarSystemUI/res/values/colors_car.xml
index 2f720f5..08e16cd 100644
--- a/packages/CarSystemUI/res/values/colors_car.xml
+++ b/packages/CarSystemUI/res/values/colors_car.xml
@@ -26,6 +26,4 @@
<color name="car_user_switcher_add_user_background_color">@color/car_dark_blue_grey_600</color>
<color name="car_user_switcher_add_user_add_sign_color">@color/car_body1_light</color>
- <!-- colors for volume dialog tint -->
- <color name="car_volume_dialog_tint">@color/car_tint</color>
</resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 85dab57..10a0ae5 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -554,8 +554,7 @@
// Adding the items which are not coming from the default item.
VolumeItem volumeItem = mAvailableVolumeItems.get(groupId);
if (volumeItem.defaultItem) {
- // Set progress here due to the progress of seekbar may not be updated.
- volumeItem.listItem.setProgress(volumeItem.progress);
+ updateDefaultVolumeItem(volumeItem.listItem);
} else {
addSeekbarListItem(volumeItem, groupId, 0, null);
}
@@ -572,8 +571,7 @@
if (!volumeItem.defaultItem) {
itr.remove();
} else {
- // Set progress here due to the progress of seekbar may not be updated.
- seekbarListItem.setProgress(volumeItem.progress);
+ updateDefaultVolumeItem(seekbarListItem);
}
}
inAnimator = AnimatorInflater.loadAnimator(
@@ -595,6 +593,21 @@
mPagedListAdapter.notifyDataSetChanged();
}
+ private void updateDefaultVolumeItem(SeekbarListItem seekbarListItem){
+ VolumeItem volumeItem = findVolumeItem(seekbarListItem);
+
+ // When volume dialog is expanded or collapsed the default list item is never
+ // reset. Whereas all other list items are removed when the dialog is collapsed and then
+ // added when the dialog is expanded using {@link CarVolumeDialogImpl#addSeekbarListItem}.
+ // This sets the progressbar and the tint color of icons for all items other than default
+ // if they were changed. For default list item it should be done manually here.
+ int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint);
+ Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon);
+ primaryIcon.mutate().setTint(color);
+ volumeItem.listItem.setPrimaryActionIcon(primaryIcon);
+ volumeItem.listItem.setProgress(volumeItem.progress);
+ }
+
private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener {
private final int mVolumeGroupId;
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index b6b229c..c5e598d 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -230,6 +230,10 @@
NotificationEntry entry =
new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
SmartActionsHelper.SmartSuggestions suggestions = mSmartActionsHelper.suggest(entry);
+ if (DEBUG) {
+ Log.d(TAG, String.format("Creating Adjustment for %s, with %d actions, and %d replies.",
+ sbn.getKey(), suggestions.actions.size(), suggestions.replies.size()));
+ }
return createEnqueuedNotificationAdjustment(
entry, suggestions.actions, suggestions.replies);
}
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 08cc39f..f372fe5 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -21,6 +21,7 @@
import android.app.Person;
import android.app.RemoteAction;
import android.content.Context;
+import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.Process;
@@ -42,6 +43,7 @@
import java.util.Collections;
import java.util.Deque;
import java.util.List;
+import java.util.Objects;
import java.util.stream.Collectors;
public class SmartActionsHelper {
@@ -120,6 +122,12 @@
if (messages.isEmpty()) {
return Collections.emptyList();
}
+ // Do not generate smart actions if the last message is from the local user.
+ ConversationActions.Message lastMessage = messages.get(messages.size() - 1);
+ if (arePersonsEqual(
+ ConversationActions.Message.PERSON_USER_SELF, lastMessage.getAuthor())) {
+ return Collections.emptyList();
+ }
TextClassifier.EntityConfig.Builder typeConfigBuilder =
new TextClassifier.EntityConfig.Builder();
@@ -230,8 +238,11 @@
private Notification.Action createNotificationAction(
RemoteAction remoteAction, String actionType) {
+ Icon icon = remoteAction.shouldShowIcon()
+ ? remoteAction.getIcon()
+ : Icon.createWithResource(mContext, com.android.internal.R.drawable.ic_action_open);
return new Notification.Action.Builder(
- remoteAction.getIcon(),
+ icon,
remoteAction.getTitle(),
remoteAction.getActionIntent())
.setContextual(true)
@@ -312,13 +323,12 @@
if (message == null) {
continue;
}
+ // As per the javadoc of Notification.addMessage, null means local user.
Person senderPerson = message.getSenderPerson();
- // Skip encoding once the sender is missing as it is important to distinguish
- // local user and remote user when generating replies.
if (senderPerson == null) {
- break;
+ senderPerson = localUser;
}
- Person author = localUser != null && localUser.equals(senderPerson)
+ Person author = localUser != null && arePersonsEqual(localUser, senderPerson)
? ConversationActions.Message.PERSON_USER_SELF : senderPerson;
extractMessages.push(new ConversationActions.Message.Builder(author)
.setText(message.getText())
@@ -333,6 +343,12 @@
return new ArrayList<>(extractMessages);
}
+ private static boolean arePersonsEqual(@NonNull Person left, @NonNull Person right) {
+ return Objects.equals(left.getKey(), right.getKey())
+ && Objects.equals(left.getName(), right.getName())
+ && Objects.equals(left.getUri(), right.getUri());
+ }
+
static class SmartSuggestions {
public final ArrayList<CharSequence> replies;
public final ArrayList<Notification.Action> actions;
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
index ebbd961..74c20fc 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
@@ -222,22 +222,29 @@
List<ConversationActions.Message> messages =
runSuggestAndCaptureRequest().getConversation();
- assertThat(messages).hasSize(3);
+ assertThat(messages).hasSize(4);
- ConversationActions.Message secondMessage = messages.get(0);
+ ConversationActions.Message firstMessage = messages.get(0);
+ MessageSubject.assertThat(firstMessage).hasText("firstMessage");
+ MessageSubject.assertThat(firstMessage)
+ .hasPerson(ConversationActions.Message.PERSON_USER_SELF);
+ MessageSubject.assertThat(firstMessage)
+ .hasReferenceTime(createZonedDateTimeFromMsUtc(1000));
+
+ ConversationActions.Message secondMessage = messages.get(1);
MessageSubject.assertThat(secondMessage).hasText("secondMessage");
MessageSubject.assertThat(secondMessage)
.hasPerson(ConversationActions.Message.PERSON_USER_SELF);
MessageSubject.assertThat(secondMessage)
.hasReferenceTime(createZonedDateTimeFromMsUtc(2000));
- ConversationActions.Message thirdMessage = messages.get(1);
+ ConversationActions.Message thirdMessage = messages.get(2);
MessageSubject.assertThat(thirdMessage).hasText("thirdMessage");
MessageSubject.assertThat(thirdMessage).hasPerson(userA);
MessageSubject.assertThat(thirdMessage)
.hasReferenceTime(createZonedDateTimeFromMsUtc(3000));
- ConversationActions.Message fourthMessage = messages.get(2);
+ ConversationActions.Message fourthMessage = messages.get(3);
MessageSubject.assertThat(fourthMessage).hasText("fourthMessage");
MessageSubject.assertThat(fourthMessage).hasPerson(userB);
MessageSubject.assertThat(fourthMessage)
@@ -245,6 +252,28 @@
}
@Test
+ public void testSuggest_lastMessageLocalUser() {
+ Person me = new Person.Builder().setName("Me").build();
+ Person userA = new Person.Builder().setName("A").build();
+ Notification.MessagingStyle style =
+ new Notification.MessagingStyle(me)
+ .addMessage("firstMessage", 1000, userA)
+ .addMessage("secondMessage", 2000, me);
+ Notification notification =
+ mNotificationBuilder
+ .setContentText("You have two new messages")
+ .setStyle(style)
+ .setActions(createReplyAction())
+ .build();
+ when(mStatusBarNotification.getNotification()).thenReturn(notification);
+
+ mSmartActionsHelper.suggest(createNotificationEntry());
+
+ verify(mTextClassifier, never())
+ .suggestConversationActions(any(ConversationActions.Request.class));
+ }
+
+ @Test
public void testSuggest_messageStyle_noPerson() {
Person me = new Person.Builder().setName("Me").build();
Notification.MessagingStyle style =
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index dbeee1c..26ea6ab 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -220,4 +220,7 @@
<!-- Default for Settings.Secure.CHARGING_SOUNDS_ENABLED -->
<bool name="def_charging_sounds_enabled">true</bool>
+
+ <!-- Default for Settings.Secure.NOTIFICATION_BUBBLES -->
+ <bool name="def_notification_bubbles">true</bool>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 23e5f0e..a7ad223 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3232,7 +3232,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 173;
+ private static final int SETTINGS_VERSION = 174;
private final int mUserId;
@@ -4252,6 +4252,24 @@
currentVersion = 173;
}
+ if (currentVersion == 173) {
+ // Version 173: Set the default value for Secure Settings: NOTIFICATION_BUBBLES
+
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+
+ final Setting bubblesSetting = secureSettings.getSettingLocked(
+ Secure.NOTIFICATION_BUBBLES);
+
+ if (bubblesSetting.isNull()) {
+ secureSettings.insertSettingLocked(Secure.NOTIFICATION_BUBBLES,
+ getContext().getResources().getBoolean(
+ R.bool.def_notification_bubbles) ? "1" : "0", null,
+ true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ currentVersion = 174;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
index ac69043..38bf77d 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -55,9 +55,16 @@
void setTextColor(int color);
/**
+ * Sets the color palette for the clock face.
+ * @param supportsDarkText Whether dark text can be displayed.
+ * @param colors Colors that should be used on the clock face, ordered from darker to lighter.
+ */
+ default void setColorPalette(boolean supportsDarkText, int[] colors) {}
+
+ /**
* Notifies that time tick alarm from doze service fired.
*/
- default void dozeTimeTick() { }
+ default void dozeTimeTick() {}
/**
* Set the amount (ratio) that the device has transitioned to doze.
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
new file mode 100644
index 0000000..3ee69b4
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.plugins.statusbar;
+
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+
+
+/**
+ * Sends updates to {@link StateListener}s about changes to the status bar state and dozing state
+ */
+@ProvidesInterface(version = StatusBarStateController.VERSION)
+@DependsOn(target = StatusBarStateController.StateListener.class)
+public interface StatusBarStateController {
+ int VERSION = 1;
+
+ /**
+ * Current status bar state
+ */
+ int getState();
+
+ /**
+ * Is device dozing
+ */
+ boolean isDozing();
+
+ /**
+ * Adds a state listener
+ */
+ void addCallback(StateListener listener);
+
+ /**
+ * Removes callback from listeners
+ */
+ void removeCallback(StateListener listener);
+
+ /**
+ * Get amount of doze
+ */
+ float getDozeAmount();
+
+ /**
+ * Listener for StatusBarState updates
+ */
+ @ProvidesInterface(version = StateListener.VERSION)
+ public interface StateListener {
+ int VERSION = 1;
+
+ /**
+ * Callback before the new state is applied, for those who need to preempt the change.
+ */
+ default void onStatePreChange(int oldState, int newState) {
+ }
+
+ /**
+ * Callback after all listeners have had a chance to update based on the state change
+ */
+ default void onStatePostChange() {
+ }
+
+ /**
+ * Required callback. Get the new state and do what you will with it. Keep in mind that
+ * other listeners are typically unordered and don't rely on your work being done before
+ * other peers.
+ *
+ * Only called if the state is actually different.
+ */
+ default void onStateChanged(int newState) {
+ }
+
+ /**
+ * Callback to be notified when Dozing changes. Dozing is stored separately from state.
+ */
+ default void onDozingChanged(boolean isDozing) {}
+
+ /**
+ * Callback to be notified when the doze amount changes. Useful for animations.
+ * Note: this will be called for each animation frame. Please be careful to avoid
+ * performance regressions.
+ */
+ default void onDozeAmountChanged(float linear, float eased) {}
+ }
+}
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index da11db3..54537e5 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM is nou gedeaktiveer. Voer PUK-kode in om voort te gaan. Jy het <xliff:g id="_NUMBER_1">%d</xliff:g> pogings oor voordat die SIM permanent onbruikbaar word. Kontak die diensverskaffer vir besonderhede.</item>
<item quantity="one">SIM is nou gedeaktiveer. Voer PUK-kode in om voort te gaan. Jy het <xliff:g id="_NUMBER_0">%d</xliff:g> poging oor voordat die SIM permanent onbruikbaar word. Kontak die diensverskaffer vir besonderhede.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Dit is"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Twaalf"</item>
<item msgid="7389464214252023751">"Een"</item>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index 0d154f5..379838d 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">ሲም አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ሲም እስከመጨረሻው መጠቀም የማይቻል ከመሆኑ በፊት <xliff:g id="_NUMBER_1">%d</xliff:g> ሙከራዎች ይቀረዎታል። ዝርዝሮችን ለማግኘት የአገልግሎት አቅራቢን ያነጋግሩ።</item>
<item quantity="other">ሲም አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ሲም እስከመጨረሻው መጠቀም የማይቻል ከመሆኑ በፊት <xliff:g id="_NUMBER_1">%d</xliff:g> ሙከራዎች ይቀረዎታል። ዝርዝሮችን ለማግኘት የአገልግሎት አቅራቢን ያነጋግሩ።</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ነው"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"አስራ ሁለት"</item>
<item msgid="7389464214252023751">"አንድ"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 826f2f0..2fef027 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -182,7 +182,7 @@
<item quantity="other">تم إيقاف شريحة SIM الآن. أدخل رمز PUK للمتابعة، وتتبقى لديك <xliff:g id="_NUMBER_1">%d</xliff:g> محاولة قبل أن تصبح شريحة SIM غير صالحة للاستخدام نهائيًا. ويمكنك الاتصال بمشغل شبكة الجوّال لمعرفة التفاصيل.</item>
<item quantity="one">تم إيقاف شريحة SIM الآن. أدخل رمز PUK للمتابعة، وتتبقى لديك محاولة واحدة (<xliff:g id="_NUMBER_0">%d</xliff:g>) قبل أن تصبح شريحة SIM غير صالحة للاستخدام نهائيًا. ويمكنك الاتصال بمشغل شبكة الجوّال لمعرفة التفاصيل.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"الساعة"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"الثانية عشرة"</item>
<item msgid="7389464214252023751">"الواحدة"</item>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index f67e009..63d0512 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">ছিমখন অক্ষম হ’ল। অব্যাহত ৰাখিবলৈ PUK দিয়ক। ছিমখন স্থায়ীভাৱে ব্যৱহাৰৰ অনুপযোগী হোৱাৰ পূৰ্বে আপোনাৰ হাতত <xliff:g id="_NUMBER_1">%d</xliff:g>টা প্ৰয়াস বাকী আছে। সবিশেষ জানিবলৈ বাহকৰ সৈতে যোগাযোগ কৰক।</item>
<item quantity="other">ছিমখন অক্ষম হ’ল। অব্যাহত ৰাখিবলৈ PUK দিয়ক। ছিমখন স্থায়ীভাৱে ব্যৱহাৰৰ অনুপযোগী হোৱাৰ পূৰ্বে আপোনাৰ হাতত <xliff:g id="_NUMBER_1">%d</xliff:g>টা প্ৰয়াস বাকী আছে। সবিশেষ জানিবলৈ বাহকৰ সৈতে যোগাযোগ কৰক।</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"সময়"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"বাৰ"</item>
<item msgid="7389464214252023751">"এক"</item>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index 50f1b1f..3714ec6e 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM indi deaktivdir. Davam etmək üçün PUK kodunu daxil edin. SIM birdəfəlik yararsız olmadan öncə <xliff:g id="_NUMBER_1">%d</xliff:g> cəhdiniz qalır. Ətraflı məlumat üçün operatorla əlaqə saxlayın.</item>
<item quantity="one">SIM indi deaktivdir. Davam etmək üçün PUK kodunu daxil edin. SIM birdəfəlik yararsız olmadan öncə <xliff:g id="_NUMBER_0">%d</xliff:g> cəhdiniz qalır. Ətraflı məlumat üçün operatorla əlaqə saxlayın.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Saat"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"On iki"</item>
<item msgid="7389464214252023751">"Bir"</item>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index a5fceef..3272313 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -158,7 +158,7 @@
<item quantity="few">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja pre nego što SIM postane trajno neupotrebljiv. Detaljne informacije potražite od mobilnog operatera.</item>
<item quantity="other">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja pre nego što SIM postane trajno neupotrebljiv. Detaljne informacije potražite od mobilnog operatera.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Sada je"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"dvanaest"</item>
<item msgid="7389464214252023751">"jedan"</item>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index 872cd7b..aaa4cb6 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -166,7 +166,7 @@
<item quantity="many">SIM-карта заблакіравана. Каб працягнуць, увядзіце PUK-код. У вас ёсць яшчэ <xliff:g id="_NUMBER_1">%d</xliff:g> спроб, пасля чаго SIM-карта будзе заблакіравана назаўсёды. Звярніцеся да аператара, каб даведацца больш.</item>
<item quantity="other">SIM-карта заблакіравана. Каб працягнуць, увядзіце PUK-код. У вас ёсць яшчэ <xliff:g id="_NUMBER_1">%d</xliff:g> спробы, пасля чаго SIM-карта будзе заблакіравана назаўсёды. Звярніцеся да аператара, каб даведацца больш.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Зараз"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Дванаццаць"</item>
<item msgid="7389464214252023751">"Адна"</item>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index 741834f..d89dd41 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM картата вече е деактивирана. Въведете PUK кода, за да продължите. Остават ви <xliff:g id="_NUMBER_1">%d</xliff:g> опита, преди SIM картата да стане неизползваема завинаги. Свържете се с оператора за подробности.</item>
<item quantity="one">SIM картата вече е деактивирана. Въведете PUK кода, за да продължите. Остава ви <xliff:g id="_NUMBER_0">%d</xliff:g> опит, преди SIM картата да стане неизползваема завинаги. Свържете се с оператора за подробности.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Часът е"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"дванайсет"</item>
<item msgid="7389464214252023751">"един"</item>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 25346a5..d0794c3 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">সিম অক্ষম করা হয়েছে। চালিয়ে যেতে PUK কোড লিখুন। আপনি আর <xliff:g id="_NUMBER_1">%d</xliff:g> বার চেষ্টা করতে পারবেন, তারপরে এই সিমটি আর একেবারেই ব্যবহার করা যাবে না। বিশদে জানতে পরিষেবা প্রদানকারীর সাথে যোগাযোগ করুন।</item>
<item quantity="other">সিম অক্ষম করা হয়েছে। চালিয়ে যেতে PUK কোড লিখুন। আপনি আর <xliff:g id="_NUMBER_1">%d</xliff:g> বার চেষ্টা করতে পারবেন, তারপরে এই সিমটি আর একেবারেই ব্যবহার করা যাবে না। বিশদে জানতে পরিষেবা প্রদানকারীর সাথে যোগাযোগ করুন।</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"এখন"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"বারো"</item>
<item msgid="7389464214252023751">"এক"</item>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 9396ef1..72e4603 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -158,7 +158,7 @@
<item quantity="few">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Za više informacija kontaktirajte mobilnog operatera.</item>
<item quantity="other">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Za više informacija kontaktirajte mobilnog operatera.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Sada je"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dvanaest"</item>
<item msgid="7389464214252023751">"Jedan"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 2fa0897..185a3f3 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">La targeta SIM s\'ha desactivat. Introdueix el codi PUK per continuar. Et queden <xliff:g id="_NUMBER_1">%d</xliff:g> intents; si no l\'encertes, la SIM no es podrà tornar a fer servir. Contacta amb l\'operador de telefonia mòbil per obtenir-ne més informació.</item>
<item quantity="one">La targeta SIM s\'ha desactivat. Introdueix el codi PUK per continuar. Et queda <xliff:g id="_NUMBER_0">%d</xliff:g> intent; si no l\'encertes, la SIM no es podrà tornar a fer servir. Contacta amb l\'operador de telefonia mòbil per obtenir-ne més informació.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Són les"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"i dotze"</item>
<item msgid="7389464214252023751">"Una"</item>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 2708f8f..bb01b7e 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -166,7 +166,7 @@
<item quantity="other">SIM karta je teď zablokována. Chcete-li pokračovat, zadejte kód PUK. Máte ještě <xliff:g id="_NUMBER_1">%d</xliff:g> pokusů, poté bude SIM karta natrvalo zablokována. Podrobnosti vám poskytne operátor.</item>
<item quantity="one">SIM karta je teď zablokována. Chcete-li pokračovat, zadejte kód PUK. Máte ještě <xliff:g id="_NUMBER_0">%d</xliff:g> pokus, poté bude SIM karta natrvalo zablokována. Podrobnosti vám poskytne operátor.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Je"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dvanáct"</item>
<item msgid="7389464214252023751">"Jedna"</item>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 34c248d..fbdaf0f 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">SIM-kortet er nu deaktiveret. Angiv PUK-koden for at fortsætte. Du har <xliff:g id="_NUMBER_1">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt. Kontakt dit mobilselskab for at få flere oplysninger.</item>
<item quantity="other">SIM-kortet er nu deaktiveret. Angiv PUK-koden for at fortsætte. Du har <xliff:g id="_NUMBER_1">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt. Kontakt dit mobilselskab for at få flere oplysninger.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Den er"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Tolv"</item>
<item msgid="7389464214252023751">"Et"</item>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index d8daf83f..b6127df 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">Die SIM-Karte ist jetzt deaktiviert. Gib den PUK-Code ein, um fortzufahren. Du hast noch <xliff:g id="_NUMBER_1">%d</xliff:g> Versuche, bevor die SIM-Karte endgültig gesperrt wird. Weitere Informationen erhältst du von deinem Mobilfunkanbieter.</item>
<item quantity="one">Die SIM-Karte ist jetzt deaktiviert. Gib den PUK-Code ein, um fortzufahren. Du hast noch <xliff:g id="_NUMBER_0">%d</xliff:g> Versuch, bevor die SIM-Karte endgültig gesperrt wird. Weitere Informationen erhältst du von deinem Mobilfunkanbieter.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Es ist"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"zwölf Uhr"</item>
<item msgid="7389464214252023751">"ein Uhr"</item>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 6c0916c..402e297 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">Η κάρτα SIM απενεργοποιήθηκε. Καταχωρίστε τον κωδικό PUK, για να συνεχίσετε. Απομένουν <xliff:g id="_NUMBER_1">%d</xliff:g> ακόμη προσπάθειες προτού να μην είναι πλέον δυνατή η χρήση της κάρτας SIM. Επικοινωνήστε με την εταιρεία κινητής τηλεφωνίας για λεπτομέρειες.</item>
<item quantity="one">Η κάρτα SIM απενεργοποιήθηκε. Καταχωρίστε τον κωδικό PUK, για να συνεχίσετε. Απομένει <xliff:g id="_NUMBER_0">%d</xliff:g> ακόμη προσπάθεια προτού να μην είναι πλέον δυνατή η χρήση της κάρτας SIM. Επικοινωνήστε με την εταιρεία κινητής τηλεφωνίας για λεπτομέρειες.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Είναι"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Δώδεκα"</item>
<item msgid="7389464214252023751">"Μία"</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 80c9b82..72b8085 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact operator for details.</item>
<item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact operator for details.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"It’s"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Twelve"</item>
<item msgid="7389464214252023751">"One"</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index 20c4d56..ecc0f71 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact operator for details.</item>
<item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact operator for details.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"It’s"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Twelve"</item>
<item msgid="7389464214252023751">"One"</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 80c9b82..72b8085 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact operator for details.</item>
<item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact operator for details.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"It’s"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Twelve"</item>
<item msgid="7389464214252023751">"One"</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 80c9b82..72b8085 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact operator for details.</item>
<item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact operator for details.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"It’s"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Twelve"</item>
<item msgid="7389464214252023751">"One"</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index a33d817..501dcb7 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
<item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact carrier for details.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"It’s"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Twelve"</item>
<item msgid="7389464214252023751">"One"</item>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index 98453a7..f93d933 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">Se inhabilitó la SIM. Para continuar, ingresa el código PUK. Te quedan <xliff:g id="_NUMBER_1">%d</xliff:g> intentos más antes de que la SIM quede inutilizable permanentemente. Comunícate con tu proveedor para obtener más detalles.</item>
<item quantity="one">Se inhabilitó la SIM. Para continuar, ingresa el código PUK. Te queda <xliff:g id="_NUMBER_0">%d</xliff:g> intento más antes de que la SIM quede inutilizable permanentemente. Comunícate con tu proveedor para obtener más detalles.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Son las"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Doce"</item>
<item msgid="7389464214252023751">"Una"</item>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 00bdd91..9c189d9 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">La tarjeta SIM está inhabilitada. Introduce el código PUK para continuar. Te quedan <xliff:g id="_NUMBER_1">%d</xliff:g> intentos para que la tarjeta SIM quede inservible de forma permanente. Ponte en contacto con tu operador para obtener más información.</item>
<item quantity="one">La tarjeta SIM está inhabilitada. Introduce el código PUK para continuar. Te queda <xliff:g id="_NUMBER_0">%d</xliff:g> intento para que la tarjeta SIM quede inservible de forma permanente. Ponte en contacto con tu operador para obtener más información.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Son las"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Doce"</item>
<item msgid="7389464214252023751">"Uno"</item>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index e778804..7594537 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM-kaart on nüüd keelatud. Jätkamiseks sisestage PUK-kood. Teil on jäänud veel <xliff:g id="_NUMBER_1">%d</xliff:g> katset enne, kui SIM-kaart püsivalt lukustatakse. Lisateavet küsige operaatorilt.</item>
<item quantity="one">SIM-kaart on nüüd keelatud. Jätkamiseks sisestage PUK-kood. Teil on jäänud veel <xliff:g id="_NUMBER_0">%d</xliff:g> katse enne, kui SIM-kaart püsivalt lukustatakse. Lisateavet küsige operaatorilt.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Kell on"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Kaksteist"</item>
<item msgid="7389464214252023751">"Üks"</item>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 3ebb536..8b1284d 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">Desgaitu egin da SIM txartela. Aurrera egiteko, idatzi PUK kodea. <xliff:g id="_NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela betiko erabilgaitz geratu aurretik. Xehetasunak lortzeko, jarri operadorearekin harremanetan.</item>
<item quantity="one">Desgaitu egin da SIM txartela. Aurrera egiteko, idatzi PUK kodea. <xliff:g id="_NUMBER_0">%d</xliff:g> saiakera geratzen zaizu SIM txartela betiko erabilgaitz geratu aurretik. Xehetasunak lortzeko, jarri operadorearekin harremanetan.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Ordua:"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Hamabiak"</item>
<item msgid="7389464214252023751">"Ordu bata"</item>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 0c30d03..183152e 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">سیمکارت اکنون غیرفعال است. برای ادامه دادن کد PUK را وارد کنید. <xliff:g id="_NUMBER_1">%d</xliff:g> تلاش دیگر باقی مانده است و پس از آن سیمکارت برای همیشه غیرقابلاستفاده میشود. برای اطلاع از جزئیات با شرکت مخابراتی تماس بگیرید.</item>
<item quantity="other">سیمکارت اکنون غیرفعال است. برای ادامه دادن کد PUK را وارد کنید. <xliff:g id="_NUMBER_1">%d</xliff:g> تلاش دیگر باقی مانده است و پس از آن سیمکارت برای همیشه غیرقابلاستفاده میشود. برای اطلاع از جزئیات با شرکت مخابراتی تماس بگیرید.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ساعت:"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"دوازده"</item>
<item msgid="7389464214252023751">"یک"</item>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index 6092372..ec3c596 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM-kortti on nyt lukittu. Anna PUK-koodi, niin voit jatkaa. Sinulla on <xliff:g id="_NUMBER_1">%d</xliff:g> yritystä jäljellä, ennen kuin SIM-kortti poistuu pysyvästi käytöstä. Pyydä lisätietoja operaattoriltasi.</item>
<item quantity="one">SIM-kortti on nyt lukittu. Anna PUK-koodi, niin voit jatkaa. Sinulla on <xliff:g id="_NUMBER_0">%d</xliff:g> yritys jäljellä, ennen kuin SIM-kortti poistuu pysyvästi käytöstä. Pyydä lisätietoja operaattoriltasi.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Kello on"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Kaksitoista"</item>
<item msgid="7389464214252023751">"Yksi"</item>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 8e92ffc..73705c8 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM devienne définitivement inutilisable. Pour obtenir plus de détails, communiquez avec votre fournisseur de services.</item>
<item quantity="other">La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM devienne définitivement inutilisable. Pour obtenir plus de détails, communiquez avec votre fournisseur de services.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Il est"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"douze h."</item>
<item msgid="7389464214252023751">"Une h."</item>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index cde5e68..cf4f2d0 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">La carte SIM est maintenant désactivée. Saisissez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne devienne définitivement inutilisable. Pour de plus amples informations, veuillez contacter votre opérateur.</item>
<item quantity="other">La carte SIM est maintenant désactivée. Saisissez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne devienne définitivement inutilisable. Pour de plus amples informations, veuillez contacter votre opérateur.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Il est"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"douze heures"</item>
<item msgid="7389464214252023751">"une heure"</item>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 6d85cdb..810a75b 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">A SIM está desactivada. Introduce o código PUK para continuar. Quédanche <xliff:g id="_NUMBER_1">%d</xliff:g> intentos antes de que a SIM quede inutilizable para sempre. Contacta co operador para obter información.</item>
<item quantity="one">A SIM está desactivada. Introduce o código PUK para continuar. Quédache <xliff:g id="_NUMBER_0">%d</xliff:g> intento antes de que a SIM quede inutilizable para sempre. Contacta co operador para obter información.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Hora:"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Doce"</item>
<item msgid="7389464214252023751">"Unha"</item>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index d9fdf03..538b100 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">સિમ હવે બંધ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. સિમ કાયમીરૂપે બિનઉપયોગી બની જાય એ પહેલાં તમારી પાસે <xliff:g id="_NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે. વિગતો માટે કૅરિઅરનો સંપર્ક કરો.</item>
<item quantity="other">સિમ હવે બંધ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. સિમ કાયમીરૂપે બિનઉપયોગી બની જાય એ પહેલાં તમારી પાસે <xliff:g id="_NUMBER_1">%d</xliff:g> પ્રયાસો બાકી છે. વિગતો માટે કૅરિઅરનો સંપર્ક કરો.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"સમય છે"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"બાર"</item>
<item msgid="7389464214252023751">"એક"</item>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index b004cde..f03ddd4 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">सिम बंद कर दिया गया है. जारी रखने के लिए PUK कोड डालें. आपके पास <xliff:g id="_NUMBER_1">%d</xliff:g> मौके बचे हैं, उसके बाद, सिम हमेशा के लिए काम करना बंद कर देगा. जानकारी के लिए, मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें.</item>
<item quantity="other">सिम बंद कर दिया गया है. जारी रखने के लिए PUK कोड डालें. आपके पास <xliff:g id="_NUMBER_1">%d</xliff:g> मौके बचे हैं, उसके बाद, सिम हमेशा के लिए काम करना बंद कर देगा. जानकारी के लिए, मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"यह"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"बारह"</item>
<item msgid="7389464214252023751">"एक"</item>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index c99b646..2839453 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -158,7 +158,7 @@
<item quantity="few">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Više informacija zatražite od mobilnog operatera.</item>
<item quantity="other">SIM je sada onemogućen. Unesite PUK kôd da biste nastavili. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Više informacija zatražite od mobilnog operatera.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Sada je"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dvanaest"</item>
<item msgid="7389464214252023751">"Jedan"</item>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index 4eb8bc8..de22c02 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">A SIM-kártya le van tiltva. A folytatáshoz adja meg a PUK-kódot. Még <xliff:g id="_NUMBER_1">%d</xliff:g> próbálkozása van, mielőtt végleg használhatatlanná válik a SIM-kártya. További információért forduljon a szolgáltatóhoz.</item>
<item quantity="one">A SIM-kártya le van tiltva. A folytatáshoz adja meg a PUK-kódot. Még <xliff:g id="_NUMBER_0">%d</xliff:g> próbálkozása van, mielőtt végleg használhatatlanná válik a SIM-kártya. További információért forduljon a szolgáltatóhoz.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Az idő:"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Tizenkettő"</item>
<item msgid="7389464214252023751">"Egy"</item>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index 5d9a2c0..2c10437 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">SIM քարտն անջատված է: Շարունակելու համար մուտքագրեք PUK կոդը: Մնացել է <xliff:g id="_NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն այլևս հնարավոր չի լինի օգտագործել: Մանրամասների համար դիմեք օպերատորին:</item>
<item quantity="other">SIM քարտն անջատված է: Շարունակելու համար մուտքագրեք PUK կոդը: Մնացել է <xliff:g id="_NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն այլևս հնարավոր չի լինի օգտագործել: Մանրամասների համար դիմեք օպերատորին:</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Ժամն է՝"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"տասներկու"</item>
<item msgid="7389464214252023751">"մեկ"</item>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index 603b4c2..0cd1382 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM kini dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Tersisa <xliff:g id="_NUMBER_1">%d</xliff:g> percobaan sebelum SIM tidak dapat digunakan secara permanen. Hubungi operator untuk mengetahui detailnya.</item>
<item quantity="one">SIM kini dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Tersisa <xliff:g id="_NUMBER_0">%d</xliff:g> percobaan sebelum SIM tidak dapat digunakan secara permanen. Hubungi operator untuk mengetahui detailnya.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Pukul"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dua Belas"</item>
<item msgid="7389464214252023751">"Satu"</item>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index 71f2078..dd9785d 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">SIM-kortið er nú óvirkt. Sláðu inn PUK-númer til að halda áfram. Það er <xliff:g id="_NUMBER_1">%d</xliff:g> tilraun eftir þar til SIM-kortið verður ónothæft til frambúðar. Hafðu samband við símafyrirtækið til að fá upplýsingar.</item>
<item quantity="other">SIM-kortið er nú óvirkt. Sláðu inn PUK-númer til að halda áfram. Það eru <xliff:g id="_NUMBER_1">%d</xliff:g> tilraunir eftir þar til SIM-kortið verður ónothæft til frambúðar. Hafðu samband við símafyrirtækið til að fá upplýsingar.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Hún er"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Tólf"</item>
<item msgid="7389464214252023751">"Eitt"</item>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index e0b55b3..ac2375f 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item>
<item quantity="one">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Ora"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dodici"</item>
<item msgid="7389464214252023751">"Una"</item>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index 509c463..0fadaff 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -166,7 +166,7 @@
<item quantity="other">כרטיס ה-SIM מושבת כעת. יש להזין קוד PUK כדי להמשיך. נותרו לך <xliff:g id="_NUMBER_1">%d</xliff:g> ניסיונות נוספים לפני שכרטיס ה-SIM ינעל לצמיתות. למידע נוסף, ניתן לפנות לספק שלך.</item>
<item quantity="one">כרטיס ה-SIM מושבת כעת. יש להזין קוד PUK כדי להמשיך. נותר לך <xliff:g id="_NUMBER_0">%d</xliff:g> ניסיון נוסף לפני שכרטיס ה-SIM ינעל לצמיתות. למידע נוסף, ניתן לפנות לספק שלך.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"השעה"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"שתים-עשרה"</item>
<item msgid="7389464214252023751">"אחת"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index 343d557..b0514ef 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM が無効になりました。続行するには PUK コードを入力してください。入力できるのはあと <xliff:g id="_NUMBER_1">%d</xliff:g> 回です。この回数を超えると SIM は完全に使用できなくなります。詳しくは携帯通信会社にお問い合わせください。</item>
<item quantity="one">SIM が無効になりました。続行するには PUK コードを入力してください。入力できるのはあと <xliff:g id="_NUMBER_0">%d</xliff:g> 回です。この回数を超えると SIM は完全に使用できなくなります。詳しくは携帯通信会社にお問い合わせください。</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"時刻:"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"12"</item>
<item msgid="7389464214252023751">"1"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index 9118e56..9290874 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM ბარათი ახლა დეაქტივირებულია. გასაგრძელებლად შეიყვანეთ PUK-კოდი. თქვენ დაგრჩათ <xliff:g id="_NUMBER_1">%d</xliff:g> მცდელობა, სანამ SIM სამუდამოდ გამოუსადეგარი გახდება. დეტალური ინფორმაციისთვის დაუკავშირდით თქვენს ოპერატორს.</item>
<item quantity="one">SIM ბარათი ახლა დეაქტივირებულია. გასაგრძელებლად შეიყვანეთ PUK-კოდი. თქვენ დაგრჩათ <xliff:g id="_NUMBER_0">%d</xliff:g> მცდელობა, სანამ SIM სამუდამოდ გამოუსადეგარი გახდება. დეტალური ინფორმაციისთვის დაუკავშირდით თქვენს ოპერატორს.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ახლაა"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"თორმეტი"</item>
<item msgid="7389464214252023751">"ერთი"</item>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 2270c92..f1d6449 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM картасы өшірілді. Жалғастыру үшін PUK кодын енгізіңіз. <xliff:g id="_NUMBER_1">%d</xliff:g> мүмкіндік қалды, одан кейін SIM картасы біржола құлыпталады. Толығырақ мәліметті оператордан алыңыз.</item>
<item quantity="one">SIM картасы өшірілді. Жалғастыру үшін PUK кодын енгізіңіз. <xliff:g id="_NUMBER_0">%d</xliff:g> мүмкіндік қалды, одан кейін SIM картасы біржола құлыпталады. Толығырақ мәліметті оператордан алыңыз.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Қазір"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Он екі"</item>
<item msgid="7389464214252023751">"Бір"</item>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index 80b124a..f4795b6 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">ឥឡូវនេះស៊ីមត្រូវបានបិទ។ សូមបញ្ចូលកូដ PUK ដើម្បីបន្ត។ អ្នកនៅសល់ការព្យាយាម <xliff:g id="_NUMBER_1">%d</xliff:g> ដងទៀតមុនពេលស៊ីមមិនអាចប្រើបានជាអចិន្ត្រៃយ៍។ ទាក់ទងទៅក្រុមហ៊ុនសេវាទូរសព្ទសម្រាប់ព័ត៌មានលម្អិត។</item>
<item quantity="one">ឥឡូវនេះស៊ីមត្រូវបានបិទ។ សូមបញ្ចូលកូដ PUK ដើម្បីបន្ត។ អ្នកនៅសល់ការព្យាយាម <xliff:g id="_NUMBER_0">%d</xliff:g> ដងទៀតមុនពេលស៊ីមមិនអាចប្រើបានជាអចិន្ត្រៃយ៍។ ទាក់ទងទៅក្រុមហ៊ុនសេវាទូរសព្ទសម្រាប់ព័ត៌មានលម្អិត។</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"វាជា"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"ដប់ពីរ"</item>
<item msgid="7389464214252023751">"មួយ"</item>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index f48d606..6f83dde 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">ಸಿಮ್ ಅನ್ನು ಈಗ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಸಲು PUK ಕೋಡ್ ನಮೂದಿಸಿ. ಸಿಮ್ ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಪ್ರಯೋಜಕವಾಗುವ ಮುನ್ನ ನಿಮ್ಮಲ್ಲಿ <xliff:g id="_NUMBER_1">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ. ವಿವರಗಳಿಗಾಗಿ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಿ.</item>
<item quantity="other">ಸಿಮ್ ಅನ್ನು ಈಗ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಸಲು PUK ಕೋಡ್ ನಮೂದಿಸಿ. ಸಿಮ್ ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಪ್ರಯೋಜಕವಾಗುವ ಮುನ್ನ ನಿಮ್ಮಲ್ಲಿ <xliff:g id="_NUMBER_1">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ. ವಿವರಗಳಿಗಾಗಿ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಿ.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ಇದು"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"ಹನ್ನೆರಡು"</item>
<item msgid="7389464214252023751">"ಒಂದು"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 0466009..1651be7 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM이 사용 중지되었습니다. 계속하려면 PUK 코드를 입력하세요. <xliff:g id="_NUMBER_1">%d</xliff:g>번 더 실패하면 SIM을 완전히 사용할 수 없게 됩니다. 자세한 내용은 이동통신사에 문의하세요.</item>
<item quantity="one">SIM이 사용 중지되었습니다. 계속하려면 PUK 코드를 입력하세요. <xliff:g id="_NUMBER_0">%d</xliff:g>번 더 실패하면 SIM을 완전히 사용할 수 없게 됩니다. 자세한 내용은 이동통신사에 문의하세요.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"현재 시각:"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"열두 시"</item>
<item msgid="7389464214252023751">"한 시"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index eca9b22..6d0f2ff 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM-карта азыр жарактан чыкты. Улантуу үчүн PUK-кодду киргизиңиз. SIM-картанын биротоло жарактан чыгарына <xliff:g id="_NUMBER_1">%d</xliff:g> аракет калды. Чоо-жайын билүү үчүн байланыш операторуна кайрылыңыз.</item>
<item quantity="one">SIM-карта азыр жарактан чыкты. Улантуу үчүн PUK-кодду киргизиңиз. SIM-картанын биротоло жарактан чыгаарына <xliff:g id="_NUMBER_0">%d</xliff:g> аракет калды. Чоо-жайын билүү үчүн байланыш операторуна кайрылыңыз.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Саат"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Он эки"</item>
<item msgid="7389464214252023751">"Бир"</item>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index bd6e53d..23f179e 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">ຕອນນີ້ປິດການນຳໃຊ້ SIM ແລ້ວ. ໃສ່ລະຫັດ PUK ເພື່ອດຳເນີນການຕໍ່. ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="_NUMBER_1">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຈະບໍ່ສາມາດໃຊ້ໄດ້ຖາວອນ. ກະລຸນາຕິດຕໍ່ຜູ້ໃຫ້ບໍລິການສຳລັບລາຍລະອຽດ.</item>
<item quantity="one">ຕອນນີ້ປິດການນຳໃຊ້ SIM ແລ້ວ. ໃສ່ລະຫັດ PUK ເພື່ອດຳເນີນການຕໍ່. ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="_NUMBER_0">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຈະບໍ່ສາມາດໃຊ້ໄດ້ຖາວອນ. ກະລຸນາຕິດຕໍ່ຜູ້ໃຫ້ບໍລິການສຳລັບລາຍລະອຽດ.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ມັນແມ່ນ"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"ສິບສອງ"</item>
<item msgid="7389464214252023751">"ໜຶ່ງ"</item>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index 6df93d8..9e4d169 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -166,7 +166,7 @@
<item quantity="many">SIM kortelė dabar yra išjungta. Jei norite tęsti, įveskite PUK kodą. Jums liko <xliff:g id="_NUMBER_1">%d</xliff:g> bandymo. Paskui visiškai nebegalėsite naudoti SIM kortelės. Jei reikia išsamios informacijos, susisiekite su operatoriumi.</item>
<item quantity="other">SIM kortelė dabar yra išjungta. Jei norite tęsti, įveskite PUK kodą. Jums liko <xliff:g id="_NUMBER_1">%d</xliff:g> bandymų. Paskui visiškai nebegalėsite naudoti SIM kortelės. Jei reikia išsamios informacijos, susisiekite su operatoriumi.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Dabar"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dvylika"</item>
<item msgid="7389464214252023751">"Pirma"</item>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index d906176..9ea4143 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -158,7 +158,7 @@
<item quantity="one">SIM karte tagad ir atspējota. Ievadiet PUK kodu, lai turpinātu. Varat mēģināt vēl <xliff:g id="_NUMBER_1">%d</xliff:g> reizi. Kļūdas gadījumā SIM karti vairs nevarēs izmantot. Lai iegūtu detalizētu informāciju, sazinieties ar mobilo sakaru operatoru.</item>
<item quantity="other">SIM karte tagad ir atspējota. Ievadiet PUK kodu, lai turpinātu. Varat mēģināt vēl <xliff:g id="_NUMBER_1">%d</xliff:g> reizes. Kļūdas gadījumā SIM karti vairs nevarēs izmantot. Lai iegūtu detalizētu informāciju, sazinieties ar mobilo sakaru operatoru.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Laiks:"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Divpadsmit"</item>
<item msgid="7389464214252023751">"Viens"</item>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index 221b997..e48b93d 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">SIM-картичката сега е оневозможена. Внесете PUK-код за да продолжите. Ви преостанува уште <xliff:g id="_NUMBER_1">%d</xliff:g> обид пред SIM-картичката да стане трајно неупотреблива. Контактирајте го операторот за детали.</item>
<item quantity="other">SIM-картичката сега е оневозможена. Внесете PUK-код за да продолжите. Ви преостануваат уште <xliff:g id="_NUMBER_1">%d</xliff:g> обиди пред SIM-картичката да стане трајно неупотреблива. Контактирајте го операторот за детали.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Сега е"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Дванаесет"</item>
<item msgid="7389464214252023751">"Еден"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index e664288..37ce007 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">സിം ഇപ്പോൾ പ്രവർത്തനരഹിതമാക്കി. തുടരുന്നതിന് PUK കോഡ് നൽകുക. സിം ശാശ്വതമായി ഉപയോഗശൂന്യമാകുന്നതിന് മുമ്പായി <xliff:g id="_NUMBER_1">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ശേഷിക്കുന്നു. വിശദാംശങ്ങൾക്ക് കാരിയറുമായി ബന്ധപ്പെടുക.</item>
<item quantity="one">സിം ഇപ്പോൾ പ്രവർത്തനരഹിതമാക്കി. തുടരുന്നതിന് PUK കോഡ് നൽകുക. സിം ശാശ്വതമായി ഉപയോഗശൂന്യമാകുന്നതിന് മുമ്പായി <xliff:g id="_NUMBER_0">%d</xliff:g> ശ്രമം കൂടി ശേഷിക്കുന്നു. വിശദാംശങ്ങൾക്ക് കാരിയറുമായി ബന്ധപ്പെടുക.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"സമയം"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"പന്ത്രണ്ട്"</item>
<item msgid="7389464214252023751">"ഒന്ന്"</item>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index e418731..86da688 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM-г идэвхгүй болголоо. Үргэлжлүүлэхийн тулд PUK кодыг оруулна уу. Таны SIM бүрмөсөн хүчингүй болох хүртэл <xliff:g id="_NUMBER_1">%d</xliff:g> оролдлого үлдлээ. Дэлгэрэнгүй мэдээлэл авахын тулд оператор компанитайгаа холбогдоно уу.</item>
<item quantity="one">SIM-г идэвхгүй болголоо. Үргэлжлүүлэхийн тулд PUK кодыг оруулна уу. Таны SIM бүрмөсөн хүчингүй болох хүртэл <xliff:g id="_NUMBER_0">%d</xliff:g> оролдлого үлдлээ. Дэлгэрэнгүй мэдээлэл авахын тулд оператор компанитайгаа холбогдоно уу.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Одоо"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Арван хоёр"</item>
<item msgid="7389464214252023751">"Нэг"</item>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 9d83e93..ea0c0bb 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">सिम आता बंद केलेले आहे. सुरू ठेवण्यासाठी PUK कोड टाका. सिम कायमचे बंद होण्याआधी तुमच्याकडे <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहे. तपशीलांसाठी वाहकाशी संपर्क साधा.</item>
<item quantity="other">सिम आता बंद केलेले आहे. सुरू ठेवण्यासाठी PUK कोड टाका. सिम कायमचे बंद होण्याआधी तुमच्याकडे <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत. तपशीलांसाठी वाहकाशी संपर्क साधा.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"हे आहे"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"बारा"</item>
<item msgid="7389464214252023751">"एक"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index 1c82f7c..03dca91 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">Kini SIM dilumpuhkan. Masukkan kod PUK untuk meneruskan. Tinggal <xliff:g id="_NUMBER_1">%d</xliff:g> percubaan sebelum SIM tidak boleh digunakan secara kekal. Hubungi pembawa untuk mendapatkan butiran.</item>
<item quantity="one">Kini SIM dilumpuhkan. Masukkan kod PUK untuk meneruskan. Tinggal <xliff:g id="_NUMBER_0">%d</xliff:g> percubaan sebelum SIM tidak boleh digunakan secara kekal. Hubungi pembawa untuk mendapatkan butiran.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Pukul"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dua bls"</item>
<item msgid="7389464214252023751">"Satu"</item>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index efdd779..a468a85 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် PUK ကုဒ်ကို ထည့်ပါ။ ဆင်းမ်ကဒ် အပြီးပိတ်မသွားမီ သင့်တွင် <xliff:g id="_NUMBER_1">%d</xliff:g> ကြိမ် စမ်းသပ်ခွင့် ကျန်ပါသေးသည်။ အသေးစိတ်အချက်များအတွက် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ။</item>
<item quantity="one">ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် PUK ကုဒ်ကို ထည့်ပါ။ ဆင်းမ်ကဒ် အပြီးပိတ်မသွားမီ သင့်တွင် <xliff:g id="_NUMBER_0">%d</xliff:g> ကြိမ် စမ်းသပ်ခွင့် ကျန်ပါသေးသည်။ အသေးစိတ်အချက်များအတွက် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ။</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ယခု"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"ဆယ့်နှစ်"</item>
<item msgid="7389464214252023751">"တစ်"</item>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index 17704c4..fcf06eb 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM-kortet er deaktivert nå. Skriv inn PUK-koden for å fortsette. Du har <xliff:g id="_NUMBER_1">%d</xliff:g> forsøk igjen før SIM-kortet blir permanent ubrukelig. Kontakt operatøren for å få vite mer.</item>
<item quantity="one">SIM-kortet er deaktivert nå. Skriv inn PUK-koden for å fortsette. Du har <xliff:g id="_NUMBER_0">%d</xliff:g> forsøk igjen før SIM-kortet blir permanent ubrukelig. Kontakt operatøren for å få vite mer.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Klokken"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Tolv"</item>
<item msgid="7389464214252023751">"Ett"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 77bc113..c3d92ab 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM लाई असक्षम पारिएको छ। जारी राख्न PUK कोड प्रविष्टि गर्नुहोस्। तपाईंसँग <xliff:g id="_NUMBER_1">%d</xliff:g> प्रयासहरू बाँकी छन्, त्यसपछि SIM सदाका लागि प्रयोग गर्न नमिल्ने हुन्छ। विवरणहरूका लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।</item>
<item quantity="one">SIM लाई असक्षम पारिएको छ। जारी राख्न PUK कोड प्रविष्टि गर्नुहोस्। तपाईंसँग <xliff:g id="_NUMBER_0">%d</xliff:g> प्रयास बाँकी छ, त्यसपछि SIM सदाका लागि प्रयोग गर्न नमिल्ने हुन्छ। विवरणहरूका लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"समय:"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"बाह्र"</item>
<item msgid="7389464214252023751">"एक"</item>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 3bbbb53..b3d65bb7 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">De simkaart is nu uitgeschakeld. Geef de pukcode op om door te gaan. Je hebt nog <xliff:g id="_NUMBER_1">%d</xliff:g> pogingen over voordat de simkaart definitief onbruikbaar wordt. Neem contact op met je provider voor meer informatie.</item>
<item quantity="one">De simkaart is nu uitgeschakeld. Geef de pukcode op om door te gaan. Je hebt nog <xliff:g id="_NUMBER_0">%d</xliff:g> poging over voordat de simkaart definitief onbruikbaar wordt. Neem contact op met je provider voor meer informatie.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Het is"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Twaalf"</item>
<item msgid="7389464214252023751">"Eén"</item>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index 0db20aa..94c42c4 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM କାର୍ଡକୁ ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରିଦିଆଯାଇଛି। ଜାରି ରଖିବାକୁ PUK କୋଡ୍ ଲେଖନ୍ତୁ। ଆଉ <xliff:g id="_NUMBER_1">%d</xliff:g> ଥର ଭୁଲ କୋଡ୍ ଲେଖିବା ପରେ SIM କାର୍ଡ ସ୍ଥାୟୀ ଭାବେ ଅନୁପଯୋଗୀ ହୋଇଯିବ। ବିବରଣୀ ପାଇଁ କେରିଅର୍ର ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।</item>
<item quantity="one">SIM କାର୍ଡକୁ ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରିଦିଆଯାଇଛି। ଜାରି ରଖିବାକୁ PUK କୋଡ୍ ଲେଖନ୍ତୁ। ଆଉ <xliff:g id="_NUMBER_0">%d</xliff:g> ଥର ଭୁଲ କୋଡ୍ ଲେଖିବା ପରେ SIM କାର୍ଡ ସ୍ଥାୟୀ ଭାବେ ଅନୁପଯୋଗୀ ହୋଇଯିବ। ବିବରଣୀ ପାଇଁ କେରିଅର୍ର ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ଏବେ"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"ବାର"</item>
<item msgid="7389464214252023751">"ଏକ"</item>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index 9fd9b19..9b4e28d 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">ਸਿਮ ਹੁਣ ਬੰਦ ਹੋ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਸਿਮ ਦੇ ਪੱਕੇ ਤੌਰ \'ਤੇ ਬੇਕਾਰ ਹੋ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="_NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।</item>
<item quantity="other">ਸਿਮ ਹੁਣ ਬੰਦ ਹੋ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਸਿਮ ਦੇ ਪੱਕੇ ਤੌਰ \'ਤੇ ਬੇਕਾਰ ਹੋ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="_NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ਸਮਾਂ"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"ਬਾਰਾਂ"</item>
<item msgid="7389464214252023751">"ਇੱਕ"</item>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 106fab3..2294430 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -166,7 +166,7 @@
<item quantity="other">Karta SIM została wyłączona. Wpisz kod PUK, by przejść dalej. Masz jeszcze <xliff:g id="_NUMBER_1">%d</xliff:g> próby, zanim karta SIM zostanie trwale zablokowana. Aby uzyskać szczegółowe informacje, skontaktuj się z operatorem.</item>
<item quantity="one">Karta SIM została wyłączona. Wpisz kod PUK, by przejść dalej. Masz jeszcze <xliff:g id="_NUMBER_0">%d</xliff:g> próbę, zanim karta SIM zostanie trwale zablokowana. Aby uzyskać szczegółowe informacje, skontaktuj się z operatorem.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Jest"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dwanaście"</item>
<item msgid="7389464214252023751">"Jeden"</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index 3c6a372..56815ca 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">O chip agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativa restante antes de o chip se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
<item quantity="other">O chip agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas restantes antes de o chip se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"São"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Doze"</item>
<item msgid="7389464214252023751">"Uma"</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 4f60187..4e09dc7 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item>
<item quantity="one">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"São"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Doze"</item>
<item msgid="7389464214252023751">"Google One"</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index 3c6a372..56815ca 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">O chip agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativa restante antes de o chip se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
<item quantity="other">O chip agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas restantes antes de o chip se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"São"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Doze"</item>
<item msgid="7389464214252023751">"Uma"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index 9e4170e..23be62c 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -158,7 +158,7 @@
<item quantity="other">Cardul SIM este dezactivat acum. Introduceți codul PUK pentru a continua. V-au mai rămas <xliff:g id="_NUMBER_1">%d</xliff:g> de încercări până când cardul SIM va deveni inutilizabil definitiv. Contactați operatorul pentru detalii.</item>
<item quantity="one">Cardul SIM este dezactivat acum. Introduceți codul PUK pentru a continua. V-a mai rămas <xliff:g id="_NUMBER_0">%d</xliff:g> încercare până când cardul SIM va deveni inutilizabil definitiv. Contactați operatorul pentru detalii.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Este"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Douăsprezece"</item>
<item msgid="7389464214252023751">"Unu"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index dd9bc6a..f093748 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -166,7 +166,7 @@
<item quantity="many">SIM-карта отключена. Чтобы продолжить, введите PUK-код. Осталось <xliff:g id="_NUMBER_1">%d</xliff:g> попыток. После этого SIM-карта будет заблокирована навсегда. За подробной информацией обратитесь к оператору связи.</item>
<item quantity="other">SIM-карта отключена. Чтобы продолжить, введите PUK-код. Осталось <xliff:g id="_NUMBER_1">%d</xliff:g> попытки. После этого SIM-карта будет заблокирована навсегда. За подробной информацией обратитесь к оператору связи.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Сейчас"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"двенадцать"</item>
<item msgid="7389464214252023751">"один"</item>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index 59d2a06..17122a5 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">SIM දැන් අබල කර ඇත. දිගටම කරගෙන යාමට PUK කේතය ඇතුළු කරන්න. SIM ස්ථිරවම භාවිත කළ නොහැකි බවට පත් වීමට පෙර ඔබ සතුව උත්සාහයන් <xliff:g id="_NUMBER_1">%d</xliff:g>ක් ඉතිරිව ඇත. විස්තර සඳහා වාහක සම්බන්ධ කර ගන්න.</item>
<item quantity="other">SIM දැන් අබල කර ඇත. දිගටම කරගෙන යාමට PUK කේතය ඇතුළු කරන්න. SIM ස්ථිරවම භාවිත කළ නොහැකි බවට පත් වීමට පෙර ඔබ සතුව උත්සාහයන් <xliff:g id="_NUMBER_1">%d</xliff:g>ක් ඉතිරිව ඇත. විස්තර සඳහා වාහක සම්බන්ධ කර ගන්න.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ඒ"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"දොළහ"</item>
<item msgid="7389464214252023751">"එක"</item>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index 0cd5f78..c991903 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -166,7 +166,7 @@
<item quantity="other">SIM karta je deaktivovaná. Pokračujte zadaním kódu PUK. Zostáva vám <xliff:g id="_NUMBER_1">%d</xliff:g> pokusov, potom sa SIM karta natrvalo zablokuje. Podrobnosti vám poskytne operátor.</item>
<item quantity="one">SIM karta je deaktivovaná. Pokračujte zadaním kódu PUK. Zostáva vám <xliff:g id="_NUMBER_0">%d</xliff:g> pokus, potom sa SIM karta natrvalo zablokuje. Podrobnosti vám poskytne operátor.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Práve je"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dvanásť"</item>
<item msgid="7389464214252023751">"Jedna"</item>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index 52b9d60..1aba2aa 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -166,7 +166,7 @@
<item quantity="few">Kartica SIM je zdaj onemogočena. Če želite nadaljevati, vnesite kodo PUK. Na voljo imate še <xliff:g id="_NUMBER_1">%d</xliff:g> poskuse. Potem bo kartica SIM postala trajno neuporabna. Za podrobnosti se obrnite na operaterja.</item>
<item quantity="other">Kartica SIM je zdaj onemogočena. Če želite nadaljevati, vnesite kodo PUK. Na voljo imate še <xliff:g id="_NUMBER_1">%d</xliff:g> poskusov. Potem bo kartica SIM postala trajno neuporabna. Za podrobnosti se obrnite na operaterja.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Ura je"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dvanajst"</item>
<item msgid="7389464214252023751">"Ena"</item>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 1dfb8fd..29819e2 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">Karta SIM tani është çaktivizuar. Fut kodin PUK për të vazhduar. Të kanë mbetur edhe <xliff:g id="_NUMBER_1">%d</xliff:g> përpjekje përpara se karta SIM të bëhet përgjithmonë e papërdorshme. Kontakto me operatorin për detaje.</item>
<item quantity="one">Karta SIM tani është çaktivizuar. Fut kodin PUK për të vazhduar. Të ka mbetur edhe <xliff:g id="_NUMBER_0">%d</xliff:g> përpjekje përpara se karta SIM të bëhet përgjithmonë e papërdorshme. Kontakto me operatorin për detaje.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Ora është"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Dymbëdhjetë"</item>
<item msgid="7389464214252023751">"Një"</item>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index 7bb41e9..d572f96 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -158,7 +158,7 @@
<item quantity="few">SIM је сада онемогућен. Унесите PUK кôд да бисте наставили. Имате још <xliff:g id="_NUMBER_1">%d</xliff:g> покушаја пре него што SIM постане трајно неупотребљив. Детаљне информације потражите од мобилног оператера.</item>
<item quantity="other">SIM је сада онемогућен. Унесите PUK кôд да бисте наставили. Имате још <xliff:g id="_NUMBER_1">%d</xliff:g> покушаја пре него што SIM постане трајно неупотребљив. Детаљне информације потражите од мобилног оператера.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Сада је"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"дванаест"</item>
<item msgid="7389464214252023751">"један"</item>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index 2475dc1..6608add 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM-kortet är inaktiverat. Ange PUK-koden om du vill fortsätta. <xliff:g id="_NUMBER_1">%d</xliff:g> försök återstår innan SIM-kortet blir obrukbart. Kontakta operatören för mer information.</item>
<item quantity="one">SIM-kortet är inaktiverat. Ange PUK-koden om du vill fortsätta. <xliff:g id="_NUMBER_0">%d</xliff:g> försök återstår innan SIM-kortet blir obrukbart. Kontakta operatören för mer information.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Hon är"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Tolv"</item>
<item msgid="7389464214252023751">"En"</item>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 0a1acf2..102db535 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">Sasa SIM imefungwa. Weka msimbo wa PUK ili uendelee. Umesalia na majaribio <xliff:g id="_NUMBER_1">%d</xliff:g> kabla ya SIM kuacha kufanya kazi kabisa. Wasiliana na mtoa huduma kwa maelezo.</item>
<item quantity="one">Sasa SIM imefungwa. Weka msimbo wa PUK ili uendelee. Umesalia na jaribio <xliff:g id="_NUMBER_0">%d</xliff:g> kabla ya SIM kuacha kufanya kazi kabisa. Wasiliana na mtoa huduma kwa maelezo.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Ni saa"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Sita"</item>
<item msgid="7389464214252023751">"Saba"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index 57a614a..009fb2d 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு, PUK குறியீட்டை உள்ளிடவும். நீங்கள் <xliff:g id="_NUMBER_1">%d</xliff:g> முறை மட்டுமே முயற்சிக்க முடியும். அதன்பிறகு சிம் நிரந்தரமாக முடக்கப்படும். விவரங்களுக்கு, மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளவும்.</item>
<item quantity="one">சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு, PUK குறியீட்டை உள்ளிடவும். நீங்கள் <xliff:g id="_NUMBER_0">%d</xliff:g> முறை மட்டுமே முயற்சிக்க முடியும். அதன்பிறகு சிம் நிரந்தரமாக முடக்கப்படும். விவரங்களுக்கு, மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளவும்.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"அதன்"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"பன்னிரண்டு"</item>
<item msgid="7389464214252023751">"ஒன்று"</item>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 58880c4..8f4000f 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM ఇప్పుడు నిలిపివేయబడింది. PUK కోడ్ను నమోదు చేయండి. SIM శాశ్వతంగా నిరుపయోగం కాకుండా ఉండటానికి మీకు <xliff:g id="_NUMBER_1">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి. వివరాల కోసం కారియర్ను సంప్రదించండి.</item>
<item quantity="one">SIM ఇప్పుడు నిలిపివేయబడింది. PUK కోడ్ను నమోదు చేయండి. SIM శాశ్వతంగా నిరుపయోగం కాకుండా ఉండటానికి మీకు <xliff:g id="_NUMBER_0">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది వివరాల కోసం కారియర్ను సంప్రదించండి.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"ఇప్పుడు"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"పన్నెండు"</item>
<item msgid="7389464214252023751">"ఒకటి"</item>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index bb52a7f..bb58e20 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">ซิมถูกปิดใช้งานในขณะนี้ โปรดป้อนรหัส PUK เพื่อทำต่อ คุณพยายามได้อีก <xliff:g id="_NUMBER_1">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ</item>
<item quantity="one">ซิมถูกปิดใช้งานในขณะนี้ โปรดป้อนรหัส PUK เพื่อทำต่อ คุณพยายามได้อีก <xliff:g id="_NUMBER_0">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"เวลา"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"สิบสอง"</item>
<item msgid="7389464214252023751">"หนึ่ง"</item>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index 1f480f4..ec7b924 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">Naka-disable na ang SIM. Ilagay ang PUK code upang magpatuloy. Mayroon kang <xliff:g id="_NUMBER_1">%d</xliff:g> natitirang pagsubok bago tuluyang hindi magamit ang SIM. Makipag-ugnayan sa carrier para sa mga detalye.</item>
<item quantity="other">Naka-disable na ang SIM. Ilagay ang PUK code upang magpatuloy. Mayroon kang <xliff:g id="_NUMBER_1">%d</xliff:g> na natitirang pagsubok bago tuluyang hindi magamit ang SIM. Makipag-ugnayan sa carrier para sa mga detalye.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Oras ay"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Twelve"</item>
<item msgid="7389464214252023751">"One"</item>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index 8ff1d88..92b3fb3 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM artık devre dışı. Devam etmek için PUK kodunu girin. SIM kalıcı olarak kullanım dışı kalmadan önce <xliff:g id="_NUMBER_1">%d</xliff:g> deneme hakkınız kaldı. Ayrıntılı bilgi için operatörünüzle iletişim kurun.</item>
<item quantity="one">SIM artık devre dışı. Devam etmek için PUK kodunu girin. SIM kalıcı olarak kullanım dışı kalmadan önce <xliff:g id="_NUMBER_0">%d</xliff:g> deneme hakkınız kaldı. Ayrıntılı bilgi için operatörünüzle iletişim kurun.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Saat"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"On İki"</item>
<item msgid="7389464214252023751">"Bir"</item>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index 3f0982f..2772d07 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -166,7 +166,7 @@
<item quantity="many">SIM-карту заблоковано. Щоб продовжити, введіть PUK-код. Залишилося <xliff:g id="_NUMBER_1">%d</xliff:g> спроб. Після цього SIM-карту буде назавжди заблоковано. Щоб дізнатися більше, зверніться до свого оператора.</item>
<item quantity="other">SIM-карту заблоковано. Щоб продовжити, введіть PUK-код. Залишилося <xliff:g id="_NUMBER_1">%d</xliff:g> спроби. Після цього SIM-карту буде назавжди заблоковано. Щоб дізнатися більше, зверніться до свого оператора.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Зараз"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"дванадцята"</item>
<item msgid="7389464214252023751">"перша"</item>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 3c520f9..e9e6709 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM اب غیر فعال ہے۔ جاری رکھنے کیلئے PUK کوڈ درج کریں۔ SIM کے مستقل طور پر ناقابل استعمال ہونے سے پہلے آپ کے پاس <xliff:g id="_NUMBER_1">%d</xliff:g> کوششیں بچی ہیں۔ تفصیلات کیلئے کیریئر سے رابطہ کریں۔</item>
<item quantity="one">SIM اب غیر فعال ہے۔ جاری رکھنے کیلئے PUK کوڈ درج کریں۔ SIM کے مستقل طور پر ناقابل استعمال ہونے سے پہلے آپ کے پاس <xliff:g id="_NUMBER_0">%d</xliff:g> کوشش بچی ہے۔ تفصیلات کیلئے کیریئر سے رابطہ کریں۔</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"وقت/ابھی"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"بارہ"</item>
<item msgid="7389464214252023751">"ایک"</item>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 640a987..676f7bb9 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -152,7 +152,7 @@
<item quantity="other">SIM karta faolsizlantirildi. Davom etish uchun PUK kodni kiriting. Yana <xliff:g id="_NUMBER_1">%d</xliff:g> marta xato qilsangiz, SIM kartangiz butunlay qulflanadi. Batafsil axborot olish uchun tarmoq operatoriga murojaat qiling.</item>
<item quantity="one">SIM karta faolsizlantirildi. Davom etish uchun PUK kodni kiriting. Yana <xliff:g id="_NUMBER_0">%d</xliff:g> marta xato qilsangiz, SIM kartangiz butunlay qulflanadi. Batafsil axborot olish uchun tarmoq operatoriga murojaat qiling.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Hozir"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Oʻn ikki"</item>
<item msgid="7389464214252023751">"Bir"</item>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 2a62fb8..f2cfb2a 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM hiện đã bị tắt. Hãy nhập mã PUK để tiếp tục. Bạn còn <xliff:g id="_NUMBER_1">%d</xliff:g> lần thử trước khi SIM vĩnh viễn không sử dụng được. Hãy liên hệ với nhà cung cấp dịch vụ để biết chi tiết.</item>
<item quantity="one">SIM hiện đã bị tắt. Hãy nhập mã PUK để tiếp tục. Bạn còn <xliff:g id="_NUMBER_0">%d</xliff:g> lần thử trước khi SIM vĩnh viễn không thể sử dụng được. Hãy liên hệ với nhà cung cấp dịch vụ để biết chi tiết.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Hiện là"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Mười hai"</item>
<item msgid="7389464214252023751">"Một"</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 80fac90..efa5fc3 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM 卡现已停用,请输入 PUK 码继续使用。您还可以尝试 <xliff:g id="_NUMBER_1">%d</xliff:g> 次。如果仍不正确,该 SIM 卡将永远无法使用。有关详情,请联系您的运营商。</item>
<item quantity="one">SIM 卡现已停用,请输入 PUK 码继续使用。您还可以尝试 <xliff:g id="_NUMBER_0">%d</xliff:g> 次。如果仍不正确,该 SIM 卡将永远无法使用。有关详情,请联系您的运营商。</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"时间是"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"十二"</item>
<item msgid="7389464214252023751">"一"</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index 926d601..eeff66a 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM 卡已停用。請輸入 PUK 碼以繼續進行。您還可以再試 <xliff:g id="_NUMBER_1">%d</xliff:g> 次。如果仍然輸入錯誤,SIM 卡將永久無法使用。詳情請與流動網絡供應商聯絡。</item>
<item quantity="one">SIM 卡已停用。請輸入 PUK 碼以繼續進行。您還可以再試 <xliff:g id="_NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,SIM 卡將永久無法使用。詳情請與流動網絡供應商聯絡。</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"現在是"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"十二"</item>
<item msgid="7389464214252023751">"一"</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index 728f1a9..961ef39 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -150,7 +150,7 @@
<item quantity="other">SIM 卡現在已遭停用。請輸入 PUK 碼以繼續進行。你還可以再試 <xliff:g id="_NUMBER_1">%d</xliff:g> 次,如果仍然失敗,SIM 卡將永久無法使用。詳情請與電信業者聯絡。</item>
<item quantity="one">SIM 卡現在已遭停用。請輸入 PUK 碼以繼續進行。你還可以再試 <xliff:g id="_NUMBER_0">%d</xliff:g> 次,如果仍然失敗,SIM 卡將永久無法使用。詳情請與電信業者聯絡。</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"時間是"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"十二"</item>
<item msgid="7389464214252023751">"一"</item>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index 7e0a03c..2e948b4 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -150,7 +150,7 @@
<item quantity="one">I-SIM manje ikhutshaziwe. Faka ikhodi ye-PUK ukuze uqhubeke. Unemizamo engu-<xliff:g id="_NUMBER_1">%d</xliff:g> esele ngaphambi kokuthi i-SIM ingasebenziseki unaphakade. Xhumana nenkampani yenethiwekhi ngemininingwane.</item>
<item quantity="other">I-SIM manje ikhutshaziwe. Faka ikhodi ye-PUK ukuze uqhubeke. Unemizamo engu-<xliff:g id="_NUMBER_1">%d</xliff:g> esele ngaphambi kokuthi i-SIM ingasebenziseki unaphakade. Xhumana nenkampani yenethiwekhi ngemininingwane.</item>
</plurals>
- <string name="type_clock_header" msgid="4786545441902447636">"Kuyi-"</string>
+ <!-- no translation found for type_clock_header (6782840450655632763) -->
<string-array name="type_clock_hours">
<item msgid="3543074812389379830">"Ishumi nambili"</item>
<item msgid="7389464214252023751">"Kunye"</item>
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
index 36d0659..f1158ef 100644
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
@@ -17,6 +17,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4a4a4a" />
- <padding android:padding="@dimen/ongoing_appops_chip_bg_padding" />
+ <padding android:paddingTop="@dimen/ongoing_appops_chip_bg_padding"
+ android:paddingBottom="@dimen/ongoing_appops_chip_bg_padding"/>
<corners android:radius="@dimen/ongoing_appops_chip_bg_corner_radius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index d502baa..91353d7 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -71,18 +71,38 @@
android:maxLines="1"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/pkg_divider" />
- <!-- 24 dp icon with 16 dp padding all around to mirror notification content margins -->
- <ImageButton
- android:id="@+id/info"
- android:layout_width="56dp"
- android:layout_height="56dp"
- android:layout_alignParentEnd="true"
+ <LinearLayout
+ android:id="@+id/info_and_settings"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_centerVertical="true"
- android:background="@drawable/ripple_drawable"
- android:contentDescription="@string/notification_more_settings"
- android:padding="16dp"
- android:src="@drawable/ic_info"
- android:tint="?android:attr/colorAccent" />
+ android:layout_alignParentEnd="true"
+ android:paddingHorizontal="16dp"
+ android:orientation="horizontal">
+ <!-- Optional link to app. Only appears if the channel is not disabled and the app
+asked for it -->
+ <ImageButton
+ android:id="@+id/app_settings"
+ android:layout_width="40dp"
+ android:layout_height="56dp"
+ android:layout_centerVertical="true"
+ android:paddingRight="16dp"
+ android:visibility="gone"
+ android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/notification_app_settings"
+ android:src="@drawable/ic_settings"
+ android:tint="?android:attr/colorAccent" />
+ <!-- 24 dp icon with 16 dp padding all around to mirror notification content margins -->
+ <ImageButton
+ android:id="@+id/info"
+ android:layout_width="24dp"
+ android:layout_height="56dp"
+ android:layout_centerVertical="true"
+ android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/notification_more_settings"
+ android:src="@drawable/ic_info"
+ android:tint="?android:attr/colorAccent" />
+ </LinearLayout>
</RelativeLayout>
<LinearLayout
@@ -143,50 +163,61 @@
</LinearLayout>
<!-- Settings and Done buttons -->
- <LinearLayout
+ <RelativeLayout
android:id="@+id/block_or_minimize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_guts_button_spacing"
android:layout_marginStart="@dimen/notification_guts_button_side_margin"
android:layout_marginEnd="@dimen/notification_guts_button_side_margin"
- android:gravity="end"
- android:orientation="horizontal">
-
- <!-- Optional link to app. Only appears if the channel is not disabled and the app
- asked for it -->
+ android:clipChildren="false"
+ android:clipToPadding="false">
<TextView
- android:id="@+id/app_settings"
- android:text="@string/notification_app_settings"
+ android:id="@+id/done"
+ android:text="@string/inline_done_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:visibility="gone"
- android:ellipsize="end"
- android:maxLines="1"
+ android:layout_centerVertical="true"
style="@style/TextAppearance.NotificationInfo.Button"/>
- <TextView
- android:id="@+id/block"
- android:text="@string/inline_stop_button"
+
+ <LinearLayout
+ android:id="@+id/block_buttons"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
- style="@style/TextAppearance.NotificationInfo.Button"/>
- <TextView
- android:id="@+id/minimize"
- android:text="@string/inline_minimize_button"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
- style="@style/TextAppearance.NotificationInfo.Button" />
- <TextView
- android:id="@+id/keep"
- android:minWidth="48dp"
- android:text="@string/inline_keep_button"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
- style="@style/TextAppearance.NotificationInfo.Button"/>
- </LinearLayout>
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_alignParentEnd="true"
+ android:orientation="horizontal">
+ <TextView
+ android:id="@+id/deliver_silently"
+ android:text="@string/inline_deliver_silently_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+ android:paddingRight="24dp"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ <TextView
+ android:id="@+id/block"
+ android:text="@string/inline_block_button"
+ android:minWidth="48dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ <TextView
+ android:id="@+id/minimize"
+ android:text="@string/inline_minimize_button"
+ android:minWidth="48dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ </LinearLayout>
+
+
+ </RelativeLayout>
<LinearLayout
android:id="@+id/interruptiveness_settings"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index cbdd51b..58fe811 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -29,14 +29,25 @@
android:orientation="horizontal"
android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
- android:background="@drawable/privacy_chip_bg"
android:focusable="true">
+ <TextView
+ android:id="@+id/in_use_text"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin_collapsed"
+ android:gravity="center_vertical"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:textColor="@color/status_bar_clock_color"
+ android:text="@string/ongoing_privacy_chip_in_use"
+ />
+
<LinearLayout
android:id="@+id/icons_container"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- android:layout_gravity="center_vertical|start"
+ android:layout_gravity="center_vertical"
android:gravity="center_vertical"
/>
@@ -51,7 +62,7 @@
android:gravity="center_vertical"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:textColor="@color/status_bar_clock_color"
- android:layout_marginStart="@dimen/ongoing_appops_chip_icon_margin"
- android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin"
+ android:layout_marginStart="@dimen/ongoing_appops_chip_icon_margin_collapsed"
+ android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin_collapsed"
/>
</com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 053371a..9b765f8 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> program gebruik jou <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Het dit"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privaatheidsinstellings"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Program wat jou <xliff:g id="TYPES_LIST">%s</xliff:g> gebruik"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Programme wat jou <xliff:g id="TYPES_LIST">%s</xliff:g> gebruik"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensors is af"</string>
<string name="device_services" msgid="1191212554435440592">"Toesteldienste"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Titelloos"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Maak <xliff:g id="APP_NAME">%1$s</xliff:g> oop"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Maak kennisgewinginstellings oop vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 8acd1b8..d12ba4c 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> መተግበሪያዎች የእርስዎን <xliff:g id="TYPE_5">%2$s</xliff:g> እየተጠቀሙ ነው።</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"ገባኝ"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"የግላዊነት ቅንብሮች"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"የእርስዎን <xliff:g id="TYPES_LIST">%s</xliff:g> የሚጠቀሙ መተግበሪያዎች"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"የእርስዎን <xliff:g id="TYPES_LIST">%s</xliff:g> የሚጠቀሙ መተግበሪያዎች"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"፣ "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"ዳሳሾች ጠፍተዋል"</string>
<string name="device_services" msgid="1191212554435440592">"የመሣሪያ አገልግሎቶች"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"ርዕስ የለም"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ክፈት"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"የማስታወቂያ ቅንብሮች ለ <xliff:g id="APP_NAME">%1$s</xliff:g> ክፈት"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 0312adf..7c08783 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -907,8 +907,7 @@
<item quantity="one">هناك تطبيق واحد (<xliff:g id="NUM_APPS_0">%1$d</xliff:g>) يستخدِم <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"حسنًا"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"إعدادات الخصوصية"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"التطبيق الذي يستخدِم <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"التطبيقات التي تستخدِم <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"، "</string>
@@ -927,8 +926,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"إيقاف أجهزة الاستشعار"</string>
<string name="device_services" msgid="1191212554435440592">"خدمات الأجهزة"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"بلا عنوان"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"فتح <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"فتح إعدادات الإشعارات في <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index fbaad96..c782d1b 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 70608a1..896fe34 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> tətbiq <xliff:g id="TYPE_1">%2$s</xliff:g> tətbiqindən istifadə edir.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Anladım"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Məxfilik ayarları"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"<xliff:g id="TYPES_LIST">%s</xliff:g> tətbiqindən istifadə edən tətbiq"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"<xliff:g id="TYPES_LIST">%s</xliff:g> tətbiqindən istifadə edən tətbiqlər"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensorlar deaktivdir"</string>
<string name="device_services" msgid="1191212554435440592">"Cihaz Xidmətləri"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Başlıq yoxdur"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqini açın"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün bildiriş ayarlarını açın"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<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 8a754f3..14ab0a4 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -886,8 +886,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> aplikacija koristi dozvolu <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Važi"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Podešav. privatnosti"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplikacija koja koristi dozvole <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplikacije koje koriste dozvole <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -903,8 +902,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Senzori su isključeni"</string>
<string name="device_services" msgid="1191212554435440592">"Usluge za uređaje"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Bez naslova"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otvorite <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Otvorite podešavanja obaveštenja za <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 3390fcb..0e724fa 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -917,4 +917,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 00454dd..c44b3ad 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> приложение използва <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Разбрах"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Поверит.: Настройки"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Приложение, което използва <xliff:g id="TYPES_LIST">%s</xliff:g> ви"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Приложения, които използват <xliff:g id="TYPES_LIST">%s</xliff:g> ви"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Сензорите са изключени"</string>
<string name="device_services" msgid="1191212554435440592">"Услуги за устройството"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Няма заглавие"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Отваряне на „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Отваряне на настройките за известията за „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index b864206..ec7ff6d 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index d152831..77069b2 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -888,8 +888,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> aplikacija koristi <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Razumijem"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Postavke privatnosti"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplikacija koristi odobrenja <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplikacije koriste odobrenja <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -905,8 +904,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Senzori su isključeni"</string>
<string name="device_services" msgid="1191212554435440592">"Usluge uređaja"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Bez naslova"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otvorite aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Otvorite postavke obavijesti za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index f41ea3c..1c52610 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4bdc271..735b476 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -915,4 +915,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 0c3c253..615338d 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> apps anvender din/dit <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privatlivsindstill."</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App, der anvender din/dit <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps, der anvender din/dit <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Deaktiver sensorer"</string>
<string name="device_services" msgid="1191212554435440592">"Enhedstjenester"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Ingen titel"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Åbn <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Åbn notifikationsindstillingerne for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c21288d..4e2e1e1 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -441,7 +441,7 @@
<string name="battery_saver_notification_text" msgid="820318788126672692">"Reduzierung der Leistung und Hintergrunddaten"</string>
<string name="battery_saver_notification_action_text" msgid="132118784269455533">"Energiesparmodus deaktivieren"</string>
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> nimmt alle auf deinem Bildschirm angezeigten Aktivitäten auf."</string>
- <string name="media_projection_remember_text" msgid="3103510882172746752">"Nicht erneut anzeigen"</string>
+ <string name="media_projection_remember_text" msgid="3103510882172746752">"Nicht mehr anzeigen"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Alle löschen"</string>
<string name="manage_notifications_text" msgid="2386728145475108753">"Verwalten"</string>
<string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Benachrichtigungen durch \"Bitte nicht stören\" pausiert"</string>
@@ -883,8 +883,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> App verwendet gerade: <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Datenschutzeinst."</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App, die <xliff:g id="TYPES_LIST">%s</xliff:g> verwendet"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps, die <xliff:g id="TYPES_LIST">%s</xliff:g> verwenden"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -899,8 +898,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensoren aus"</string>
<string name="device_services" msgid="1191212554435440592">"Gerätedienste"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Kein Titel"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> öffnen"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Benachrichtigungseinstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g> öffnen"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 23818956..1a0df6b 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> εφαρμογή χρησιμοποιεί το <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Κατάλαβα"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Ρυθμίσεις απορρήτου"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Εφαρμογή που χρησιμοποιεί τις λειτουργίες <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Εφαρμογές που χρησιμοποιούν τις λειτουργίες <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Αισθητήρες ανενεργοί"</string>
<string name="device_services" msgid="1191212554435440592">"Υπηρεσίες συσκευής"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Χωρίς τίτλο"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Άνοιγμα <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Άνοιγμα ρυθμίσεων ειδοποιήσεων για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 63f6773..95c1349 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> application is using your <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Got it"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privacy settings"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensors off"</string>
<string name="device_services" msgid="1191212554435440592">"Device Services"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"No title"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Open notification settings for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index d6539e7..6d55c5a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> application is using your <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Got it"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privacy settings"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensors off"</string>
<string name="device_services" msgid="1191212554435440592">"Device Services"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"No title"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Open notification settings for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 63f6773..95c1349 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> application is using your <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Got it"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privacy settings"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensors off"</string>
<string name="device_services" msgid="1191212554435440592">"Device Services"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"No title"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Open notification settings for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 63f6773..95c1349 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> application is using your <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Got it"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privacy settings"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensors off"</string>
<string name="device_services" msgid="1191212554435440592">"Device Services"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"No title"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Open notification settings for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 36ef647..266faa8 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> application is using your <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Got it"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privacy settings"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps using your <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensors off"</string>
<string name="device_services" msgid="1191212554435440592">"Device Services"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"No title"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Open <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Open notification settings for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 81cd300..b1f7068 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> aplicación está usando tu <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Entendido"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Config. privacidad"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Una app está usando tu <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps que están usando tu <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Se desactivaron los sensores"</string>
<string name="device_services" msgid="1191212554435440592">"Servicios del dispositivo"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Sin título"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Abrir la configuración de notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 16c182b..b1947fd 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index b02e457..8085224 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> rakendus kasutab üksust <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Selge"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privaatsusseaded"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Rakendus, mis kasutab üksusi <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Rakendused, mis kasutavad üksusi <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Andurid on välja lülitatud"</string>
<string name="device_services" msgid="1191212554435440592">"Seadme teenused"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Pealkiri puudub"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Ava <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Ava rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> märguandeseaded"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index b2d29c1..7f9bffa 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> aplikazio ari da <xliff:g id="TYPE_1">%2$s</xliff:g> erabiltzen.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Ados"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Pribatutasun-ezarpenak"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"<xliff:g id="TYPES_LIST">%s</xliff:g> erabiltzen ari den aplikazioa"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"<xliff:g id="TYPES_LIST">%s</xliff:g> erabiltzen ari diren aplikazioak"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sentsoreak desaktibatuta daude"</string>
<string name="device_services" msgid="1191212554435440592">"Gailuetarako zerbitzuak"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Ez du izenik"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Ireki <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Ireki <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren jakinarazpen-ezarpenak"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 4fb889b..018d6d1 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> برنامه درحال استفاده از <xliff:g id="TYPE_5">%2$s</xliff:g> شما است.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"متوجه شدم"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"تنظیمات حریم خصوصی"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"برنامهای که از <xliff:g id="TYPES_LIST">%s</xliff:g> شما استفاده میکند"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"برنامههایی که از <xliff:g id="TYPES_LIST">%s</xliff:g> شما استفاده میکنند"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"، "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"حسگرها خاموش است"</string>
<string name="device_services" msgid="1191212554435440592">"سرویسهای دستگاه"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"بدون عنوان"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"باز کردن <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"تنظیمات اعلان <xliff:g id="APP_NAME">%1$s</xliff:g> را باز کنید"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 1ab48a0..0258ccb 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="TYPE_1">%2$s</xliff:g> on <xliff:g id="NUM_APPS_0">%1$d</xliff:g> sovelluksen käytössä.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Selvä"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Tietosuoja-asetukset"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Sovellus, jolla on <xliff:g id="TYPES_LIST">%s</xliff:g> ‑käyttöoikeus"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Sovellukset, joilla on <xliff:g id="TYPES_LIST">%s</xliff:g> ‑käyttöoikeus"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Anturit pois päältä"</string>
<string name="device_services" msgid="1191212554435440592">"Laitepalvelut"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Ei nimeä"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Avaa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Avaa ilmoitusasetukset (<xliff:g id="APP_NAME">%1$s</xliff:g>)"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 554a222..a3a31356 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 2e47000..d1ce32e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 90b9f87..d76c34a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> aplicación utiliza o teu dispositivo (<xliff:g id="TYPE_1">%2$s</xliff:g>).</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"De acordo"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Config. privacidade"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplicación que utiliza o seguinte: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplicacións que utilizan o seguinte: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Desactivar sensores"</string>
<string name="device_services" msgid="1191212554435440592">"Servizos do dispositivo"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Sen título"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abre a aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Abre a configuración de notificacións para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 5717616..c84051c 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 20b9198..157f55c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 79f410a..77c3ce3 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -886,8 +886,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> aplikacija upotrebljava <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Shvaćam"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Postavke privatnosti"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplikacije koje upotrebljavaju <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplikacije koje upotrebljavaju <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -903,8 +902,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Senzori su isključeni"</string>
<string name="device_services" msgid="1191212554435440592">"Usluge uređaja"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Bez naslova"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otvorite aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Otvorite postavke obavijesti za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d0cdfb4..308295a 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> alkalmazás használja a következőt: <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Értem"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Adatvédelmi beállítások"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"A következőket használó alkalmazás: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"A következőt használó alkalmazások: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Érzékelők kikapcsolva"</string>
<string name="device_services" msgid="1191212554435440592">"Eszközszolgáltatások"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Nincs cím"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> megnyitása"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g> – az alkalmazás értesítési beállításainak megnyitása"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 41bd378..a3e05ad 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 98e1c4b..2bad55e0 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> aplikasi menggunakan <xliff:g id="TYPE_1">%2$s</xliff:g> Anda.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Oke"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Setelan privasi"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplikasi yang menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g> Anda"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplikasi yang menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g> Anda"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensor nonaktif"</string>
<string name="device_services" msgid="1191212554435440592">"Layanan Perangkat"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Tanpa judul"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Buka <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Buka setelan notifikasi untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index d1ea979..3502613 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> forrit eru að nota <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Ég skil"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Persónuvernd"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Forrit sem nota <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Forrit sem nota <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Slökkt á skynjurum"</string>
<string name="device_services" msgid="1191212554435440592">"Tækjaþjónusta"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Enginn titill"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Opna <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Opna tilkynningastillingar fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index af22c6d..42ff72a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> applicazione sta utilizzando <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Impostazioni privacy"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App che usa <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"App che utilizzano <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensori disattivati"</string>
<string name="device_services" msgid="1191212554435440592">"Servizi del dispositivo"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Senza titolo"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Apri <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Apri le impostazioni di notifica dell\'app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index a7d5138..036b0df 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -519,9 +519,9 @@
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"כווץ"</string>
<string name="accessibility_output_chooser" msgid="8185317493017988680">"החלפת מכשיר פלט"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"המסך מוצמד"</string>
- <string name="screen_pinning_description" msgid="8909878447196419623">"נשאר בתצוגה עד לביטול ההצמדה. גע בלחצנים \'הקודם\' ו\'סקירה\' והחזק כדי לבטל את ההצמדה."</string>
+ <string name="screen_pinning_description" msgid="8909878447196419623">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'סקירה\' כדי לבטל את ההצמדה."</string>
<string name="screen_pinning_description_recents_invisible" msgid="8281145542163727971">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'דף הבית\' כדי לבטל את ההצמדה."</string>
- <string name="screen_pinning_description_accessible" msgid="426190689254018656">"נשאר בתצוגה עד לביטול ההצמדה. גע בלחצן \'סקירה\' והחזק כדי לבטל את ההצמדה."</string>
+ <string name="screen_pinning_description_accessible" msgid="426190689254018656">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצן \'סקירה\' כדי לבטל את ההצמדה."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצן \'דף הבית\' כדי לבטל את ההצמדה."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"כדי לבטל את ההצמדה של מסך זה, יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'סקירה\'"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"כדי לבטל את ההצמדה של מסך זה, יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'דף הבית\'"</string>
@@ -915,4 +915,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 9095fd1..7aa7fbf 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> 個のアプリが <xliff:g id="TYPE_1">%2$s</xliff:g> を使用しています。</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"プライバシー設定"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"<xliff:g id="TYPES_LIST">%s</xliff:g>を使用しているアプリ"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"<xliff:g id="TYPES_LIST">%s</xliff:g>を使用しているアプリ"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"、 "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"センサー OFF"</string>
<string name="device_services" msgid="1191212554435440592">"デバイス サービス"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"タイトルなし"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> を開く"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g> の通知設定を開く"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 9236830..4fec284 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one">თქვენი <xliff:g id="TYPE_1">%2$s</xliff:g> გამოიყენება <xliff:g id="NUM_APPS_0">%1$d</xliff:g> აპლიკაციის მიერ.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"გასაგებია"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"კონფიდ. პარამეტრები"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"აპი, რომლის მიერაც გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"აპები, რომელთა მიერაც გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"სენსორების გამორთვა"</string>
<string name="device_services" msgid="1191212554435440592">"მოწყობილობის სერვისები"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"უსათაურო"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის გახსნა"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის შეტყობინების პარამეტრების გახსნა"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 3b46364..c5022b5 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 6811072..c03dddd 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 273470a..aa0e63f 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ca45e4d..eb94903 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 82d709b..14d93e4 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index ed05407..467a2dc 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a136772..c79743f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -893,8 +893,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> programų naudoja jūsų <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Supratau"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privatumo nustatymai"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Programa, kuri naudoja: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Programos, kurios naudoja: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -911,8 +910,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Jutikliai išjungti"</string>
<string name="device_services" msgid="1191212554435440592">"Įrenginio paslaugos"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Nėra pavadinimo"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Atidaryti „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Atidaryti „<xliff:g id="APP_NAME">%1$s</xliff:g>“ pranešimų nustatymus"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index fec4fe8..d6dc8f3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -886,8 +886,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> lietojumprogrammās tiek izmantots: <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Labi"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Konfidencialitāte"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Lietotne, kurā tiek izmantots: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Lietotnes, kurās tiek izmantots: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -903,8 +902,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensori izslēgti"</string>
<string name="device_services" msgid="1191212554435440592">"Ierīces pakalpojumi"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Nav nosaukuma"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Atvērt lietotni <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Atvērt paziņojumu iestatījumus lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 6b3e8cc..03e31f74 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 37d4b8c..f25ae1d 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 42cb765..0e5dbb7 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one">Таны <xliff:g id="TYPE_1">%2$s</xliff:g>-г <xliff:g id="NUM_APPS_0">%1$d</xliff:g> апп ашиглаж байна.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Ойлголоо"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Нууцлалын тохиргоо"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Апп таны <xliff:g id="TYPES_LIST">%s</xliff:g>-г ашиглаж байна"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Аппууд таны <xliff:g id="TYPES_LIST">%s</xliff:g>-г ашиглаж байна"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Мэдрэгчийг унтраах"</string>
<string name="device_services" msgid="1191212554435440592">"Төхөөрөмжийн үйлчилгээ"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Гарчиггүй"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г нээх"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н мэдэгдлийн тохиргоог нээх"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 44d8c4e..1b81062 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index eee6b25..df10b2f 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index b341bea..f827805 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -684,7 +684,7 @@
<string name="keyboard_key_numpad_template" msgid="8729216555174634026">"ဂဏန်းကွက်<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"စနစ်"</string>
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ပင်မ"</string>
- <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"မကြာသေးခင်က"</string>
+ <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"လတ်တလော"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"နောက်သို့"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"အကြောင်းကြားချက်များ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ကီးဘုတ် ဖြတ်လမ်းများ"</string>
@@ -879,8 +879,7 @@
<item quantity="one">အပလီကေးရှင်း <xliff:g id="NUM_APPS_0">%1$d</xliff:g> ခုက သင်၏ <xliff:g id="TYPE_1">%2$s</xliff:g> ကို အသုံးပြုနေသည်။</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"ရပါပြီ"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"ကန့်သတ်ဆက်တင်များ"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"သင့် <xliff:g id="TYPES_LIST">%s</xliff:g> ကို အသုံးပြုနေသော အက်ပ်"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"သင့် <xliff:g id="TYPES_LIST">%s</xliff:g> ကို အသုံးပြုနေသော အက်ပ်များ"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"၊ "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"အာရုံခံကိရိယာများ ပိတ်ထားသည်"</string>
<string name="device_services" msgid="1191212554435440592">"စက်ပစ္စည်းဝန်ဆောင်မှုများ"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"ခေါင်းစဉ် မရှိပါ"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကိုဖွင့်ရန်"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် အကြောင်းကြားချက်ဆက်တင်များကို ဖွင့်ရန်"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a27addb..1370468 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 1bb3664..08f3cef 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 8075ef4..7cb4b5a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -792,7 +792,7 @@
<string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g>-instellingen openen."</string>
<string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Volgorde van instellingen bewerken."</string>
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
- <string name="tuner_lock_screen" msgid="5755818559638850294">"Scherm vergrendelen"</string>
+ <string name="tuner_lock_screen" msgid="5755818559638850294">"Vergrendelingsscherm"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Uitvouwen"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimaliseren"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Sluiten"</string>
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> app gebruikt je <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Privacyinstellingen"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App die je <xliff:g id="TYPES_LIST">%s</xliff:g> gebruikt"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps die je <xliff:g id="TYPES_LIST">%s</xliff:g> gebruiken"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensoren uit"</string>
<string name="device_services" msgid="1191212554435440592">"Apparaatservices"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Geen titel"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> openen"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Instellingen voor meldingen voor <xliff:g id="APP_NAME">%1$s</xliff:g> openen"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 337b15d..b9b4ea8 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 4d8e3f1..5432975 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index d955236..b692045 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -893,8 +893,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> aplikacja używa: <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Ustawienia prywatności"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplikacje, które używają: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplikacje, które używają: <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -911,8 +910,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Wyłącz czujniki"</string>
<string name="device_services" msgid="1191212554435440592">"Usługi urządzenia"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Bez tytułu"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otwórz: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Otwórz ustawienia powiadomień z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index d2219d2..fcd7f85 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> aplicativos estão usando <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Ok"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Config. de privacidade"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App usando <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps usando <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensores desativados"</string>
<string name="device_services" msgid="1191212554435440592">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Sem título"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Abra as configurações de notificação do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 0866ffc..6579645 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> aplicação está a utilizar o(a) <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Compreendi"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Def. de privacidade"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplicações que utilizam o(a) <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplicações que utilizam o(a) <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensores desativados"</string>
<string name="device_services" msgid="1191212554435440592">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Sem título"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir a aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Abrir as definições de notificação da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index d2219d2..fcd7f85 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> aplicativos estão usando <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Ok"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Config. de privacidade"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App usando <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Apps usando <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensores desativados"</string>
<string name="device_services" msgid="1191212554435440592">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Sem título"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Abrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Abra as configurações de notificação do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index e040484..144bfc3 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -886,8 +886,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> aplicație folosește <xliff:g id="TYPE_1">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Setări de confidențialitate"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplicație care folosește <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplicații care folosesc <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -903,8 +902,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Senzori dezactivați"</string>
<string name="device_services" msgid="1191212554435440592">"Servicii pentru dispozitiv"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Fără titlu"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Accesați <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Deschideți setările pentru notificări pentru aplicația <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 338ce14..6d65592 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -893,8 +893,7 @@
<item quantity="other">Функцию \"<xliff:g id="TYPE_5">%2$s</xliff:g>\" используют <xliff:g id="NUM_APPS_4">%1$d</xliff:g> приложения.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"ОК"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Конфиденциальность"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Приложение, в котором используются операции <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Приложения, в которых используются операции <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -911,8 +910,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Датчики отключены"</string>
<string name="device_services" msgid="1191212554435440592">"Сервисы устройства"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Без названия"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Открыть приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Настройки уведомлений приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 3a0b3a4..2529f19 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other">යෙදුම් <xliff:g id="NUM_APPS_4">%1$d</xliff:g>ක් ඔබේ <xliff:g id="TYPE_5">%2$s</xliff:g> භාවිත කරමින් සිටිති.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"තේරුණා"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"පෞද්ගලිකත්ව සැකසීම්"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"ඔබගේ <xliff:g id="TYPES_LIST">%s</xliff:g> භාවිත කරන යෙදුම්"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"ඔබගේ <xliff:g id="TYPES_LIST">%s</xliff:g> භාවිත කරන යෙදුම්"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"සංවේදක ක්රියාවිරහිතයි"</string>
<string name="device_services" msgid="1191212554435440592">"උපාංග සේවා"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"මාතෘකාවක් නැත"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> විවෘත කරන්න"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා දැනුම්දීම් සැකසීම් විවෘත කරන්න"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 883243e..923384f 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -893,8 +893,7 @@
<item quantity="one"><xliff:g id="TYPE_1">%2$s</xliff:g> používa <xliff:g id="NUM_APPS_0">%1$d</xliff:g> aplikácia.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Dobre"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Nastavenia ochrany súkromia"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Aplikácia používajúca <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Aplikácie používajúce <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -911,8 +910,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Senzory sú vypnuté"</string>
<string name="device_services" msgid="1191212554435440592">"Služby zariadenia"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Bez názvu"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Otvoriť <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Otvoriť nastavenia upozornení pre <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index db40b44..d497f26 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -915,4 +915,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index ad6113e..db905ce 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 768ae7f..264698a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -886,8 +886,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> апликација користи дозволу <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Важи"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Подешав. приватности"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Апликација која користи дозволе <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Апликације које користе дозволе <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -903,8 +902,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Сензори су искључени"</string>
<string name="device_services" msgid="1191212554435440592">"Услуге за уређаје"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Без наслова"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Отворите <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Отворите подешавања обавештења за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0f36517..7e8446e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index a11e4d4..eb658ff 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a8587c1..5bcc6fe 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index a512c0c..cb9b70d 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index b8a840e..6a126ff 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one">มี <xliff:g id="NUM_APPS_0">%1$d</xliff:g> แอปพลิเคชันกำลังใช้<xliff:g id="TYPE_1">%2$s</xliff:g></item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"รับทราบ"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"การตั้งค่าความเป็นส่วนตัว"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"มีแอปกำลังใช้<xliff:g id="TYPES_LIST">%s</xliff:g>ของคุณ"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"มีหลายแอปกำลังใช้<xliff:g id="TYPES_LIST">%s</xliff:g>ของคุณ"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"เซ็นเซอร์ปิดอยู่"</string>
<string name="device_services" msgid="1191212554435440592">"บริการของอุปกรณ์"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"ไม่มีชื่อ"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"เปิด <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"เปิดการตั้งค่าการแจ้งเตือนสำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 72c5eac..1550787 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other">Ginagamit ng <xliff:g id="NUM_APPS_4">%1$d</xliff:g> na application ang iyong <xliff:g id="TYPE_5">%2$s</xliff:g>.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Mga setting ng privacy"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"App na gumagamit ng iyong <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Mga app na gumagamit ng iyong <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Naka-off ang mga sensor"</string>
<string name="device_services" msgid="1191212554435440592">"Mga Serbisyo ng Device"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Walang pamagat"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Buksan ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Buksan ang mga setting ng notification para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 5cd4e4c..9367155 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index b231c58..a850f21 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -915,4 +915,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 90447d7..c7bf3b0 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> ایپلیکیشن آپ کی <xliff:g id="TYPE_1">%2$s</xliff:g> کا استعمال کر رہی ہے۔</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"سمجھ آ گئی"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"رازداری کی ترتیبات"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"ایپ آپ کی <xliff:g id="TYPES_LIST">%s</xliff:g> کا استعمال کر رہی ہیں"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"ایپس آپ کی <xliff:g id="TYPES_LIST">%s</xliff:g> کا استعمال کر رہی ہیں"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"، "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"سینسرز آف ہیں"</string>
<string name="device_services" msgid="1191212554435440592">"آلہ کی سروس"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"کوئی عنوان نہیں ہے"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"<xliff:g id="APP_NAME">%1$s</xliff:g> کھولیں"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لئے اطلاع کی ترتیبات کھولیں"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 4a7af62..48532fa 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> ta ilova <xliff:g id="TYPE_1">%2$s</xliff:g> ishlatmoqda.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Maxfiylik sozlama-ri"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"<xliff:g id="TYPES_LIST">%s</xliff:g> ishlatayotgan ilova"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Ilovalar <xliff:g id="TYPES_LIST">%s</xliff:g> ishlatmoqda"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Sensorlar nofaol"</string>
<string name="device_services" msgid="1191212554435440592">"Qurilma xizmatlari"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Nomsiz"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Ochish: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"<xliff:g id="APP_NAME">%1$s</xliff:g> bildirishnoma sozlamalarini ochish"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index ad8d17c..b796503 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one"><xliff:g id="NUM_APPS_0">%1$d</xliff:g> ứng dụng đang dùng <xliff:g id="TYPE_1">%2$s</xliff:g> của bạn.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"OK"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Cài đặt quyền riêng tư"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Ứng dụng đang sử dụng <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Các ứng dụng đang sử dụng <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Tắt cảm biến"</string>
<string name="device_services" msgid="1191212554435440592">"Dịch vụ cho thiết bị"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Không có tiêu đề"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Mở <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"Mở mục cài đặt thông báo dành cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 0330edf..3a5dd5c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -899,4 +899,10 @@
<skip />
<!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
<skip />
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
+ <skip />
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 01797fb..8d67f5c 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one">有 <xliff:g id="NUM_APPS_0">%1$d</xliff:g> 個應用程式正在使用您的<xliff:g id="TYPE_1">%2$s</xliff:g>。</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"知道了"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"隱私權設定"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"使用<xliff:g id="TYPES_LIST">%s</xliff:g>的應用程式"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"使用<xliff:g id="TYPES_LIST">%s</xliff:g>的應用程式"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"、 "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"感應器已關閉"</string>
<string name="device_services" msgid="1191212554435440592">"裝置服務"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"無標題"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"開啟「<xliff:g id="APP_NAME">%1$s</xliff:g>」"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"開啟「<xliff:g id="APP_NAME">%1$s</xliff:g>」的通知設定"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 62b7cb6..d8d0c07 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -879,8 +879,7 @@
<item quantity="one">有 <xliff:g id="NUM_APPS_0">%1$d</xliff:g> 個應用程式正在使用你的<xliff:g id="TYPE_1">%2$s</xliff:g>。</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"我知道了"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"隱私權設定"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"使用<xliff:g id="TYPES_LIST">%s</xliff:g>的應用程式"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"使用<xliff:g id="TYPES_LIST">%s</xliff:g>的應用程式"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">"、 "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"已關閉感應器"</string>
<string name="device_services" msgid="1191212554435440592">"裝置服務"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"無標題"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"開啟「<xliff:g id="APP_NAME">%1$s</xliff:g>」"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"開啟「<xliff:g id="APP_NAME">%1$s</xliff:g>」的通知設定"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index f8bf2e3..2e0efcc 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -879,8 +879,7 @@
<item quantity="other"><xliff:g id="NUM_APPS_4">%1$d</xliff:g> izinhlelo zokusebenza zisebenzisa i-<xliff:g id="TYPE_5">%2$s</xliff:g> yakho.</item>
</plurals>
<string name="ongoing_privacy_dialog_ok" msgid="3273300106348958308">"Ngiyezwa"</string>
- <!-- no translation found for ongoing_privacy_dialog_open_settings (6773015940472748876) -->
- <skip />
+ <string name="ongoing_privacy_dialog_open_settings" msgid="6773015940472748876">"Izilungiselelo zobumfihlo"</string>
<string name="ongoing_privacy_dialog_single_app_title" msgid="6019646962021696632">"Uhlelo lokusebenza olusebenzisa i-<xliff:g id="TYPES_LIST">%s</xliff:g> yakho"</string>
<string name="ongoing_privacy_dialog_multiple_apps_title" msgid="8013356222977903365">"Izinhlelo zokusebenza ezisebenzisa i-<xliff:g id="TYPES_LIST">%s</xliff:g> yakho"</string>
<string name="ongoing_privacy_dialog_separator" msgid="6854860652480837439">", "</string>
@@ -895,8 +894,12 @@
<string name="sensor_privacy_mode" msgid="8982771253020769598">"Izinzwa zivaliwe"</string>
<string name="device_services" msgid="1191212554435440592">"Amasevisi edivayisi"</string>
<string name="music_controls_no_title" msgid="5236895307087002011">"Asikho isihloko"</string>
- <!-- no translation found for bubbles_deep_link_button_description (8895837143057564517) -->
+ <string name="bubbles_deep_link_button_description" msgid="8895837143057564517">"Vula i-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="bubbles_settings_button_description" msgid="1940331766151865776">"VUla izilungiselelo zesaziso ze-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for bubbles_prompt (2684301469286150276) -->
<skip />
- <!-- no translation found for bubbles_settings_button_description (1940331766151865776) -->
+ <!-- no translation found for no_bubbles (7173621233904687258) -->
+ <skip />
+ <!-- no translation found for yes_bubbles (668809525728633841) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 0344535..1e1245f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -967,7 +967,7 @@
<!-- Height and width of App Opp icons in Ongoing App Ops dialog -->
<dimen name="ongoing_appops_dialog_icon_size">24dp</dimen>
<!-- Left margin of App Opp icons in Ongoing App Ops dialog -->
- <dimen name="ongoing_appops_dialog_icon_margin">8dp</dimen>
+ <dimen name="ongoing_appops_dialog_icon_margin">12dp</dimen>
<!-- Height and width of Application icons in Ongoing App Ops dialog -->
<dimen name="ongoing_appops_dialog_app_icon_size">32dp</dimen>
<!-- Height and width of Plus sign in Ongoing App Ops dialog -->
@@ -988,12 +988,14 @@
<dimen name="ongoing_appops_chip_side_padding">6dp</dimen>
<!-- Padding between background of Ongoing App Ops chip and content -->
<dimen name="ongoing_appops_chip_bg_padding">0dp</dimen>
- <!-- Margin between icons of Ongoing App Ops chip -->
- <dimen name="ongoing_appops_chip_icon_margin">4dp</dimen>
+ <!-- Margin between icons of Ongoing App Ops chip when QQS-->
+ <dimen name="ongoing_appops_chip_icon_margin_collapsed">0dp</dimen>
+ <!-- Margin between icons of Ongoing App Ops chip when QS-->
+ <dimen name="ongoing_appops_chip_icon_margin_expanded">8dp</dimen>
<!-- Icon size of Ongoing App Ops chip -->
<dimen name="ongoing_appops_chip_icon_size">18dp</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
- <dimen name="ongoing_appops_chip_bg_corner_radius">12dp</dimen>
+ <dimen name="ongoing_appops_chip_bg_corner_radius">4dp</dimen>
<!-- Text size for Ongoing App Ops dialog title -->
<dimen name="ongoing_appops_dialog_title_size">20sp</dimen>
<!-- Text size for Ongoing App Ops dialog items -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index db4a6cc..db92ed2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1573,12 +1573,18 @@
<string name="inline_blocking_helper">You usually dismiss these notifications.
\nKeep showing them?</string>
+ <!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=25] -->
+ <string name="inline_done_button">Done</string>
+
<!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
<string name="inline_keep_showing">Keep showing these notifications?</string>
<!-- Notification inline controls: block notifications button -->
<string name="inline_stop_button">Stop notifications</string>
+ <!-- Notification inline controls: button to deliver notifications silently from this channel [CHAR_LIMIT=35] -->
+ <string name="inline_deliver_silently_button">Deliver Silently</string>
+
<!-- Notification inline controls: button to block notifications from this channel [CHAR_LIMIT=35] -->
<string name="inline_block_button">Block</string>
@@ -2301,6 +2307,9 @@
<!-- Content description for ongoing privacy chip. Use with multiple apps [CHAR LIMIT=NONE]-->
<string name="ongoing_privacy_chip_content_multiple_apps">Applications are using your <xliff:g id="types_list" example="camera, location">%s</xliff:g>.</string>
+ <!-- Ongoing Privacy "Chip" in use text [CHAR LIMIT=10]-->
+ <string name="ongoing_privacy_chip_in_use">In use:</string>
+
<!-- Content description for ongoing privacy chip. Use with multiple apps using same app op[CHAR LIMIT=NONE]-->
<plurals name="ongoing_privacy_chip_content_multiple_apps_single_op">
<item quantity="one"><xliff:g id="num_apps" example="1">%1$d</xliff:g> application is using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
new file mode 100644
index 0000000..f7ccb81
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system;
+
+import android.os.Looper;
+import android.util.Pair;
+import android.view.BatchedInputEventReceiver;
+import android.view.Choreographer;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventSender;
+
+/**
+ * @see android.view.InputChannel
+ */
+public class InputChannelCompat {
+
+ /**
+ * Callback for receiving event callbacks
+ */
+ public interface InputEventListener {
+ /**
+ * @param ev event to be handled
+ */
+ void onInputEvent(InputEvent ev);
+ }
+
+ /**
+ * Creates a dispatcher and receiver pair to better handle events across threads.
+ */
+ public static Pair<InputEventDispatcher, InputEventReceiver> createPair(String name,
+ Looper looper, Choreographer choreographer, InputEventListener listener) {
+ InputChannel[] channels = InputChannel.openInputChannelPair(name);
+
+ InputEventDispatcher dispatcher = new InputEventDispatcher(channels[0], looper);
+ InputEventReceiver receiver = new InputEventReceiver(channels[1], looper, choreographer,
+ listener);
+ return Pair.create(dispatcher, receiver);
+ }
+
+ /**
+ * @see BatchedInputEventReceiver
+ */
+ public static class InputEventReceiver {
+
+ private final BatchedInputEventReceiver mReceiver;
+ private final InputChannel mInputChannel;
+
+ public InputEventReceiver(InputChannel inputChannel, Looper looper,
+ Choreographer choreographer, final InputEventListener listener) {
+ mInputChannel = inputChannel;
+ mReceiver = new BatchedInputEventReceiver(inputChannel, looper, choreographer) {
+
+ @Override
+ public void onInputEvent(InputEvent event) {
+ listener.onInputEvent(event);
+ finishInputEvent(event, true /* handled */);
+ }
+ };
+ }
+
+ /**
+ * @see BatchedInputEventReceiver#dispose()
+ */
+ public void dispose() {
+ mReceiver.dispose();
+ mInputChannel.dispose();
+ }
+ }
+
+ /**
+ * @see InputEventSender
+ */
+ public static class InputEventDispatcher {
+
+ private final InputChannel mInputChannel;
+ private final InputEventSender mSender;
+
+ private InputEventDispatcher(InputChannel inputChannel, Looper looper) {
+ mInputChannel = inputChannel;
+ mSender = new InputEventSender(inputChannel, looper) { };
+ }
+
+ /**
+ * @see InputEventSender#sendInputEvent(int, InputEvent)
+ */
+ public void dispatch(InputEvent ev) {
+ mSender.sendInputEvent(ev.getSequenceNumber(), ev);
+ }
+
+ /**
+ * @see InputEventSender#dispose()
+ */
+ public void dispose() {
+ mSender.dispose();
+ mInputChannel.dispose();
+ }
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 2bdbf0b..221782e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -20,6 +20,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
/**
* @see RemoteAnimationTarget
@@ -47,6 +48,8 @@
public final boolean isNotInRecents;
public final Rect contentInsets;
+ private final SurfaceControl mStartLeash;
+
public RemoteAnimationTargetCompat(RemoteAnimationTarget app) {
taskId = app.taskId;
mode = app.mode;
@@ -59,6 +62,8 @@
isNotInRecents = app.isNotInRecents;
contentInsets = app.contentInsets;
activityType = app.windowConfiguration.getActivityType();
+
+ mStartLeash = app.startLeash;
}
public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) {
@@ -69,4 +74,14 @@
}
return appsCompat;
}
+
+ /**
+ * @see SurfaceControl#release()
+ */
+ public void release() {
+ leash.mSurfaceControl.release();
+ if (mStartLeash != null) {
+ mStartLeash.release();
+ }
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index d5bd2b2..1539582 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -299,8 +299,9 @@
displayText.toString().split(mSeparator.toString()),
anySimReadyAndInService && !missingSimsWithSubs,
subsIds);
- if (mCarrierTextCallback != null) {
- handler.post(() -> mCarrierTextCallback.updateCarrierInfo(info));
+ final CarrierTextCallback callback = mCarrierTextCallback;
+ if (callback != null) {
+ handler.post(() -> callback.updateCarrierInfo(info));
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 7218acf..fc1843b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -1,5 +1,6 @@
package com.android.keyguard;
+import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Paint.Style;
@@ -12,11 +13,13 @@
import androidx.annotation.VisibleForTesting;
+import com.android.internal.colorextraction.ColorExtractor;
import com.android.keyguard.clock.ClockManager;
import com.android.systemui.Dependency;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import java.util.TimeZone;
@@ -50,6 +53,8 @@
* Maintain state so that a newly connected plugin can be initialized.
*/
private float mDarkAmount;
+ private boolean mSupportsDarkText;
+ private int[] mColorPalette;
private final StatusBarStateController.StateListener mStateListener =
new StatusBarStateController.StateListener() {
@@ -72,6 +77,21 @@
private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
+ /**
+ * Listener for changes to the color palette.
+ *
+ * The color palette changes when the wallpaper is changed.
+ */
+ private SysuiColorExtractor.OnColorsChangedListener mColorsListener = (extractor, which) -> {
+ if ((which & WallpaperManager.FLAG_LOCK) != 0) {
+ if (extractor instanceof SysuiColorExtractor) {
+ updateColors((SysuiColorExtractor) extractor);
+ } else {
+ updateColors(Dependency.get(SysuiColorExtractor.class));
+ }
+ }
+ };
+
public KeyguardClockSwitch(Context context) {
this(context, null);
}
@@ -100,6 +120,9 @@
super.onAttachedToWindow();
Dependency.get(ClockManager.class).addOnClockChangedListener(mClockChangedListener);
Dependency.get(StatusBarStateController.class).addCallback(mStateListener);
+ SysuiColorExtractor colorExtractor = Dependency.get(SysuiColorExtractor.class);
+ colorExtractor.addOnColorsChangedListener(mColorsListener);
+ updateColors(colorExtractor);
}
@Override
@@ -107,6 +130,8 @@
super.onDetachedFromWindow();
Dependency.get(ClockManager.class).removeOnClockChangedListener(mClockChangedListener);
Dependency.get(StatusBarStateController.class).removeCallback(mStateListener);
+ Dependency.get(SysuiColorExtractor.class)
+ .removeOnColorsChangedListener(mColorsListener);
}
private void setClockPlugin(ClockPlugin plugin) {
@@ -149,6 +174,9 @@
mClockPlugin.setStyle(getPaint().getStyle());
mClockPlugin.setTextColor(getCurrentTextColor());
mClockPlugin.setDarkAmount(mDarkAmount);
+ if (mColorPalette != null) {
+ mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette);
+ }
}
/**
@@ -246,6 +274,16 @@
}
}
+ private void updateColors(SysuiColorExtractor colorExtractor) {
+ ColorExtractor.GradientColors colors = colorExtractor.getColors(WallpaperManager.FLAG_LOCK,
+ true);
+ mSupportsDarkText = colors.supportsDarkText();
+ mColorPalette = colors.getColorPalette();
+ if (mClockPlugin != null) {
+ mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette);
+ }
+ }
+
@VisibleForTesting (otherwise = VisibleForTesting.NONE)
ClockManager.ClockChangedListener getClockChangedListener() {
return mClockChangedListener;
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index db6127f..3114708 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -89,7 +89,17 @@
@Override
public void setTextColor(int color) {
mLockClock.setTextColor(color);
- mDigitalClock.setTextColor(color);
+ }
+
+ @Override
+ public void setColorPalette(boolean supportsDarkText, int[] colorPalette) {
+ if (colorPalette == null || colorPalette.length == 0) {
+ return;
+ }
+ final int length = colorPalette.length;
+ mDigitalClock.setTextColor(colorPalette[Math.max(0, length - 6)]);
+ mAnalogClock.setClockColors(colorPalette[Math.max(0, length - 6)],
+ colorPalette[Math.max(0, length - 3)]);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java b/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
index 2c709e0..e35cf11 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
@@ -78,6 +78,16 @@
mTime.setTimeZone(timeZone);
}
+ /**
+ * Sets the colors to use on the clock face.
+ * @param dark Darker color obtained from color palette.
+ * @param light Lighter color obtained from color palette.
+ */
+ public void setClockColors(int dark, int light) {
+ mHourHand.setColorFilter(dark);
+ mMinuteHand.setColorFilter(light);
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
index 87347545..3c9a4f8 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
@@ -76,10 +76,12 @@
}
/**
- * Set the color of the minute hand.
+ * Set the colors to use on the clock face.
+ * @param dark Darker color obtained from color palette.
+ * @param light Lighter color obtained from color palette.
*/
- public void setMinuteHandColor(int color) {
- mMinutePaint.setColor(color);
+ public void setClockColor(int dark, int light) {
+ mHourPaint.setColor(dark);
invalidate();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
index 0a39158..c465114 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
@@ -89,8 +89,17 @@
@Override
public void setTextColor(int color) {
mLockClock.setTextColor(color);
- mDigitalClock.setTextColor(color);
- mAnalogClock.setMinuteHandColor(color);
+ }
+
+ @Override
+ public void setColorPalette(boolean supportsDarkText, int[] colorPalette) {
+ if (colorPalette == null || colorPalette.length == 0) {
+ return;
+ }
+ final int length = colorPalette.length;
+ mDigitalClock.setTextColor(colorPalette[Math.max(0, length - 5)]);
+ mAnalogClock.setClockColor(colorPalette[Math.max(0, length - 5)],
+ colorPalette[Math.max(0, length - 2)]);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
index 17d929d..2ea39c4 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
@@ -87,6 +87,15 @@
}
@Override
+ public void setColorPalette(boolean supportsDarkText, int[] colorPalette) {
+ if (colorPalette == null || colorPalette.length == 0) {
+ return;
+ }
+ final int length = colorPalette.length;
+ mTypeClock.setClockColor(colorPalette[Math.max(0, length - 5)]);
+ }
+
+ @Override
public void dozeTimeTick() {
mTypeClock.onTimeChanged();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
index 8feae53..6f1b59c 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
@@ -43,7 +43,7 @@
private final Resources mResources;
private final String[] mHours;
private final String[] mMinutes;
- private final int mAccentColor;
+ private int mAccentColor;
private Calendar mTime;
private String mDescFormat;
private TimeZone mTimeZone;
@@ -106,6 +106,13 @@
mTime.setTimeZone(timeZone);
}
+ /**
+ * Sets the accent color used on the clock face.
+ */
+ public void setClockColor(int color) {
+ mAccentColor = color;
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index c3f61ee..5672073 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -42,6 +42,7 @@
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.PowerUI;
import com.android.systemui.privacy.PrivacyItemController;
@@ -55,7 +56,6 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.SmartReplyController;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 9b3d7ed..755d6fc 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -33,6 +33,7 @@
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -40,7 +41,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -152,6 +153,15 @@
return new VolumeDialogComponent(systemUi, context);
}
+ /**
+ * Provides status bar state controller implementation
+ */
+ @Singleton
+ @Provides
+ public StatusBarStateController provideStatusBarStateController(Context context) {
+ return new StatusBarStateControllerImpl();
+ }
+
@Singleton
@Provides
public NotificationData.KeyguardEnvironment provideKeyguardEnvironment(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 6877f5e..41bc1b2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -28,6 +28,9 @@
import static com.android.systemui.statusbar.notification.NotificationAlertingManager.alertAgain;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.app.IActivityTaskManager;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.PendingIntent;
@@ -35,11 +38,13 @@
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.util.StatsLog;
+import android.view.Display;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -51,7 +56,9 @@
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -60,6 +67,7 @@
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -93,6 +101,8 @@
private final Context mContext;
private final NotificationEntryManager mNotificationEntryManager;
+ private final IActivityTaskManager mActivityTaskManager;
+ private final BubbleTaskStackListener mTaskStackListener;
private BubbleStateChangeListener mStateChangeListener;
private BubbleExpandListener mExpandListener;
private LayoutInflater mInflater;
@@ -176,6 +186,10 @@
mStatusBarWindowController = statusBarWindowController;
mStatusBarStateListener = new StatusBarStateListener();
Dependency.get(StatusBarStateController.class).addCallback(mStatusBarStateListener);
+
+ mActivityTaskManager = ActivityTaskManager.getService();
+ mTaskStackListener = new BubbleTaskStackListener();
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
}
/**
@@ -533,6 +547,64 @@
|| autoBubbleAll;
}
+ /**
+ * This task stack listener is responsible for responding to tasks moved to the front
+ * which are on the default (main) display. When this happens, expanded bubbles must be
+ * collapsed so the user may interact with the app which was just moved to the front.
+ * <p>
+ * This listener is registered with SystemUI's ActivityManagerWrapper which dispatches
+ * these calls via a main thread Handler.
+ */
+ @MainThread
+ private class BubbleTaskStackListener extends TaskStackChangeListener {
+
+ @Nullable
+ private ActivityManager.StackInfo findStackInfo(int taskId) throws RemoteException {
+ final List<ActivityManager.StackInfo> stackInfoList =
+ mActivityTaskManager.getAllStackInfos();
+ // Iterate through stacks from top to bottom.
+ final int stackCount = stackInfoList.size();
+ for (int stackIndex = 0; stackIndex < stackCount; stackIndex++) {
+ final ActivityManager.StackInfo stackInfo = stackInfoList.get(stackIndex);
+ // Iterate through tasks from top to bottom.
+ for (int taskIndex = stackInfo.taskIds.length - 1; taskIndex >= 0; taskIndex--) {
+ if (stackInfo.taskIds[taskIndex] == taskId) {
+ return stackInfo;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onTaskMovedToFront(int taskId) {
+ ActivityManager.StackInfo stackInfo = null;
+ try {
+ stackInfo = findStackInfo(taskId);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ if (stackInfo != null && stackInfo.displayId == Display.DEFAULT_DISPLAY
+ && mStackView != null) {
+ mStackView.collapseStack();
+ }
+ }
+
+ /**
+ * This is a workaround for the case when the activity had to be created in a new task.
+ * Existing code in ActivityStackSupervisor checks the display where the activity
+ * ultimately ended up, displays an error message toast, and calls this method instead of
+ * onTaskMovedToFront.
+ */
+ // TODO(b/124058588): add requestedDisplayId to this callback, ignore unless matches
+ @Override
+ public void onActivityLaunchOnSecondaryDisplayFailed() {
+ if (mStackView != null) {
+ mStackView.collapseStack();
+ }
+ }
+ }
+
private static boolean shouldAutoBubbleMessages(Context context) {
return Settings.Secure.getInt(context.getContentResolver(),
ENABLE_AUTO_BUBBLE_MESSAGES, 0) != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index bf9d7ba..976a766 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -34,8 +34,10 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.StatsLog;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
@@ -234,6 +236,8 @@
mStackView.collapseStack(() -> {
try {
n.contentIntent.send();
+ logBubbleClickEvent(mEntry.notification,
+ StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_APP);
} catch (PendingIntent.CanceledException e) {
Log.w(TAG, "Failed to send intent for bubble with key: "
+ (mEntry != null ? mEntry.key : " null entry"));
@@ -242,7 +246,11 @@
} else if (id == R.id.settings_button) {
Intent intent = getSettingsIntent(mEntry.notification.getPackageName(),
mEntry.notification.getUid());
- mStackView.collapseStack(() -> mContext.startActivity(intent));
+ mStackView.collapseStack(() -> {
+ mContext.startActivity(intent);
+ logBubbleClickEvent(mEntry.notification,
+ StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
+ });
} else if (id == R.id.no_bubbles_button) {
setBubblesAllowed(false);
} else if (id == R.id.yes_bubbles_button) {
@@ -262,6 +270,9 @@
} else if (mOnBubbleBlockedListener != null) {
mOnBubbleBlockedListener.onBubbleBlocked(mEntry);
}
+ logBubbleClickEvent(mEntry.notification,
+ allowed ? StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_OPT_IN :
+ StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_OPT_OUT);
} catch (RemoteException e) {
Log.w(TAG, e);
}
@@ -318,4 +329,22 @@
*/
void onBubbleBlocked(NotificationEntry entry);
}
+
+ /**
+ * Logs bubble UI click event.
+ *
+ * @param notification the bubble notification that user is interacting with.
+ * @param action the user interaction enum.
+ */
+ private void logBubbleClickEvent(StatusBarNotification notification, int action) {
+ StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
+ notification.getPackageName(),
+ notification.getNotification().getChannelId(),
+ notification.getId(),
+ mStackView.getBubbleIndex(mStackView.getExpandedBubble()),
+ mStackView.getBubbleCount(),
+ action,
+ mStackView.getNormalizedXPosition(),
+ mStackView.getNormalizedYPosition());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 305f866..2b344f6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -41,6 +41,7 @@
import android.widget.FrameLayout;
import android.widget.LinearLayout;
+import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringAnimation;
@@ -384,7 +385,10 @@
/**
* Collapses the stack of bubbles.
+ * <p>
+ * Must be called from the main thread.
*/
+ @MainThread
public void collapseStack() {
if (mIsExpanded) {
// TODO: Save opened bubble & move it to top of stack
@@ -402,7 +406,10 @@
/**
* Expands the stack fo bubbles.
+ * <p>
+ * Must be called from the main thread.
*/
+ @MainThread
public void expandStack() {
if (!mIsExpanded) {
mExpandedBubble = getTopBubble();
@@ -766,7 +773,7 @@
/**
* @return the number of bubbles in the stack view.
*/
- private int getBubbleCount() {
+ public int getBubbleCount() {
return mBubbleContainer.getChildCount();
}
@@ -777,14 +784,14 @@
* @return the index of the bubble view within the bubble stack. The range of the position
* is between 0 and the bubble count minus 1.
*/
- private int getBubbleIndex(BubbleView bubbleView) {
+ public int getBubbleIndex(BubbleView bubbleView) {
return mBubbleContainer.indexOfChild(bubbleView);
}
/**
* @return the normalized x-axis position of the bubble stack rounded to 4 decimal places.
*/
- private float getNormalizedXPosition() {
+ public float getNormalizedXPosition() {
return new BigDecimal(getPosition().x / mDisplaySize.x)
.setScale(4, RoundingMode.CEILING.HALF_UP)
.floatValue();
@@ -793,7 +800,7 @@
/**
* @return the normalized y-axis position of the bubble stack rounded to 4 decimal places.
*/
- private float getNormalizedYPosition() {
+ public float getNormalizedYPosition() {
return new BigDecimal(getPosition().y / mDisplaySize.y)
.setScale(4, RoundingMode.CEILING.HALF_UP)
.floatValue();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 2c23c0c..74ddc8f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -22,6 +22,8 @@
import android.app.PendingIntent;
import android.content.Context;
import android.graphics.Color;
+import android.graphics.Insets;
+import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -32,6 +34,7 @@
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -266,6 +269,24 @@
}
}
});
+ mActivityView.setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
+ ActivityView activityView = (ActivityView) view;
+ // Here we assume that the position of the ActivityView on the screen
+ // remains regardless of IME status. When we move ActivityView, the
+ // forwardedInsets should be computed not against the current location
+ // and size, but against the post-moved location and size.
+ Point displaySize = new Point();
+ view.getContext().getDisplay().getSize(displaySize);
+ int[] windowLocation = view.getLocationOnScreen();
+ final int windowBottom = windowLocation[1] + view.getHeight();
+ final int keyboardHeight = insets.getSystemWindowInsetBottom()
+ - insets.getStableInsetBottom();
+ final int insetsBottom = Math.max(0,
+ windowBottom + keyboardHeight - displaySize.y);
+ activityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom));
+ return view.onApplyWindowInsets(insets);
+ });
+
}
return mActivityView;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 4ff27b1..8f215ff 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -35,9 +35,9 @@
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.analytics.DataCollector;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.util.AsyncSensorManager;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index fdf18ce..900ea72 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -48,6 +48,7 @@
@Singleton
public class SysuiColorExtractor extends ColorExtractor implements Dumpable {
private static final String TAG = "SysuiColorExtractor";
+ private final Tonal mTonal;
private boolean mWallpaperVisible;
private boolean mHasBackdrop;
// Colors to return when the wallpaper isn't visible
@@ -61,6 +62,7 @@
@VisibleForTesting
public SysuiColorExtractor(Context context, ExtractionType type, boolean registerVisibility) {
super(context, type);
+ mTonal = type instanceof Tonal ? (Tonal) type : new Tonal(context);
mWpHiddenColors = new GradientColors();
WallpaperColors systemColors = getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
@@ -94,7 +96,7 @@
}
private void updateDefaultGradients(WallpaperColors colors) {
- Tonal.applyFallback(colors, mWpHiddenColors);
+ mTonal.applyFallback(colors, mWpHiddenColors);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index c4c8bc7..684175c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -51,8 +51,8 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index ddd9cbf..aebadf9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -16,6 +16,7 @@
package com.android.systemui.media;
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -24,6 +25,7 @@
import android.media.IAudioService;
import android.media.IRingtonePlayer;
import android.media.Ringtone;
+import android.media.VolumeShaper;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
@@ -78,11 +80,16 @@
private final Ringtone mRingtone;
public Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa) {
+ this(token, uri, user, aa, null);
+ }
+
+ Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa,
+ @Nullable VolumeShaper.Configuration volumeShaperConfig) {
mToken = token;
mRingtone = new Ringtone(getContextForUser(user), false);
mRingtone.setAudioAttributes(aa);
- mRingtone.setUri(uri);
+ mRingtone.setUri(uri, volumeShaperConfig);
}
@Override
@@ -99,6 +106,12 @@
@Override
public void play(IBinder token, Uri uri, AudioAttributes aa, float volume, boolean looping)
throws RemoteException {
+ playWithVolumeShaping(token, uri, aa, volume, looping, null);
+ }
+ @Override
+ public void playWithVolumeShaping(IBinder token, Uri uri, AudioAttributes aa, float volume,
+ boolean looping, @Nullable VolumeShaper.Configuration volumeShaperConfig)
+ throws RemoteException {
if (LOGD) {
Log.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
+ Binder.getCallingUid() + ")");
@@ -108,7 +121,7 @@
client = mClients.get(token);
if (client == null) {
final UserHandle user = Binder.getCallingUserHandle();
- client = new Client(token, uri, user, aa);
+ client = new Client(token, uri, user, aa, volumeShaperConfig);
token.linkToDeath(client, 0);
mClients.put(token, client);
}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 65ed889..ecbf024 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -16,6 +16,7 @@
import android.content.Context
import android.util.AttributeSet
+import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
@@ -29,14 +30,25 @@
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) {
- private val iconMargin =
- context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_margin)
+ private val iconMarginExpanded = context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_appops_chip_icon_margin_expanded)
+ private val iconMarginCollapsed = context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_appops_chip_icon_margin_collapsed)
private val iconSize =
context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_size)
- val iconColor = context.resources.getColor(
+ private val iconColor = context.resources.getColor(
R.color.status_bar_clock_color, context.theme)
+ private val backgroundDrawable = context.getDrawable(R.drawable.privacy_chip_bg)
private lateinit var text: TextView
private lateinit var iconsContainer: LinearLayout
+ private lateinit var inUseText: TextView
+ var expanded = false
+ set(value) {
+ if (value != field) {
+ field = value
+ updateView()
+ }
+ }
var builder = PrivacyDialogBuilder(context, emptyList<PrivacyItem>())
var privacyList = emptyList<PrivacyItem>()
set(value) {
@@ -48,15 +60,18 @@
override fun onFinishInflate() {
super.onFinishInflate()
+ inUseText = findViewById(R.id.in_use_text)
text = findViewById(R.id.text_container)
iconsContainer = findViewById(R.id.icons_container)
}
// Should only be called if the builder icons or app changed
private fun updateView() {
+ inUseText.visibility = if (expanded) View.GONE else View.VISIBLE
+ background = if (expanded) backgroundDrawable else null
fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) {
iconsContainer.removeAllViews()
- dialogBuilder.generateIcons().forEach {
+ dialogBuilder.generateIcons().forEachIndexed { i, it ->
it.mutate()
it.setTint(iconColor)
val image = ImageView(context).apply {
@@ -64,17 +79,19 @@
scaleType = ImageView.ScaleType.CENTER_INSIDE
}
iconsContainer.addView(image, iconSize, iconSize)
- val lp = image.layoutParams as MarginLayoutParams
- lp.marginStart = iconMargin
- image.layoutParams = lp
+ if (i != 0) {
+ val lp = image.layoutParams as MarginLayoutParams
+ lp.marginStart = if (expanded) iconMarginExpanded else iconMarginCollapsed
+ image.layoutParams = lp
+ }
}
}
if (!privacyList.isEmpty()) {
generateContentDescription()
setIcons(builder, iconsContainer)
- text.visibility = if (builder.types.size == 1) VISIBLE else GONE
- if (builder.types.size == 1) {
+ text.visibility = if (builder.types.size == 1 && expanded) VISIBLE else GONE
+ if (builder.types.size == 1 && expanded) {
if (builder.app != null) {
text.setText(builder.app?.applicationName)
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index b865ce8..f91c9d9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -189,6 +189,7 @@
addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
oldBottom) -> updateAnimator(right - left));
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ updateEverything();
}
private void updateAnimator(int width) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 74e82b2..ee9255c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -124,6 +124,7 @@
private TintedIconManager mIconManager;
private TouchAnimator mStatusIconsAlphaAnimator;
private TouchAnimator mHeaderTextContainerAlphaAnimator;
+ private TouchAnimator mPrivacyChipAlphaAnimator;
private View mSystemIconsView;
private View mQuickQsStatusIcons;
@@ -212,6 +213,8 @@
mNextAlarmTextView = findViewById(R.id.next_alarm_text);
mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
mRingerModeTextView = findViewById(R.id.ringer_mode_text);
+ mPrivacyChip = findViewById(R.id.privacy_chip);
+ mPrivacyChip.setOnClickListener(this);
updateResources();
@@ -230,8 +233,6 @@
mClockView = findViewById(R.id.clock);
mClockView.setOnClickListener(this);
mDateView = findViewById(R.id.date);
- mPrivacyChip = findViewById(R.id.privacy_chip);
- mPrivacyChip.setOnClickListener(this);
mSpace = findViewById(R.id.space);
// Tint for the battery icons are handled in setupHost()
@@ -383,6 +384,7 @@
updateStatusIconAlphaAnimator();
updateHeaderTextContainerAlphaAnimator();
+ updatePrivacyChipAlphaAnimator();
}
private void updateStatusIconAlphaAnimator() {
@@ -398,6 +400,12 @@
.build();
}
+ private void updatePrivacyChipAlphaAnimator() {
+ mPrivacyChipAlphaAnimator = new TouchAnimator.Builder()
+ .addFloat(mPrivacyChip, "alpha", 1, 0, 1)
+ .build();
+ }
+
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
@@ -431,6 +439,10 @@
if (mHeaderTextContainerAlphaAnimator != null) {
mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
}
+ if (mPrivacyChipAlphaAnimator != null) {
+ mPrivacyChip.setExpanded(expansionFraction > 0.5);
+ mPrivacyChipAlphaAnimator.setPosition(keyguardExpansionFraction);
+ }
// Check the original expansion fraction - we don't want to show the tooltip until the
// panel is pulled all the way out.
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 e1a4378..e275690 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -58,10 +58,10 @@
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.PagedTileLayout.TilePage;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QuickStatusBarHeader;
-import com.android.systemui.statusbar.StatusBarStateController;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 2811505..be749ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -47,7 +47,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 4f9d428..6a49b80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -44,8 +44,9 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 98a3a54..490317b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -47,6 +47,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 546b2e9..01b0bb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -26,7 +26,6 @@
import android.os.SystemProperties;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.MathUtils;
import android.view.DisplayCutout;
import android.view.View;
import android.view.ViewGroup;
@@ -38,7 +37,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -118,8 +118,8 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- Dependency.get(StatusBarStateController.class)
- .addCallback(this, StatusBarStateController.RANK_SHELF);
+ ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+ .addCallback(this, SysuiStatusBarStateController.RANK_SHELF);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index f2ff85b..662cf51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -61,7 +61,7 @@
protected final NotificationLockscreenUserManager mLockscreenUserManager;
protected final NotificationGroupManager mGroupManager;
protected final VisualStabilityManager mVisualStabilityManager;
- private final StatusBarStateController mStatusBarStateController;
+ private final StatusBarStateControllerImpl mStatusBarStateController;
private final NotificationEntryManager mEntryManager;
// Lazy
@@ -82,7 +82,7 @@
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
- StatusBarStateController statusBarStateController,
+ StatusBarStateControllerImpl statusBarStateController,
NotificationEntryManager notificationEntryManager,
Lazy<ShadeController> shadeController) {
mLockscreenUserManager = notificationLockscreenUserManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
similarity index 60%
rename from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 54bce1c..ad5aa57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,27 +11,22 @@
* 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.statusbar;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
-import android.annotation.IntDef;
import android.util.FloatProperty;
import android.view.animation.Interpolator;
import com.android.internal.annotations.GuardedBy;
import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
-import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.CallbackController;
-import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Comparator;
@@ -42,24 +37,25 @@
* Tracks and reports on {@link StatusBarState}.
*/
@Singleton
-public class StatusBarStateController implements CallbackController<StateListener> {
+public class StatusBarStateControllerImpl implements SysuiStatusBarStateController,
+ CallbackController<StateListener> {
private static final String TAG = "SbStateController";
private static final int MAX_STATE = StatusBarState.FULLSCREEN_USER_SWITCHER;
private static final int MIN_STATE = StatusBarState.SHADE;
- private static final Comparator <RankedListener> mComparator
- = (o1, o2) -> Integer.compare(o1.rank, o2.rank);
- private static final FloatProperty<StatusBarStateController> SET_DARK_AMOUNT_PROPERTY =
- new FloatProperty<StatusBarStateController>("mDozeAmount") {
+ private static final Comparator<RankedListener> sComparator =
+ Comparator.comparingInt(o -> o.mRank);
+ private static final FloatProperty<StatusBarStateControllerImpl> SET_DARK_AMOUNT_PROPERTY =
+ new FloatProperty<StatusBarStateControllerImpl>("mDozeAmount") {
@Override
- public void setValue(StatusBarStateController object, float value) {
+ public void setValue(StatusBarStateControllerImpl object, float value) {
object.setDozeAmountInternal(value);
}
@Override
- public Float get(StatusBarStateController object) {
+ public Float get(StatusBarStateControllerImpl object) {
return object.mDozeAmount;
}
};
@@ -95,29 +91,16 @@
*/
private Interpolator mDozeInterpolator = Interpolators.FAST_OUT_SLOW_IN;
- // TODO: b/115739177 (remove this explicit ordering if we can)
- @Retention(SOURCE)
- @IntDef({RANK_STATUS_BAR, RANK_STATUS_BAR_WINDOW_CONTROLLER, RANK_STACK_SCROLLER, RANK_SHELF})
- public @interface SbStateListenerRank {}
- // This is the set of known dependencies when updating StatusBarState
- public static final int RANK_STATUS_BAR = 0;
- public static final int RANK_STATUS_BAR_WINDOW_CONTROLLER = 1;
- public static final int RANK_STACK_SCROLLER = 2;
- public static final int RANK_SHELF = 3;
-
@Inject
- public StatusBarStateController() {
+ public StatusBarStateControllerImpl() {
}
+ @Override
public int getState() {
return mState;
}
- /**
- * Update the status bar state
- * @param state see {@link StatusBarState} for valid options
- * @return {@code true} if the state changed, else {@code false}
- */
+ @Override
public boolean setState(int state) {
if (state > MAX_STATE || state < MIN_STATE) {
throw new IllegalArgumentException("Invalid state " + state);
@@ -127,40 +110,38 @@
}
synchronized (mListeners) {
for (RankedListener rl : new ArrayList<>(mListeners)) {
- rl.listener.onStatePreChange(mState, state);
+ rl.mListener.onStatePreChange(mState, state);
}
mLastState = mState;
mState = state;
for (RankedListener rl : new ArrayList<>(mListeners)) {
- rl.listener.onStateChanged(mState);
+ rl.mListener.onStateChanged(mState);
}
for (RankedListener rl : new ArrayList<>(mListeners)) {
- rl.listener.onStatePostChange();
+ rl.mListener.onStatePostChange();
}
}
return true;
}
+ @Override
public boolean isDozing() {
return mIsDozing;
}
+ @Override
public float getDozeAmount() {
return mDozeAmount;
}
+ @Override
public float getInterpolatedDozeAmount() {
return mDozeInterpolator.getInterpolation(mDozeAmount);
}
- /**
- * Update the dozing state from {@link StatusBar}'s perspective
- * @param isDozing well, are we dozing?
- * @return {@code true} if the state changed, else {@code false}
- */
- @SuppressWarnings("UnusedReturnValue")
+ @Override
public boolean setIsDozing(boolean isDozing) {
if (mIsDozing == isDozing) {
return false;
@@ -170,19 +151,14 @@
synchronized (mListeners) {
for (RankedListener rl : new ArrayList<>(mListeners)) {
- rl.listener.onDozingChanged(isDozing);
+ rl.mListener.onDozingChanged(isDozing);
}
}
return true;
}
- /**
- * Changes the current doze amount.
- *
- * @param dozeAmount New doze/dark amount.
- * @param animated If change should be animated or not. This will cancel current animations.
- */
+ @Override
public void setDozeAmount(float dozeAmount, boolean animated) {
if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
if (animated && mDozeAmountTarget == dozeAmount) {
@@ -217,27 +193,32 @@
float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
synchronized (mListeners) {
for (RankedListener rl : new ArrayList<>(mListeners)) {
- rl.listener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
+ rl.mListener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
}
}
}
+ @Override
public boolean goingToFullShade() {
return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide;
}
+ @Override
public void setLeaveOpenOnKeyguardHide(boolean leaveOpen) {
mLeaveOpenOnKeyguardHide = leaveOpen;
}
+ @Override
public boolean leaveOpenOnKeyguardHide() {
return mLeaveOpenOnKeyguardHide;
}
+ @Override
public boolean fromShadeLocked() {
return mLastState == StatusBarState.SHADE_LOCKED;
}
+ @Override
public void addCallback(StateListener listener) {
synchronized (mListeners) {
addListenerInternalLocked(listener, Integer.MAX_VALUE);
@@ -254,6 +235,8 @@
* StatusBarState out of StatusBar.java. Any new listeners should be built not to need ranking
* (i.e., they are non-dependent on the order of operations of StatusBarState listeners).
*/
+ @Deprecated
+ @Override
public void addCallback(StateListener listener, @SbStateListenerRank int rank) {
synchronized (mListeners) {
addListenerInternalLocked(listener, rank);
@@ -264,91 +247,38 @@
private void addListenerInternalLocked(StateListener listener, int rank) {
// Protect against double-subscribe
for (RankedListener rl : mListeners) {
- if (rl.listener.equals(listener)) {
+ if (rl.mListener.equals(listener)) {
return;
}
}
- RankedListener rl = new RankedListener(listener, rank);
+ RankedListener rl = new SysuiStatusBarStateController.RankedListener(listener, rank);
mListeners.add(rl);
- mListeners.sort(mComparator);
+ mListeners.sort(sComparator);
}
+
+ @Override
public void removeCallback(StateListener listener) {
synchronized (mListeners) {
- mListeners.removeIf((it) -> it.listener.equals(listener));
+ mListeners.removeIf((it) -> it.mListener.equals(listener));
}
}
+ @Override
public void setKeyguardRequested(boolean keyguardRequested) {
mKeyguardRequested = keyguardRequested;
}
+ @Override
public boolean isKeyguardRequested() {
return mKeyguardRequested;
}
+ /**
+ * Returns String readable state of status bar from {@link StatusBarState}
+ */
public static String describe(int state) {
return StatusBarState.toShortString(state);
}
-
- private class RankedListener {
- private final StateListener listener;
- private final int rank;
-
- private RankedListener(StateListener l, int r) {
- listener = l;
- rank = r;
- }
- }
-
- /**
- * Listener for StatusBarState updates
- */
- public interface StateListener {
-
- /**
- * Callback before the new state is applied, for those who need to preempt the change.
- *
- * @param oldState state before the change
- * @param newState new state to be applied in {@link #onStateChanged}
- */
- public default void onStatePreChange(int oldState, int newState) {
- }
-
- /**
- * Callback after all listeners have had a chance to update based on the state change
- */
- public default void onStatePostChange() {
- }
-
- /**
- * Required callback. Get the new state and do what you will with it. Keep in mind that
- * other listeners are typically unordered and don't rely on your work being done before
- * other peers.
- *
- * Only called if the state is actually different.
- *
- * @param newState the new {@link StatusBarState}
- */
- default void onStateChanged(int newState) {
- }
-
- /**
- * Callback to be notified when Dozing changes. Dozing is stored separately from state.
- *
- * @param isDozing {@code true} if dozing according to {@link StatusBar}
- */
- public default void onDozingChanged(boolean isDozing) {}
-
- /**
- * Callback to be notified when the doze amount changes. Useful for animations.
- * Note: this will be called for each animation frame. Please be careful to avoid
- * performance regressions.
- *
- * @param linear A number from 0 to 1, where 1 means that the device is dozing.
- * @param eased Same as {@code linear} but transformed by an interpolator.
- */
- default void onDozeAmountChanged(float linear, float eased) {}
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
new file mode 100644
index 0000000..dc5e1e9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import java.lang.annotation.Retention;
+
+/**
+ * Sends updates to {@link StateListener}s about changes to the status bar state and dozing state
+ */
+public interface SysuiStatusBarStateController extends StatusBarStateController {
+
+ // TODO: b/115739177 (remove this explicit ordering if we can)
+ @Retention(SOURCE)
+ @IntDef({RANK_STATUS_BAR, RANK_STATUS_BAR_WINDOW_CONTROLLER, RANK_STACK_SCROLLER, RANK_SHELF})
+ @interface SbStateListenerRank {}
+ // This is the set of known dependencies when updating StatusBarState
+ int RANK_STATUS_BAR = 0;
+ int RANK_STATUS_BAR_WINDOW_CONTROLLER = 1;
+ int RANK_STACK_SCROLLER = 2;
+ int RANK_SHELF = 3;
+
+ /**
+ * Add a listener and a rank based on the priority of this message
+ * @param listener the listener
+ * @param rank the order in which you'd like to be called. Ranked listeners will be
+ * notified before unranked, and we will sort ranked listeners from low to high
+ *
+ * @deprecated This method exists only to solve latent inter-dependencies from refactoring
+ * StatusBarState out of StatusBar.java. Any new listeners should be built not to need ranking
+ * (i.e., they are non-dependent on the order of operations of StatusBarState listeners).
+ */
+ @Deprecated
+ void addCallback(StateListener listener, int rank);
+
+ /**
+ * Update the status bar state
+ * @param state see {@link StatusBarState} for valid options
+ * @return {@code true} if the state changed, else {@code false}
+ */
+ boolean setState(int state);
+
+ /**
+ * Update the dozing state from {@link StatusBar}'s perspective
+ * @param isDozing well, are we dozing?
+ * @return {@code true} if the state changed, else {@code false}
+ */
+ boolean setIsDozing(boolean isDozing);
+
+ /**
+ * Changes the current doze amount.
+ *
+ * @param dozeAmount New doze/dark amount.
+ * @param animated If change should be animated or not. This will cancel current animations.
+ */
+ void setDozeAmount(float dozeAmount, boolean animated);
+
+ /**
+ * Sets whether to leave status bar open when hiding keyguard
+ */
+ void setLeaveOpenOnKeyguardHide(boolean leaveOpen);
+
+ /**
+ * Whether to leave status bar open when hiding keyguard
+ */
+ boolean leaveOpenOnKeyguardHide();
+
+ /**
+ * Interpolated doze amount
+ */
+ float getInterpolatedDozeAmount();
+
+ /**
+ * Whether status bar is going to full shade
+ */
+ boolean goingToFullShade();
+
+ /**
+ * Whether the previous state of the status bar was the shade locked
+ */
+ boolean fromShadeLocked();
+
+ /**
+ * Set keyguard requested
+ */
+ void setKeyguardRequested(boolean keyguardRequested);
+
+ /**
+ * Is keyguard requested
+ */
+ boolean isKeyguardRequested();
+
+ /**
+ * Listener with rankings SbStateListenerRank that have dependencies so must be updated
+ * in a certain order
+ */
+ class RankedListener {
+ final StateListener mListener;
+ final int mRank;
+
+ RankedListener(StateListener l, int r) {
+ mListener = l;
+ mRank = r;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index c50f10b..7cbe1a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -35,8 +35,8 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationPresenter;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index 54ed0d9..8b522a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -16,8 +16,10 @@
package com.android.systemui.statusbar.notification.collection;
+import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
+import android.app.Person;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.SnoozeCriterion;
@@ -235,8 +237,11 @@
if (mRankingMap != null) {
getRanking(statusBarNotification.getKey(), mTmpRanking);
if (mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
- || statusBarNotification.getNotification().isForegroundService()
- || statusBarNotification.getNotification().hasMediaSession()) {
+ || isImportantOngoing(statusBarNotification.getNotification())
+ || statusBarNotification.getNotification().hasMediaSession()
+ || hasPerson(statusBarNotification.getNotification())
+ || hasStyle(statusBarNotification.getNotification(),
+ Notification.MessagingStyle.class)) {
return true;
}
if (mGroupManager.isSummaryOfGroup(statusBarNotification)) {
@@ -252,6 +257,24 @@
return false;
}
+ private boolean isImportantOngoing(Notification notification) {
+ return notification.isForegroundService()
+ && mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_LOW;
+ }
+
+ private boolean hasStyle(Notification notification, Class targetStyle) {
+ Class<? extends Notification.Style> style = notification.getNotificationStyle();
+ return targetStyle.equals(style);
+ }
+
+ private boolean hasPerson(Notification notification) {
+ // TODO: cache favorite and recent contacts to check contact affinity
+ ArrayList<Person> people = notification.extras != null
+ ? notification.extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST)
+ : new ArrayList<>();
+ return people != null && !people.isEmpty();
+ }
+
public boolean isAmbient(String key) {
if (mRankingMap != null) {
getRanking(key, mTmpRanking);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
index 43b5503..a1fcbeb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
@@ -30,6 +30,9 @@
/** Counter tag for when the user hits 'stop notifications' in the blocking helper. */
public static final String BLOCKING_HELPER_STOP_NOTIFICATIONS =
"blocking_helper_stop_notifications";
+ /** Counter tag for when the user hits 'deliver silently' in the blocking helper. */
+ public static final String BLOCKING_HELPER_DELIVER_SILENTLY =
+ "blocking_helper_deliver_silently";
/** Counter tag for when the user hits 'show silently' in the blocking helper. */
public static final String BLOCKING_HELPER_TOGGLE_SILENT =
"blocking_helper_toggle_silent";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 5e52419..c4ecb82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -33,9 +33,9 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.UiOffloadThread;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 8095615..1dc48d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -68,6 +68,7 @@
public class NotificationContentView extends FrameLayout {
private static final String TAG = "NotificationContentView";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final int VISIBLE_TYPE_CONTRACTED = 0;
public static final int VISIBLE_TYPE_EXPANDED = 1;
public static final int VISIBLE_TYPE_HEADSUP = 2;
@@ -1319,6 +1320,14 @@
SmartRepliesAndActions smartRepliesAndActions =
chooseSmartRepliesAndActions(mSmartReplyConstants, entry);
+ if (DEBUG) {
+ Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.",
+ entry.notification.getKey(),
+ smartRepliesAndActions.smartActions == null ? 0 :
+ smartRepliesAndActions.smartActions.actions.size(),
+ smartRepliesAndActions.smartReplies == null ? 0 :
+ smartRepliesAndActions.smartReplies.choices.length));
+ }
applyRemoteInput(entry, smartRepliesAndActions.hasFreeformRemoteInput);
applySmartReplyView(smartRepliesAndActions, entry);
@@ -1341,6 +1350,10 @@
notification.findRemoteInputActionPair(true /* freeform */);
if (!smartReplyConstants.isEnabled()) {
+ if (DEBUG) {
+ Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for "
+ + entry.notification.getKey());
+ }
return new SmartRepliesAndActions(null, null, freeformRemoteInputActionPair != null);
}
// Only use smart replies from the app if they target P or above. We have this check because
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index aa221993..fea01ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -42,11 +42,11 @@
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index c7b2fab..3723731 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -84,6 +84,7 @@
public static final int ACTION_UNDO = 1;
public static final int ACTION_TOGGLE_SILENT = 2;
public static final int ACTION_BLOCK = 3;
+ public static final int ACTION_DELIVER_SILENTLY = 4;
private INotificationManager mINotificationManager;
private PackageManager mPm;
@@ -135,30 +136,26 @@
};
private OnClickListener mOnToggleSilent = v -> {
- Runnable saveImportance = () -> {
- swapContent(ACTION_TOGGLE_SILENT, true /* animate */);
- if (mIsForBlockingHelper) {
- mMetricsLogger.write(getLogMaker()
- .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
- .setType(MetricsEvent.TYPE_ACTION)
- .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_ALERT_ME));
- }
- };
- if (mCheckSaveListener != null) {
- mCheckSaveListener.checkSave(saveImportance, mSbn);
- } else {
- saveImportance.run();
- }
+ handleSaveImportance(ACTION_TOGGLE_SILENT, MetricsEvent.BLOCKING_HELPER_CLICK_ALERT_ME);
+ };
+
+ private OnClickListener mOnDeliverSilently = v -> {
+ handleSaveImportance(
+ ACTION_DELIVER_SILENTLY, MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT);
};
private OnClickListener mOnStopOrMinimizeNotifications = v -> {
+ handleSaveImportance(ACTION_BLOCK, MetricsEvent.BLOCKING_HELPER_CLICK_BLOCKED);
+ };
+
+ private void handleSaveImportance(int action, int metricsSubtype) {
Runnable saveImportance = () -> {
- swapContent(ACTION_BLOCK, true /* animate */);
+ swapContent(action, true /* animate */);
if (mIsForBlockingHelper) {
mMetricsLogger.write(getLogMaker()
.setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
.setType(MetricsEvent.TYPE_ACTION)
- .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_BLOCKED));
+ .setSubtype(metricsSubtype));
}
};
if (mCheckSaveListener != null) {
@@ -166,7 +163,7 @@
} else {
saveImportance.run();
}
- };
+ }
private OnClickListener mOnUndo = v -> {
// Reset exit counter that we'll log and record an undo event separately (not an exit event)
@@ -283,8 +280,6 @@
mMetricsLogger.write(notificationControlsLogMaker());
}
-
-
private void bindHeader() throws RemoteException {
// Package name
Drawable pkgicon = null;
@@ -479,17 +474,21 @@
findViewById(R.id.block_or_minimize).setVisibility(VISIBLE);
findViewById(R.id.interruptiveness_settings).setVisibility(GONE);
View block = findViewById(R.id.block);
- TextView keep = findViewById(R.id.keep);
+ TextView done = findViewById(R.id.done);
View minimize = findViewById(R.id.minimize);
+ View deliverSilently = findViewById(R.id.deliver_silently);
+
block.setOnClickListener(mOnStopOrMinimizeNotifications);
- keep.setOnClickListener(mOnKeepShowing);
+ done.setOnClickListener(mOnKeepShowing);
minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
+ deliverSilently.setOnClickListener(mOnDeliverSilently);
if (mIsNonblockable) {
- keep.setText(android.R.string.ok);
+ done.setText(android.R.string.ok);
block.setVisibility(GONE);
minimize.setVisibility(GONE);
+ deliverSilently.setVisibility(GONE);
} else if (mIsForeground) {
block.setVisibility(GONE);
minimize.setVisibility(VISIBLE);
@@ -499,7 +498,7 @@
}
// Set up app settings link (i.e. Customize)
- TextView settingsLinkView = findViewById(R.id.app_settings);
+ View settingsLinkView = findViewById(R.id.app_settings);
Intent settingsIntent = getAppSettingsIntent(mPm, mPackageName,
mSingleNotificationChannel,
mSbn.getId(), mSbn.getTag());
@@ -507,7 +506,6 @@
&& settingsIntent != null
&& !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
settingsLinkView.setVisibility(VISIBLE);
- settingsLinkView.setText(mContext.getString(R.string.notification_app_settings));
settingsLinkView.setOnClickListener((View view) -> {
mAppSettingsClickListener.onClick(view, settingsIntent);
});
@@ -531,6 +529,11 @@
case ACTION_UNDO:
mChosenImportance = mStartingChannelImportance;
break;
+ case ACTION_DELIVER_SILENTLY:
+ mExitReason = NotificationCounters.BLOCKING_HELPER_DELIVER_SILENTLY;
+ mChosenImportance = IMPORTANCE_LOW;
+ confirmationText.setText(R.string.notification_channel_silenced);
+ break;
case ACTION_TOGGLE_SILENT:
mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
if (mWasShownHighPriority) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
index 4bdc170..4c9c2f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
@@ -17,12 +17,7 @@
package com.android.systemui.statusbar.notification.row.wrapper;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Color;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
-import android.os.Build;
import android.view.View;
import com.android.internal.graphics.ColorUtils;
@@ -49,43 +44,22 @@
}
@Override
- public void onReinflated() {
- super.onReinflated();
-
- Configuration configuration = mView.getResources().getConfiguration();
- boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES;
-
- float[] hsl = new float[] {0f, 0f, 0f};
- ColorUtils.colorToHSL(mBackgroundColor, hsl);
- boolean backgroundIsDark = Color.alpha(mBackgroundColor) == 0
- || hsl[1] == 0 && hsl[2] < 0.5;
- boolean backgroundHasColor = hsl[1] > 0;
+ public void onContentUpdated(ExpandableNotificationRow row) {
+ super.onContentUpdated(row);
// Let's invert the notification colors when we're in night mode and
// the notification background isn't colorized.
- if (!backgroundIsDark && !backgroundHasColor && nightMode
- && mRow.getEntry().targetSdk < Build.VERSION_CODES.Q) {
- Paint paint = new Paint();
- ColorMatrix matrix = new ColorMatrix();
- ColorMatrix tmp = new ColorMatrix();
- // Inversion should happen on Y'UV space to conseve the colors and
- // only affect the luminosity.
- matrix.setRGB2YUV();
- tmp.set(new float[]{
- -1f, 0f, 0f, 0f, 255f,
- 0f, 1f, 0f, 0f, 0f,
- 0f, 0f, 1f, 0f, 0f,
- 0f, 0f, 0f, 1f, 0f
- });
- matrix.postConcat(tmp);
- tmp.setYUV2RGB();
- matrix.postConcat(tmp);
- paint.setColorFilter(new ColorMatrixColorFilter(matrix));
- mView.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
+ if (needsInversion(mBackgroundColor, mView)) {
+ invertViewLuminosity(mView);
- hsl[2] = 1f - hsl[2];
- mBackgroundColor = ColorUtils.HSLToColor(hsl);
+ // Also invert background color if necessary
+ // (Otherwise we'd end-up with white on white.)
+ float[] hsl = new float[] {0f, 0f, 0f};
+ ColorUtils.colorToHSL(mBackgroundColor, hsl);
+ if (mBackgroundColor != Color.TRANSPARENT && hsl[2] > 0.5) {
+ hsl[2] = 1f - hsl[2];
+ mBackgroundColor = ColorUtils.HSLToColor(hsl);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
new file mode 100644
index 0000000..49a8d56
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+/**
+ * Wraps a notification containing a decorated custom view.
+ */
+public class NotificationDecoratedCustomViewWrapper extends NotificationTemplateViewWrapper {
+
+ private View mWrappedView = null;
+
+ protected NotificationDecoratedCustomViewWrapper(Context ctx, View view,
+ ExpandableNotificationRow row) {
+ super(ctx, view, row);
+ }
+
+ @Override
+ public void onContentUpdated(ExpandableNotificationRow row) {
+ ViewGroup container = mView.findViewById(
+ com.android.internal.R.id.notification_main_column);
+ Integer childIndex = (Integer) container.getTag(
+ com.android.internal.R.id.notification_custom_view_index_tag);
+ if (childIndex != null && childIndex != -1) {
+ mWrappedView = container.getChildAt(childIndex);
+ }
+ if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
+ invertViewLuminosity(mWrappedView);
+ }
+ super.onContentUpdated(row);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 9258c99..4c06ff6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -16,13 +16,22 @@
package com.android.systemui.statusbar.notification.row.wrapper;
+import android.annotation.ColorInt;
+import android.app.Notification;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.view.NotificationHeaderView;
import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import com.android.internal.graphics.ColorUtils;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.TransformState;
@@ -50,6 +59,11 @@
} else if ("messaging".equals(v.getTag())) {
return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
}
+ Class<? extends Notification.Style> style =
+ row.getEntry().notification.getNotification().getNotificationStyle();
+ if (Notification.DecoratedCustomViewStyle.class.equals(style)) {
+ return new NotificationDecoratedCustomViewWrapper(ctx, v, row);
+ }
return new NotificationTemplateViewWrapper(ctx, v, row);
} else if (v instanceof NotificationHeaderView) {
return new NotificationHeaderViewWrapper(ctx, v, row);
@@ -75,14 +89,110 @@
if (shouldClearBackgroundOnReapply()) {
mBackgroundColor = 0;
}
- Drawable background = mView.getBackground();
- if (background instanceof ColorDrawable) {
- int backgroundColor = ((ColorDrawable) background).getColor();
- if (backgroundColor != Color.TRANSPARENT) {
- mBackgroundColor = backgroundColor;
- mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
+ int backgroundColor = getBackgroundColor(mView);
+ if (backgroundColor != Color.TRANSPARENT) {
+ mBackgroundColor = backgroundColor;
+ mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
+ }
+ }
+
+ protected boolean needsInversion(int defaultBackgroundColor, View view) {
+ if (view == null) {
+ return false;
+ }
+
+ Configuration configuration = mView.getResources().getConfiguration();
+ boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+ if (!nightMode) {
+ return false;
+ }
+
+ int background = getBackgroundColor(view);
+ if (background == Color.TRANSPARENT) {
+ background = defaultBackgroundColor;
+ }
+ if (background == Color.TRANSPARENT) {
+ background = resolveBackgroundColor();
+ }
+
+ float[] hsl = new float[] {0f, 0f, 0f};
+ ColorUtils.colorToHSL(background, hsl);
+
+ // Notifications with colored backgrounds should not be inverted
+ if (hsl[1] != 0) {
+ return false;
+ }
+
+ // Invert white or light gray backgrounds.
+ boolean isLightGrayOrWhite = hsl[1] == 0 && hsl[2] > 0.5;
+ if (isLightGrayOrWhite) {
+ return true;
+ }
+
+ // Now let's check if there's unprotected text somewhere, and invert if we find it.
+ if (view instanceof ViewGroup) {
+ return childrenNeedInversion(background, (ViewGroup) view);
+ } else {
+ return false;
+ }
+ }
+
+ private boolean childrenNeedInversion(@ColorInt int parentBackground, ViewGroup viewGroup) {
+ if (viewGroup == null) {
+ return false;
+ }
+
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ View child = viewGroup.getChildAt(i);
+ int backgroundColor = getBackgroundColor(viewGroup);
+ if (backgroundColor == Color.TRANSPARENT) {
+ backgroundColor = parentBackground;
+ }
+ if (child instanceof TextView) {
+ int foreground = ((TextView) child).getCurrentTextColor();
+ if (ColorUtils.calculateContrast(foreground, backgroundColor) < 3) {
+ return true;
+ }
+ } else if (child instanceof ViewGroup) {
+ if (childrenNeedInversion(backgroundColor, (ViewGroup) child)) {
+ return true;
+ }
}
}
+
+ return false;
+ }
+
+ protected int getBackgroundColor(View view) {
+ if (view == null) {
+ return Color.TRANSPARENT;
+ }
+ Drawable background = view.getBackground();
+ if (background instanceof ColorDrawable) {
+ return ((ColorDrawable) background).getColor();
+ }
+ return Color.TRANSPARENT;
+ }
+
+ protected void invertViewLuminosity(View view) {
+ Paint paint = new Paint();
+ ColorMatrix matrix = new ColorMatrix();
+ ColorMatrix tmp = new ColorMatrix();
+ // Inversion should happen on Y'UV space to conserve the colors and
+ // only affect the luminosity.
+ matrix.setRGB2YUV();
+ tmp.set(new float[]{
+ -1f, 0f, 0f, 0f, 255f,
+ 0f, 1f, 0f, 0f, 0f,
+ 0f, 0f, 1f, 0f, 0f,
+ 0f, 0f, 0f, 1f, 0f
+ });
+ matrix.postConcat(tmp);
+ tmp.setYUV2RGB();
+ matrix.postConcat(tmp);
+ paint.setColorFilter(new ColorMatrixColorFilter(matrix));
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
}
protected boolean shouldClearBackgroundOnReapply() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 855cfd9..7105876 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -86,6 +86,8 @@
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
import com.android.systemui.statusbar.EmptyShadeView;
@@ -94,8 +96,7 @@
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -664,8 +665,8 @@
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- Dependency.get(StatusBarStateController.class)
- .addCallback(mStateListener, StatusBarStateController.RANK_STACK_SCROLLER);
+ ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+ .addCallback(mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
Dependency.get(ConfigurationController.class).addCallback(this);
}
@@ -5430,7 +5431,8 @@
mHeadsUpAppearanceController.setPublicMode(publicMode);
}
- StatusBarStateController state = Dependency.get(StatusBarStateController.class);
+ SysuiStatusBarStateController state = (SysuiStatusBarStateController)
+ Dependency.get(StatusBarStateController.class);
setHideSensitive(publicMode, state.goingToFullShade() /* animate */);
setDimmed(onKeyguard, state.fromShadeLocked() /* animate */);
setExpandingEnabled(!onKeyguard);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 35763dc..6410860 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -33,8 +33,8 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
import com.android.systemui.statusbar.policy.EncryptionHelper;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 280dda0..d9d74b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -24,8 +24,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
/**
* Controller which handles all the doze animations of the scrims.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 035ccf1..4c1c0a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -38,9 +38,9 @@
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 1944c3f..5ccb9b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -33,9 +33,9 @@
import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index ee047e4..538d797 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -85,6 +85,7 @@
import com.android.systemui.assist.AssistManager;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -92,7 +93,6 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.ContextualButton.ContextButtonListener;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index d364356..b613e8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -25,12 +25,12 @@
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.AmbientPulseManager.OnAmbientChangedListener;
import com.android.systemui.statusbar.InflationTask;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index bb9e418..cc8af3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -22,11 +22,11 @@
import android.util.Log;
import com.android.systemui.Dependency;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.AmbientPulseManager.OnAmbientChangedListener;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.HeadsUpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 9e99fe9..62f85fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -11,6 +11,9 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+import androidx.collection.ArrayMap;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.ContrastColorUtil;
@@ -19,10 +22,10 @@
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -31,9 +34,6 @@
import java.util.ArrayList;
import java.util.function.Function;
-import androidx.annotation.NonNull;
-import androidx.collection.ArrayMap;
-
/**
* A controller for the space in the status bar to the left of the system icons. This area is
* normally reserved for notifications.
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 a9727c9..069703e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -17,8 +17,7 @@
package com.android.systemui.statusbar.phone;
import static com.android.systemui.SysUiServiceProvider.getComponent;
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
- .ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -63,6 +62,8 @@
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -73,8 +74,6 @@
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index f17145d..4d0c8c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -44,9 +44,10 @@
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -142,8 +143,8 @@
private boolean mIgnoreXTouchSlop;
private boolean mExpandLatencyTracking;
protected final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
- protected final StatusBarStateController mStatusBarStateController =
- Dependency.get(StatusBarStateController.class);
+ protected final SysuiStatusBarStateController mStatusBarStateController =
+ (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
protected void onExpandingFinished() {
mBar.onExpandingFinished();
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 37a0610..9f3bec6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -163,6 +163,7 @@
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.recents.Recents;
@@ -188,7 +189,8 @@
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
@@ -558,8 +560,8 @@
};
private boolean mNoAnimationOnNextBarModeChange;
protected FalsingManager mFalsingManager;
- private final StatusBarStateController
- mStatusBarStateController = Dependency.get(StatusBarStateController.class);
+ private final SysuiStatusBarStateController mStatusBarStateController =
+ (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
private final KeyguardUpdateMonitorCallback mUpdateCallback =
new KeyguardUpdateMonitorCallback() {
@@ -650,7 +652,8 @@
}
mColorExtractor.addOnColorsChangedListener(this);
- mStatusBarStateController.addCallback(this, StatusBarStateController.RANK_STATUS_BAR);
+ mStatusBarStateController.addCallback(this,
+ StatusBarStateControllerImpl.RANK_STATUS_BAR);
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mDreamManager = IDreamManager.Stub.asInterface(
@@ -804,15 +807,17 @@
mNotificationLogger.setUpWithContainer(notifListContainer);
mNotificationIconAreaController = SystemUIFactory.getInstance()
- .createNotificationIconAreaController(
- context, this, mStatusBarStateController, mNotificationListener);
+ .createNotificationIconAreaController(context, this,
+ mStatusBarStateController, mNotificationListener);
inflateShelf();
mNotificationIconAreaController.setupShelf(mNotificationShelf);
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
- // Allow plugins to reference DarkIconDispatcher
+ // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
Dependency.get(PluginDependencyProvider.class)
.allowPluginDependency(DarkIconDispatcher.class);
+ Dependency.get(PluginDependencyProvider.class)
+ .allowPluginDependency(StatusBarStateController.class);
FragmentHostManager.get(mStatusBarWindow)
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
CollapsedStatusBarFragment statusBarFragment =
@@ -3370,7 +3375,8 @@
// ringing.
// Other transitions are covered in handleVisibleToUserChanged().
if (mVisible && (newState == StatusBarState.SHADE_LOCKED
- || (Dependency.get(StatusBarStateController.class).goingToFullShade()))) {
+ || (((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+ .goingToFullShade()))) {
clearNotificationEffects();
}
if (newState == StatusBarState.KEYGUARD) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index bb23608..5014783 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -42,10 +42,11 @@
import com.android.systemui.Dependency;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
@@ -701,7 +702,8 @@
}
public boolean isGoingToNotificationShade() {
- return Dependency.get(StatusBarStateController.class).leaveOpenOnKeyguardHide();
+ return ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+ .leaveOpenOnKeyguardHide();
}
public boolean isSecure(int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 86326be..b0e006d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -51,13 +51,13 @@
import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index df7f53b..e9705ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -48,6 +48,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -56,7 +57,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationAlertingManager;
@@ -92,8 +93,8 @@
Dependency.get(NotificationViewHierarchyManager.class);
private final NotificationLockscreenUserManager mLockscreenUserManager =
Dependency.get(NotificationLockscreenUserManager.class);
- private final StatusBarStateController mStatusBarStateController =
- Dependency.get(StatusBarStateController.class);
+ private final SysuiStatusBarStateController mStatusBarStateController =
+ (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
private final NotificationEntryManager mEntryManager =
Dependency.get(NotificationEntryManager.class);
private final NotificationRowBinder mNotificationRowBinder =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 8d58410..21d9dcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -35,13 +35,14 @@
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager.Callback;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -57,10 +58,10 @@
StatusBarStateController.StateListener {
private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
- private final StatusBarStateController mStatusBarStateController
- = Dependency.get(StatusBarStateController.class);
- private final NotificationLockscreenUserManager mLockscreenUserManager
- = Dependency.get(NotificationLockscreenUserManager.class);
+ private final SysuiStatusBarStateController mStatusBarStateController =
+ (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
+ private final NotificationLockscreenUserManager mLockscreenUserManager =
+ Dependency.get(NotificationLockscreenUserManager.class);
private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
private final Context mContext;
private View mPendingWorkRemoteInputView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 86e17f3..e1a77b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -43,10 +43,11 @@
import com.android.systemui.Dumpable;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.RemoteInputController.Callback;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -98,8 +99,9 @@
mDozeParameters = dozeParameters;
mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
mLpChanged = new WindowManager.LayoutParams();
- Dependency.get(StatusBarStateController.class).addCallback(
- mStateListener, StatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
+ ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+ .addCallback(mStateListener,
+ SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
Dependency.get(ConfigurationController.class).addCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index c39e172..ad4ba75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -59,15 +59,14 @@
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-
public class StatusBarWindowView extends FrameLayout {
public static final String TAG = "StatusBarWindowView";
public static final boolean DEBUG = StatusBar.DEBUG;
diff --git a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
index 52cabe2..6ee341d 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
@@ -34,7 +34,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index d80b444..5d03f19 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -42,8 +42,8 @@
import com.android.keyguard.clock.ClockManager;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import org.junit.Before;
import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index cfc19ef..01d7b8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -44,8 +44,8 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.StatusBarStateController;
import org.junit.Assert;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index e5464e0..86f6cd3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -47,10 +47,10 @@
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import org.junit.Before;
import org.junit.Ignore;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 56e1fc6..62700c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -95,7 +95,7 @@
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
- mock(StatusBarStateController.class), mEntryManager,
+ mock(StatusBarStateControllerImpl.class), mEntryManager,
() -> mShadeController);
Dependency.get(InitController.class).executePostInitTasks();
mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
index ba2aec0..9f36a1e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
@@ -23,12 +23,19 @@
import static android.app.Notification.CATEGORY_EVENT;
import static android.app.Notification.CATEGORY_MESSAGE;
import static android.app.Notification.CATEGORY_REMINDER;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+
+import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_CHANNEL;
+import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_IMPORTANCE;
+import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_VIS_EFFECTS;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -36,6 +43,7 @@
import android.Manifest;
import android.app.Notification;
import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
import android.content.Intent;
@@ -84,8 +92,6 @@
private static final int UID_NORMAL = 123;
private static final int UID_ALLOW_DURING_SETUP = 456;
- private static final String TEST_HIDDEN_NOTIFICATION_KEY = "testHiddenNotificationKey";
- private static final String TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY = "exempt";
private static final NotificationChannel NOTIFICATION_CHANNEL =
new NotificationChannel("id", "name", NotificationChannel.USER_LOCKED_IMPORTANCE);
@@ -97,7 +103,7 @@
NotificationData.KeyguardEnvironment mEnvironment;
private final IPackageManager mMockPackageManager = mock(IPackageManager.class);
- private NotificationData mNotificationData;
+ private TestableNotificationData mNotificationData;
private ExpandableNotificationRow mRow;
@Before
@@ -131,6 +137,7 @@
@Test
public void testChannelSetWhenAdded() {
+ mNotificationData.rankingOverrides.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL);
mNotificationData.add(mRow.getEntry());
assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().channel);
}
@@ -217,12 +224,12 @@
@Test
public void testIsExemptFromDndVisualSuppression_foreground() {
initStatusBarNotification(false);
- when(mMockStatusBarNotification.getKey()).thenReturn(
- TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
+
Notification n = mMockStatusBarNotification.getNotification();
n.flags = Notification.FLAG_FOREGROUND_SERVICE;
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
mNotificationData.add(entry);
+ mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
assertTrue(entry.isExemptFromDndVisualSuppression());
assertFalse(entry.shouldSuppressAmbient());
@@ -231,8 +238,6 @@
@Test
public void testIsExemptFromDndVisualSuppression_media() {
initStatusBarNotification(false);
- when(mMockStatusBarNotification.getKey()).thenReturn(
- TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
Notification n = mMockStatusBarNotification.getNotification();
Notification.Builder nb = Notification.Builder.recoverBuilder(mContext, n);
nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
@@ -240,6 +245,7 @@
when(mMockStatusBarNotification.getNotification()).thenReturn(n);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
mNotificationData.add(entry);
+ mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
assertTrue(entry.isExemptFromDndVisualSuppression());
assertFalse(entry.shouldSuppressAmbient());
@@ -248,11 +254,10 @@
@Test
public void testIsExemptFromDndVisualSuppression_system() {
initStatusBarNotification(false);
- when(mMockStatusBarNotification.getKey()).thenReturn(
- TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
entry.mIsSystemNotification = true;
mNotificationData.add(entry);
+ mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
assertTrue(entry.isExemptFromDndVisualSuppression());
assertFalse(entry.shouldSuppressAmbient());
@@ -261,10 +266,10 @@
@Test
public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
initStatusBarNotification(false);
- when(mMockStatusBarNotification.getKey()).thenReturn(
- TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
entry.mIsSystemNotification = true;
+ mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS,
+ NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
mNotificationData.add(entry);
when(mMockStatusBarNotification.getNotification()).thenReturn(
@@ -353,6 +358,64 @@
assertTrue(entry.isLastMessageFromReply());
}
+ @Test
+ public void personHighPriority() {
+ Person person = new Person.Builder()
+ .setName("name")
+ .setKey("abc")
+ .setUri("uri")
+ .setBot(true)
+ .build();
+
+ Notification notification = new Notification.Builder(mContext, "test")
+ .addPerson(person)
+ .build();
+
+ StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+ notification, mContext.getUser(), "", 0);
+
+ assertTrue(mNotificationData.isHighPriority(sbn));
+ }
+
+ @Test
+ public void messagingStyleHighPriority() {
+
+ Notification notification = new Notification.Builder(mContext, "test")
+ .setStyle(new Notification.MessagingStyle(""))
+ .build();
+
+ StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+ notification, mContext.getUser(), "", 0);
+
+ assertTrue(mNotificationData.isHighPriority(sbn));
+ }
+
+ @Test
+ public void minForegroundNotHighPriority() {
+ Notification notification = mock(Notification.class);
+ when(notification.isForegroundService()).thenReturn(true);
+
+ mNotificationData.rankingOverrides.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_MIN);
+
+ StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+ notification, mContext.getUser(), "", 0);
+
+ assertFalse(mNotificationData.isHighPriority(sbn));
+ }
+
+ @Test
+ public void lowForegroundHighPriority() {
+ Notification notification = mock(Notification.class);
+ when(notification.isForegroundService()).thenReturn(true);
+
+ mNotificationData.rankingOverrides.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
+
+ StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+ notification, mContext.getUser(), "", 0);
+
+ assertTrue(mNotificationData.isHighPriority(sbn));
+ }
+
private void initStatusBarNotification(boolean allowDuringSetup) {
Bundle bundle = new Bundle();
bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
@@ -362,39 +425,90 @@
when(mMockStatusBarNotification.getNotification()).thenReturn(notification);
}
- private class TestableNotificationData extends NotificationData {
+ public static class TestableNotificationData extends NotificationData {
public TestableNotificationData() {
super();
}
+ public static final String OVERRIDE_RANK = "r";
+ public static final String OVERRIDE_DND = "dnd";
+ public static final String OVERRIDE_VIS_OVERRIDE = "vo";
+ public static final String OVERRIDE_VIS_EFFECTS = "ve";
+ public static final String OVERRIDE_IMPORTANCE = "i";
+ public static final String OVERRIDE_IMP_EXP = "ie";
+ public static final String OVERRIDE_GROUP = "g";
+ public static final String OVERRIDE_CHANNEL = "c";
+ public static final String OVERRIDE_PEOPLE = "p";
+ public static final String OVERRIDE_SNOOZE_CRITERIA = "sc";
+ public static final String OVERRIDE_BADGE = "b";
+ public static final String OVERRIDE_USER_SENTIMENT = "us";
+ public static final String OVERRIDE_HIDDEN = "h";
+ public static final String OVERRIDE_LAST_ALERTED = "la";
+ public static final String OVERRIDE_NOISY = "n";
+ public static final String OVERRIDE_SMART_ACTIONS = "sa";
+ public static final String OVERRIDE_SMART_REPLIES = "sr";
+ public static final String OVERRIDE_BUBBLE = "cb";
+
+ public Bundle rankingOverrides = new Bundle();
+
@Override
protected boolean getRanking(String key, Ranking outRanking) {
super.getRanking(key, outRanking);
- if (key.equals(TEST_HIDDEN_NOTIFICATION_KEY)) {
- outRanking.populate(key, outRanking.getRank(),
- outRanking.matchesInterruptionFilter(),
- outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
- outRanking.getImportance(), outRanking.getImportanceExplanation(),
- outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
- outRanking.canShowBadge(), outRanking.getUserSentiment(), true,
- -1, false, null, null, outRanking.canBubble());
- } else if (key.equals(TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY)) {
- outRanking.populate(key, outRanking.getRank(),
- outRanking.matchesInterruptionFilter(),
- outRanking.getVisibilityOverride(), 255,
- outRanking.getImportance(), outRanking.getImportanceExplanation(),
- outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
- outRanking.canShowBadge(), outRanking.getUserSentiment(), true, -1,
- false, null, null, outRanking.canBubble());
- } else {
- outRanking.populate(key, outRanking.getRank(),
- outRanking.matchesInterruptionFilter(),
- outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
- outRanking.getImportance(), outRanking.getImportanceExplanation(),
- outRanking.getOverrideGroupKey(), NOTIFICATION_CHANNEL, null, null,
- outRanking.canShowBadge(), outRanking.getUserSentiment(), false, -1,
- false, null, null, outRanking.canBubble());
+
+ ArrayList<String> currentAdditionalPeople = new ArrayList<>();
+ if (outRanking.getAdditionalPeople() != null) {
+ currentAdditionalPeople.addAll(outRanking.getAdditionalPeople());
}
+
+ ArrayList<SnoozeCriterion> currentSnooze = new ArrayList<>();
+ if (outRanking.getSnoozeCriteria() != null) {
+ currentSnooze.addAll(outRanking.getSnoozeCriteria());
+ }
+
+ ArrayList<Notification.Action> currentActions = new ArrayList<>();
+ if (outRanking.getSmartActions() != null) {
+ currentActions.addAll(outRanking.getSmartActions());
+ }
+
+ ArrayList<CharSequence> currentReplies = new ArrayList<>();
+ if (outRanking.getSmartReplies() != null) {
+ currentReplies.addAll(outRanking.getSmartReplies());
+ }
+
+ outRanking.populate(key,
+ rankingOverrides.getInt(OVERRIDE_RANK, outRanking.getRank()),
+ rankingOverrides.getBoolean(OVERRIDE_DND,
+ outRanking.matchesInterruptionFilter()),
+ rankingOverrides.getInt(OVERRIDE_VIS_OVERRIDE,
+ outRanking.getVisibilityOverride()),
+ rankingOverrides.getInt(OVERRIDE_VIS_EFFECTS,
+ outRanking.getSuppressedVisualEffects()),
+ rankingOverrides.getInt(OVERRIDE_IMPORTANCE, outRanking.getImportance()),
+ rankingOverrides.getCharSequence(OVERRIDE_IMP_EXP,
+ outRanking.getImportanceExplanation()),
+ rankingOverrides.getString(OVERRIDE_GROUP, outRanking.getOverrideGroupKey()),
+ rankingOverrides.containsKey(OVERRIDE_CHANNEL)
+ ? (NotificationChannel) rankingOverrides.getParcelable(OVERRIDE_CHANNEL)
+ : outRanking.getChannel(),
+ rankingOverrides.containsKey(OVERRIDE_PEOPLE)
+ ? rankingOverrides.getStringArrayList(OVERRIDE_PEOPLE)
+ : currentAdditionalPeople,
+ rankingOverrides.containsKey(OVERRIDE_SNOOZE_CRITERIA)
+ ? rankingOverrides.getParcelableArrayList(OVERRIDE_SNOOZE_CRITERIA)
+ : currentSnooze,
+ rankingOverrides.getBoolean(OVERRIDE_BADGE, outRanking.canShowBadge()),
+ rankingOverrides.getInt(OVERRIDE_USER_SENTIMENT, outRanking.getUserSentiment()),
+ rankingOverrides.getBoolean(OVERRIDE_HIDDEN, outRanking.isSuspended()),
+ rankingOverrides.getLong(OVERRIDE_LAST_ALERTED,
+ outRanking.getLastAudiblyAlertedMillis()),
+ rankingOverrides.getBoolean(OVERRIDE_NOISY, outRanking.isNoisy()),
+ rankingOverrides.containsKey(OVERRIDE_SMART_ACTIONS)
+ ? rankingOverrides.getParcelableArrayList(OVERRIDE_SMART_ACTIONS)
+ : currentActions,
+ rankingOverrides.containsKey(OVERRIDE_SMART_REPLIES)
+ ? rankingOverrides.getCharSequenceArrayList(OVERRIDE_SMART_REPLIES)
+ : currentReplies,
+ rankingOverrides.getBoolean(OVERRIDE_BUBBLE, outRanking.canBubble()));
return true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index db2706b..d47700b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -40,7 +40,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -99,7 +99,7 @@
mEntry.setRow(mRow);
mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class),
- mEntryManager, mock(StatusBarStateController.class), mBarService,
+ mEntryManager, mock(StatusBarStateControllerImpl.class), mBarService,
mExpansionStateLogger);
mLogger.setUpWithContainer(mListContainer);
verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
@@ -167,7 +167,7 @@
TestableNotificationLogger(NotificationListener notificationListener,
UiOffloadThread uiOffloadThread,
NotificationEntryManager entryManager,
- StatusBarStateController statusBarStateController,
+ StatusBarStateControllerImpl statusBarStateController,
IStatusBarService barService,
ExpansionStateLogger expansionStateLogger) {
super(notificationListener, uiOffloadThread, entryManager, statusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 105bd9d..19a73f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -737,7 +737,7 @@
guts.setGutsContent(mNotificationInfo);
mNotificationInfo.setGutsParent(guts);
- mNotificationInfo.findViewById(R.id.keep).performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
mTestableLooper.processAllMessages();
@@ -765,7 +765,7 @@
guts.setGutsContent(mNotificationInfo);
mNotificationInfo.setGutsParent(guts);
- mNotificationInfo.findViewById(R.id.keep).performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
mTestableLooper.processAllMessages();
@@ -961,6 +961,41 @@
}
@Test
+ public void testSilentlyChangedCallsUpdateNotificationChannel_blockingHelper()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(
+ mMockPackageManager,
+ mMockINotificationManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ 1 /* numChannels */,
+ mSbn,
+ null /* checkSaveListener */,
+ null /* onSettingsClick */,
+ null /* onAppSettingsClick */,
+ true /*provisioned */,
+ false /* isNonblockable */,
+ true /* isForBlockingHelper */,
+ true /* isUserSentimentNegative */,
+ IMPORTANCE_DEFAULT,
+ false);
+
+ mNotificationInfo.findViewById(R.id.deliver_silently).performClick();
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+ }
+
+ @Test
public void testKeepUpdatesNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index ae70b01..d835082 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -51,13 +51,13 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index a72be7a..3c5425c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -32,8 +32,8 @@
import com.android.systemui.R;
import com.android.systemui.SysuiBaseFragmentTest;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.tuner.TunerService;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
index 13145b8..608dd8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -20,23 +20,15 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import android.content.Context;
import android.provider.Settings;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.phone.LightBarTransitionsController.DarkIntensityApplier;
import org.junit.Before;
import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 3b98f0c..a97fa1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -27,8 +27,9 @@
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -46,7 +47,7 @@
public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
- private StatusBarStateController mStatusBarStateController;
+ private SysuiStatusBarStateController mStatusBarStateController;
@Mock
private NotificationStackScrollLayout mNotificationStackScrollLayout;
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 036e57acb..a95361f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -82,6 +82,7 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NavigationBarController;
@@ -94,7 +95,7 @@
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -153,7 +154,7 @@
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private RemoteInputController mRemoteInputController;
- @Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private StatusBarStateControllerImpl mStatusBarStateController;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private NotificationPresenter mNotificationPresenter;
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index 46335dc..11284d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -28,9 +28,9 @@
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import org.junit.Before;
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 2b45b49..82359c5 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -515,6 +515,9 @@
// Total number of scan results for WPA3-Enterprise networks
optional int32 num_wpa3_enterprise_network_scan_results = 136;
+
+ // WifiConfigStore read/write metrics.
+ optional WifiConfigStoreIO wifi_config_store_io = 137;
}
// Information that gets logged for every WiFi connection.
@@ -668,6 +671,9 @@
// Has bug report been taken.
optional bool automatic_bug_report_taken = 9;
+
+ // Connection is using locally generated random MAC address.
+ optional bool use_randomized_mac = 10 [default = false];
}
// Number of occurrences of a specific RSSI poll rssi value
@@ -1874,6 +1880,13 @@
// Rx link speed at the sample time in Mbps
optional int32 rx_link_speed_mbps = 27;
+
+ // Sequence number generated by framework
+ optional int32 seq_num_inside_framework = 28;
+
+ // Whether current entry is for the same BSSID on the same frequency compared
+ // to last entry
+ optional bool is_same_bssid_and_freq = 29;
}
message WifiUsabilityStats {
@@ -2170,3 +2183,25 @@
EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = 9;
}
}
+
+// WifiConfigStore read/write metrics.
+message WifiConfigStoreIO {
+ // Histogram of config store read durations.
+ repeated DurationBucket read_durations = 1;
+
+ // Histogram of config store write durations.
+ repeated DurationBucket write_durations = 2;
+
+ // Total Number of instances of write/read duration in this duration bucket.
+ message DurationBucket {
+ // Bucket covers duration : [range_start_ms, range_end_ms)
+ // The (inclusive) lower bound of read/write duration represented by this bucket
+ optional int32 range_start_ms = 1;
+
+ // The (exclusive) upper bound of read/write duration represented by this bucket
+ optional int32 range_end_ms = 2;
+
+ // Number of read/write durations that fit into this bucket
+ optional int32 count = 3;
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 2e45fa7..4a3f126 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -49,6 +49,7 @@
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.autofill.FillEventHistory;
import android.service.autofill.UserData;
@@ -167,10 +168,14 @@
mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
mAm = LocalServices.getService(ActivityManagerInternal.class);
+ DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_AUTOFILL,
+ ActivityThread.currentApplication().getMainExecutor(),
+ (namespace, name, value) -> setSmartSuggestionModesFromDeviceConfig(value));
+
setLogLevelFromSettings();
setMaxPartitionsFromSettings();
setMaxVisibleDatasetsFromSettings();
- setSmartSuggestionEmulationFromSettings();
+ setSmartSuggestionModesFromDeviceConfig();
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
@@ -197,9 +202,6 @@
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS), false, observer,
UserHandle.USER_ALL);
- resolver.registerContentObserver(Settings.Global.getUriFor(
- Settings.Global.AUTOFILL_SMART_SUGGESTION_EMULATION_FLAGS), false, observer,
- UserHandle.USER_ALL);
}
@Override // from AbstractMasterSystemService
@@ -214,9 +216,6 @@
case Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS:
setMaxVisibleDatasetsFromSettings();
break;
- case Settings.Global.AUTOFILL_SMART_SUGGESTION_EMULATION_FLAGS:
- setSmartSuggestionEmulationFromSettings();
- break;
default:
Slog.w(TAG, "Unexpected property (" + property + "); updating cache instead");
// fall through
@@ -457,14 +456,25 @@
}
}
- private void setSmartSuggestionEmulationFromSettings() {
- final int flags = Settings.Global.getInt(getContext().getContentResolver(),
- Settings.Global.AUTOFILL_SMART_SUGGESTION_EMULATION_FLAGS, 0);
- if (sDebug) {
- Slog.d(TAG, "setSmartSuggestionEmulationFromSettings(): "
- + getSmartSuggestionModeToString(flags));
- }
+ private void setSmartSuggestionModesFromDeviceConfig() {
+ final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_AUTOFILL,
+ AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES);
+ setSmartSuggestionModesFromDeviceConfig(value);
+ }
+ private void setSmartSuggestionModesFromDeviceConfig(@Nullable String value) {
+ if (sDebug) Slog.d(TAG, "setSmartSuggestionEmulationFromDeviceConfig(): value=" + value);
+ final int flags;
+ if (value == null) {
+ flags = AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM;
+ } else {
+ try {
+ flags = Integer.parseInt(value);
+ } catch (Exception e) {
+ Slog.w(TAG, "setSmartSuggestionEmulationFromDeviceConfig(): NAN:" + value);
+ return;
+ }
+ }
synchronized (mLock) {
mSupportedSmartSuggestionModes = flags;
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 9249c9c..4afbc64 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
+import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -39,6 +40,7 @@
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.LocalLog;
import android.util.Slog;
@@ -89,19 +91,38 @@
@Nullable
private SparseBooleanArray mDisabledUsers;
+ /**
+ * Global kill-switch based on value defined by
+ * {@link ContentCaptureManager#DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED}.
+ */
+ @GuardedBy("mLock")
+ @Nullable
+ private boolean mDisabledByDeviceConfig;
public ContentCaptureManagerService(@NonNull Context context) {
super(context, new FrameworkResourcesServiceNameResolver(context,
com.android.internal.R.string.config_defaultContentCaptureService),
UserManager.DISALLOW_CONTENT_CAPTURE);
- // Sets which serviecs are disabled
+ DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ ActivityThread.currentApplication().getMainExecutor(),
+ (namespace, key, value) -> {
+ if (!ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED
+ .equals(key)) {
+ Slog.i(mTag, "Ignoring change on " + key);
+ return;
+ }
+ setDisabledByDeviceConfig(value);
+ });
+ setDisabledByDeviceConfig();
+
+ // Sets which services are disabled
final UserManager um = getContext().getSystemService(UserManager.class);
final List<UserInfo> users = um.getUsers();
for (int i = 0; i < users.size(); i++) {
final int userId = users.get(i).id;
- final boolean disabled = isDisabledBySettings(userId);
+ final boolean disabled = mDisabledByDeviceConfig || isDisabledBySettings(userId);
if (disabled) {
- Slog.i(mTag, "user " + userId + " disabled by settings");
+ Slog.i(mTag, "user " + userId + " disabled by settings or device config");
if (mDisabledUsers == null) {
mDisabledUsers = new SparseBooleanArray(1);
}
@@ -160,7 +181,8 @@
@Override // from AbstractMasterSystemService
protected boolean isDisabledLocked(@UserIdInt int userId) {
- return isDisabledBySettingsLocked(userId) || super.isDisabledLocked(userId);
+ return mDisabledByDeviceConfig || isDisabledBySettingsLocked(userId)
+ || super.isDisabledLocked(userId);
}
private boolean isDisabledBySettingsLocked(@UserIdInt int userId) {
@@ -191,6 +213,45 @@
return false;
}
+ private void setDisabledByDeviceConfig() {
+ final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
+ setDisabledByDeviceConfig(value);
+ }
+
+ private void setDisabledByDeviceConfig(@Nullable String value) {
+ if (verbose) Slog.v(mTag, "setDisabledByDeviceConfig(): value=" + value);
+ final UserManager um = getContext().getSystemService(UserManager.class);
+ final List<UserInfo> users = um.getUsers();
+
+ final boolean newDisabledValue;
+
+ if (value != null && value.equalsIgnoreCase("false")) {
+ newDisabledValue = true;
+ } else {
+ newDisabledValue = false;
+ }
+
+ synchronized (mLock) {
+ if (mDisabledByDeviceConfig == newDisabledValue) {
+ if (verbose) {
+ Slog.v(mTag, "setDisabledByDeviceConfig(): already " + newDisabledValue);
+ }
+ return;
+ }
+ mDisabledByDeviceConfig = newDisabledValue;
+
+ Slog.i(mTag, "setDisabledByDeviceConfig(): set to " + mDisabledByDeviceConfig);
+ for (int i = 0; i < users.size(); i++) {
+ final int userId = users.get(i).id;
+ boolean disabled = mDisabledByDeviceConfig || isDisabledBySettingsLocked(userId);
+ Slog.i(mTag, "setDisabledByDeviceConfig(): updating service for user "
+ + userId + " to " + (disabled ? "'disabled'" : "'enabled'"));
+ updateCachedServiceLocked(userId, disabled);
+ }
+ }
+ }
+
private void setContentCaptureFeatureEnabledForUser(@UserIdInt int userId, boolean enabled) {
synchronized (mLock) {
if (mDisabledUsers == null) {
@@ -338,6 +399,8 @@
super.dumpLocked(prefix, pw);
pw.print(prefix); pw.print("Disabled users: "); pw.println(mDisabledUsers);
+ pw.print(prefix); pw.print("Disabled by DeviceConfig: ");
+ pw.println(mDisabledByDeviceConfig);
}
final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
@@ -406,7 +469,7 @@
"isContentCaptureFeatureEnabled()", userId, Binder.getCallingUid(), result);
if (!isService) return;
- enabled = !isDisabledBySettingsLocked(userId);
+ enabled = !mDisabledByDeviceConfig && !isDisabledBySettingsLocked(userId);
}
try {
result.send(enabled ? ContentCaptureManager.RESULT_CODE_TRUE
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
index 39d5c9d..86ad52d 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
@@ -77,15 +77,12 @@
pw.println(" Temporarily (for DURATION ms) changes the service implemtation.");
pw.println(" To reset, call with just the USER_ID argument.");
pw.println("");
- pw.println("");
pw.println(" set default-service-enabled USER_ID [true|false]");
pw.println(" Enable / disable the default service for the user.");
pw.println("");
- pw.println("");
pw.println(" get default-service-enabled USER_ID");
pw.println(" Checks whether the default service is enabled for the user.");
pw.println("");
- pw.println("");
pw.println(" list sessions [--user USER_ID]");
pw.println(" Lists all pending sessions.");
pw.println("");
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index eafa0e2..e510259 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -121,6 +121,8 @@
private static final String SETTINGS_DETAILED_TRACKING_KEY = "detailed_tracking";
private static final String SETTINGS_UPLOAD_DATA_KEY = "upload_data";
private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
+ private static final String SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY = "track_screen_state";
+ private static final String SETTINGS_TRACK_DIRECT_CALLING_UID_KEY = "track_calling_uid";
private static final String SETTINGS_MAX_CALL_STATS_KEY = "max_call_stats_count";
private boolean mEnabled;
@@ -169,6 +171,12 @@
mBinderCallsStats.setMaxBinderCallStats(mParser.getInt(
SETTINGS_MAX_CALL_STATS_KEY,
BinderCallsStats.MAX_BINDER_CALL_STATS_COUNT_DEFAULT));
+ mBinderCallsStats.setTrackScreenInteractive(
+ mParser.getBoolean(SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY,
+ BinderCallsStats.DEFAULT_TRACK_SCREEN_INTERACTIVE));
+ mBinderCallsStats.setTrackDirectCallerUid(
+ mParser.getBoolean(SETTINGS_TRACK_DIRECT_CALLING_UID_KEY,
+ BinderCallsStats.DEFAULT_TRACK_DIRECT_CALLING_UID));
final boolean enabled =
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
index 9184128..c334540 100644
--- a/services/core/java/com/android/server/LooperStatsService.java
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -51,16 +51,19 @@
private static final String LOOPER_STATS_SERVICE_NAME = "looper_stats";
private static final String SETTINGS_ENABLED_KEY = "enabled";
private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
+ private static final String SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY = "track_screen_state";
private static final String DEBUG_SYS_LOOPER_STATS_ENABLED =
"debug.sys.looper_stats_enabled";
private static final int DEFAULT_SAMPLING_INTERVAL = 100;
private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
private static final boolean DEFAULT_ENABLED = true;
+ private static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false;
private final Context mContext;
private final LooperStats mStats;
// Default should be false so that the first call to #setEnabled installed the looper observer.
private boolean mEnabled = false;
+ private boolean mTrackScreenInteractive = false;
private LooperStatsService(Context context, LooperStats stats) {
this.mContext = context;
@@ -79,6 +82,9 @@
setSamplingInterval(
parser.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL));
+ setTrackScreenInteractive(
+ parser.getBoolean(SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY,
+ DEFAULT_TRACK_SCREEN_INTERACTIVE));
// Manually specified value takes precedence over Settings.
setEnabled(SystemProperties.getBoolean(
DEBUG_SYS_LOOPER_STATS_ENABLED,
@@ -155,6 +161,13 @@
}
}
+ private void setTrackScreenInteractive(boolean enabled) {
+ if (mTrackScreenInteractive != enabled) {
+ mTrackScreenInteractive = enabled;
+ mStats.reset();
+ }
+ }
+
private void setSamplingInterval(int samplingInterval) {
if (samplingInterval > 0) {
mStats.setSamplingInterval(samplingInterval);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index f2329d3..e7d7434 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4013,7 +4013,7 @@
return;
}
userPackages.add(packageName);
- sandboxId = getSandboxId(packageName, sharedUserId);
+ sandboxId = StorageManagerService.this.getSandboxId(packageName, sharedUserId);
}
try {
@@ -4028,7 +4028,8 @@
if (!ENABLE_ISOLATED_STORAGE) {
return;
}
- final String sandboxId = getSandboxId(packageName, sharedUserId);
+ final String sandboxId = StorageManagerService.this.getSandboxId(
+ packageName, sharedUserId);
synchronized (mPackagesLock) {
final ArraySet<String> userPackages = mPackages.get(userId);
// If the userPackages is null, it means the user is not started but we still
@@ -4056,6 +4057,12 @@
return visibleVolsForUser.toArray(new String[visibleVolsForUser.size()]);
}
+ @Override
+ public String getSandboxId(String packageName) {
+ return StorageManagerService.this.getSandboxId(packageName,
+ mPmInternal.getSharedUserIdForPackage(packageName));
+ }
+
private String getVolumeLabel(VolumeInfo vol) {
// STOPSHIP: Label needs to part of VolumeInfo and need to be passed on from vold
switch (vol.getType()) {
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index c7b9a3c..8ccb6e2 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -82,6 +82,9 @@
private static final String ADB_DIRECTORY = "misc/adb";
// This file contains keys that will always be allowed to connect to the device via adb.
private static final String ADB_KEYS_FILE = "adb_keys";
+ // This file contains keys that will be allowed to connect without user interaction as long
+ // as a subsequent connection occurs within the allowed duration.
+ private static final String ADB_TEMP_KEYS_FILE = "adb_temp_keys.xml";
private static final int BUFFER_SIZE = 4096;
private final Context mContext;
@@ -263,7 +266,6 @@
AdbDebuggingHandler(Looper looper) {
super(looper);
- mAdbKeyStore = new AdbKeyStore();
}
/**
@@ -289,6 +291,7 @@
mThread = new AdbDebuggingThread();
mThread.start();
+ mAdbKeyStore = new AdbKeyStore();
break;
case MESSAGE_ADB_DISABLED:
@@ -303,6 +306,9 @@
mThread = null;
}
+ cancelJobToUpdateAdbKeyStore();
+ mAdbKeyStore = null;
+ mConnectedKey = null;
break;
case MESSAGE_ADB_ALLOW: {
@@ -322,6 +328,9 @@
mConnectedKey = key;
mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
scheduleJobToUpdateAdbKeyStore();
+ // write this key to adb_keys as well so that subsequent connections can
+ // go through the expected SIGNATURE interaction.
+ writeKey(key);
}
logAdbConnectionChanged(key, AdbProtoEnums.USER_ALLOWED, alwaysAllow);
}
@@ -354,20 +363,9 @@
}
break;
}
- // Check if the key should be allowed without user interaction.
- if (mAdbKeyStore.isKeyAuthorized(key)) {
- if (mThread != null) {
- mThread.sendResponse("OK");
- mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
- logAdbConnectionChanged(key, AdbProtoEnums.AUTOMATICALLY_ALLOWED, true);
- mConnectedKey = key;
- scheduleJobToUpdateAdbKeyStore();
- }
- } else {
- logAdbConnectionChanged(key, AdbProtoEnums.AWAITING_USER_APPROVAL, false);
- mFingerprints = fingerprints;
- startConfirmation(key, mFingerprints);
- }
+ logAdbConnectionChanged(key, AdbProtoEnums.AWAITING_USER_APPROVAL, false);
+ mFingerprints = fingerprints;
+ startConfirmation(key, mFingerprints);
break;
}
@@ -532,7 +530,11 @@
return new File(adbDir, fileName);
}
- private File getUserKeyFile() {
+ File getAdbTempKeysFile() {
+ return getAdbFile(ADB_TEMP_KEYS_FILE);
+ }
+
+ File getUserKeyFile() {
return getAdbFile(ADB_KEYS_FILE);
}
@@ -668,9 +670,6 @@
private Map<String, Long> mKeyMap;
private File mKeyFile;
private AtomicFile mAtomicKeyFile;
- // This file contains keys that will be allowed to connect without user interaction as long
- // as a subsequent connection occurs within the allowed duration.
- private static final String ADB_TEMP_KEYS_FILE = "adb_temp_keys.xml";
private static final String XML_TAG_ADB_KEY = "adbKey";
private static final String XML_ATTRIBUTE_KEY = "key";
private static final String XML_ATTRIBUTE_LAST_CONNECTION = "lastConnection";
@@ -704,9 +703,9 @@
*/
private void initKeyFile() {
if (mKeyFile == null) {
- mKeyFile = getAdbFile(ADB_TEMP_KEYS_FILE);
+ mKeyFile = getAdbTempKeysFile();
}
- // getAdbFile can return null if the adb file cannot be obtained
+ // getAdbTempKeysFile can return null if the adb file cannot be obtained
if (mKeyFile != null) {
mAtomicKeyFile = new AtomicFile(mKeyFile);
}
@@ -767,7 +766,8 @@
public void persistKeyStore() {
// if there is nothing in the key map then ensure any keys left in the key store files
// are deleted as well.
- if (mKeyMap.size() == 0) {
+ filterOutOldKeys();
+ if (mKeyMap.isEmpty()) {
deleteKeyStore();
return;
}
@@ -784,22 +784,15 @@
keyStream = mAtomicKeyFile.startWrite();
serializer.setOutput(keyStream, StandardCharsets.UTF_8.name());
serializer.startDocument(null, true);
- long allowedTime = getAllowedConnectionTime();
- long systemTime = System.currentTimeMillis();
- Iterator keyMapIterator = mKeyMap.entrySet().iterator();
- while (keyMapIterator.hasNext()) {
- Map.Entry<String, Long> keyEntry = (Map.Entry) keyMapIterator.next();
- long connectionTime = keyEntry.getValue();
- if (systemTime < (connectionTime + allowedTime)) {
- serializer.startTag(null, XML_TAG_ADB_KEY);
- serializer.attribute(null, XML_ATTRIBUTE_KEY, keyEntry.getKey());
- serializer.attribute(null, XML_ATTRIBUTE_LAST_CONNECTION,
- String.valueOf(keyEntry.getValue()));
- serializer.endTag(null, XML_TAG_ADB_KEY);
- } else {
- keyMapIterator.remove();
- }
+
+ for (Map.Entry<String, Long> keyEntry : mKeyMap.entrySet()) {
+ serializer.startTag(null, XML_TAG_ADB_KEY);
+ serializer.attribute(null, XML_ATTRIBUTE_KEY, keyEntry.getKey());
+ serializer.attribute(null, XML_ATTRIBUTE_LAST_CONNECTION,
+ String.valueOf(keyEntry.getValue()));
+ serializer.endTag(null, XML_TAG_ADB_KEY);
}
+
serializer.endDocument();
mAtomicKeyFile.finishWrite(keyStream);
} catch (IOException e) {
@@ -808,6 +801,19 @@
}
}
+ private void filterOutOldKeys() {
+ long allowedTime = getAllowedConnectionTime();
+ long systemTime = System.currentTimeMillis();
+ Iterator<Map.Entry<String, Long>> keyMapIterator = mKeyMap.entrySet().iterator();
+ while (keyMapIterator.hasNext()) {
+ Map.Entry<String, Long> keyEntry = keyMapIterator.next();
+ long connectionTime = keyEntry.getValue();
+ if (allowedTime != 0 && systemTime > (connectionTime + allowedTime)) {
+ keyMapIterator.remove();
+ }
+ }
+ }
+
/**
* Removes all of the entries in the key map and deletes the key file.
*/
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index c316915..7fd98e0 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -45,6 +45,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
@@ -95,6 +96,16 @@
public boolean isAdbEnabled() {
return mAdbEnabled;
}
+
+ @Override
+ public File getAdbKeysFile() {
+ return mDebuggingManager.getUserKeyFile();
+ }
+
+ @Override
+ public File getAdbTempKeysFile() {
+ return mDebuggingManager.getAdbTempKeysFile();
+ }
}
private final class AdbHandler extends Handler {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5932f99..60a45bf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2226,7 +2226,7 @@
mConstants = hasHandlerThread ? new ActivityManagerConstants(this, mHandler) : null;
final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */);
mProcessList.init(this, activeUids);
- mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, new Object());
+ mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
mIntentFirewall = hasHandlerThread
? new IntentFirewall(new IntentFirewallInterface(), mHandler) : null;
@@ -2274,7 +2274,7 @@
mConstants = new ActivityManagerConstants(this, mHandler);
final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */);
mProcessList.init(this, activeUids);
- mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, atm.getGlobalLock());
+ mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
// Broadcast policy parameters
final BroadcastConstants foreConstants = new BroadcastConstants(
@@ -6549,7 +6549,7 @@
conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
stable);
if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
- if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
+ if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
// If this is a perceptible app accessing the provider,
// make sure to count it as being accessed and thus
// back up on the LRU list. This is good because
@@ -10828,6 +10828,7 @@
printOomLevel(pw, "FOREGROUND_APP_ADJ", ProcessList.FOREGROUND_APP_ADJ);
printOomLevel(pw, "VISIBLE_APP_ADJ", ProcessList.VISIBLE_APP_ADJ);
printOomLevel(pw, "PERCEPTIBLE_APP_ADJ", ProcessList.PERCEPTIBLE_APP_ADJ);
+ printOomLevel(pw, "PERCEPTIBLE_LOW_APP_ADJ", ProcessList.PERCEPTIBLE_LOW_APP_ADJ);
printOomLevel(pw, "BACKUP_APP_ADJ", ProcessList.BACKUP_APP_ADJ);
printOomLevel(pw, "HEAVY_WEIGHT_APP_ADJ", ProcessList.HEAVY_WEIGHT_APP_ADJ);
printOomLevel(pw, "SERVICE_ADJ", ProcessList.SERVICE_ADJ);
@@ -10878,16 +10879,17 @@
pw.println(" Total number of kills: " + cnt);
return reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MAX_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MIN_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_B_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.PREVIOUS_APP_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.HOME_APP_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.HEAVY_WEIGHT_APP_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.BACKUP_APP_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.PERCEPTIBLE_APP_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.VISIBLE_APP_ADJ) &&
- reportLmkKillAtOrBelow(pw, ProcessList.FOREGROUND_APP_ADJ);
+ reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MIN_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_B_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.PREVIOUS_APP_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.HOME_APP_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.HEAVY_WEIGHT_APP_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.BACKUP_APP_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.PERCEPTIBLE_LOW_APP_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.PERCEPTIBLE_APP_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.VISIBLE_APP_ADJ) &&
+ reportLmkKillAtOrBelow(pw, ProcessList.FOREGROUND_APP_ADJ);
}
/**
@@ -11760,7 +11762,8 @@
ProcessList.NATIVE_ADJ,
ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ,
ProcessList.PERSISTENT_SERVICE_ADJ, ProcessList.FOREGROUND_APP_ADJ,
- ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ,
+ ProcessList.VISIBLE_APP_ADJ,
+ ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_LOW_APP_ADJ,
ProcessList.BACKUP_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.CACHED_APP_MIN_ADJ
@@ -11768,7 +11771,7 @@
static final String[] DUMP_MEM_OOM_LABEL = new String[] {
"Native",
"System", "Persistent", "Persistent Service", "Foreground",
- "Visible", "Perceptible",
+ "Visible", "Perceptible", "Perceptible Low",
"Heavy Weight", "Backup",
"A Services", "Home",
"Previous", "B Services", "Cached"
@@ -11776,7 +11779,7 @@
static final String[] DUMP_MEM_OOM_COMPACT_LABEL = new String[] {
"native",
"sys", "pers", "persvc", "fore",
- "vis", "percept",
+ "vis", "percept", "perceptl",
"heavy", "backup",
"servicea", "home",
"prev", "serviceb", "cached"
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
index 502f078..c7e4fc7 100644
--- a/services/core/java/com/android/server/am/AppCompactor.java
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -55,6 +55,8 @@
private static final int COMPACT_ACTION_FILE_FLAG = 1;
private static final int COMPACT_ACTION_ANON_FLAG = 2;
private static final int COMPACT_ACTION_FULL_FLAG = 3;
+ private static final int COMPACT_ACTION_NONE_FLAG = 4;
+ private static final String COMPACT_ACTION_NONE = "";
private static final String COMPACT_ACTION_FILE = "file";
private static final String COMPACT_ACTION_ANON = "anon";
private static final String COMPACT_ACTION_FULL = "all";
@@ -320,6 +322,8 @@
@VisibleForTesting
static String compactActionIntToString(int action) {
switch(action) {
+ case COMPACT_ACTION_NONE_FLAG:
+ return COMPACT_ACTION_NONE;
case COMPACT_ACTION_FILE_FLAG:
return COMPACT_ACTION_FILE;
case COMPACT_ACTION_ANON_FLAG:
@@ -327,7 +331,7 @@
case COMPACT_ACTION_FULL_FLAG:
return COMPACT_ACTION_FULL;
default:
- return COMPACT_ACTION_FILE;
+ return COMPACT_ACTION_NONE;
}
}
@@ -398,6 +402,10 @@
action = mCompactActionFull;
}
+ if (action.equals(COMPACT_ACTION_NONE)) {
+ return;
+ }
+
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
+ ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 7035698..93a71e5 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -127,18 +127,8 @@
private final ActivityManagerService mService;
private final ProcessList mProcessList;
- /**
- * Used to lock {@link #updateOomAdjImpl} for state consistency. It also reduces frequency lock
- * and unlock when getting and setting value to {@link ProcessRecord#mWindowProcessController}.
- * Note it is declared as Object type so the locked-region-code-injection won't wrap the
- * unnecessary priority booster.
- */
- private final Object mAtmGlobalLock;
-
- OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids,
- Object atmGlobalLock) {
+ OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
mService = service;
- mAtmGlobalLock = atmGlobalLock;
mProcessList = processList;
mActiveUids = activeUids;
@@ -196,13 +186,6 @@
@GuardedBy("mService")
final void updateOomAdjLocked() {
- synchronized (mAtmGlobalLock) {
- updateOomAdjImpl();
- }
- }
-
- @GuardedBy({"mService", "mAtmGlobalLock"})
- private void updateOomAdjImpl() {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "updateOomAdj");
mService.mOomAdjProfiler.oomAdjStarted();
final ProcessRecord TOP_APP = mService.getTopAppLocked();
@@ -1224,8 +1207,8 @@
}
} else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
- && adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) {
- newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1;
+ && adj > ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+ newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -1610,7 +1593,7 @@
// " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
if (adj > app.maxAdj) {
adj = app.maxAdj;
- if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
+ if (app.maxAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 69cf54b..f01305e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -183,6 +183,10 @@
// is not entirely fatal but is generally a bad idea.
static final int BACKUP_APP_ADJ = 300;
+ // This is a process bound by the system that's more important than services but not so
+ // perceptible that it affects the user immediately if killed.
+ static final int PERCEPTIBLE_LOW_APP_ADJ = 250;
+
// This is a process only hosting components that are perceptible to the
// user, and we really want to avoid killing them, but they are not
// immediately visible. An example is background music playback.
@@ -717,6 +721,9 @@
} else if (setAdj >= ProcessList.BACKUP_APP_ADJ) {
return buildOomTag("bkup ", "bkup", null, setAdj,
ProcessList.BACKUP_APP_ADJ, compact);
+ } else if (setAdj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+ return buildOomTag("prcl ", "prcl", null, setAdj,
+ ProcessList.PERCEPTIBLE_LOW_APP_ADJ, compact);
} else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
return buildOomTag("prcp ", "prcp", null, setAdj,
ProcessList.PERCEPTIBLE_APP_ADJ, compact);
@@ -1740,8 +1747,11 @@
try {
final String[] packageNames = mService.mContext.getPackageManager()
.getPackagesForUid(uid);
- final String[] visibleVolIds = LocalServices.getService(StorageManagerInternal.class)
+ final StorageManagerInternal storageManagerInternal =
+ LocalServices.getService(StorageManagerInternal.class);
+ final String[] visibleVolIds = storageManagerInternal
.getVisibleVolumesForUser(UserHandle.getUserId(uid));
+ final String sandboxId = storageManagerInternal.getSandboxId(app.info.packageName);
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkSlow(startTime, "startProcess: asking zygote to start proc");
@@ -1751,7 +1761,7 @@
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
- packageNames, visibleVolIds,
+ packageNames, visibleVolIds, sandboxId,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else if (hostingType.equals("app_zygote")) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
@@ -1760,14 +1770,14 @@
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
- packageNames, visibleVolIds, /*useBlastulaPool=*/ false,
+ packageNames, visibleVolIds, sandboxId, /*useBlastulaPool=*/ false,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName,
- packageNames, visibleVolIds,
+ packageNames, visibleVolIds, sandboxId,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
checkSlow(startTime, "startProcess: returned from zygote!");
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 5dccaf1..fcc857b 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -713,6 +713,8 @@
adj = ProcessList.VISIBLE_APP_ADJ;
} else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+ } else if (adj < ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+ adj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
} else if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
adj = ProcessList.CACHED_APP_MIN_ADJ;
} else if (adj < ProcessList.CACHED_APP_MAX_ADJ) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index c981e68..7f6648a 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -2072,7 +2072,8 @@
new TimingsTraceLog("SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER)
.logDuration("SystemUserUnlock", unlockTime);
} else {
- Slog.d(TAG, "Unlocking user " + id + " took " + unlockTime + " ms");
+ new TimingsTraceLog("SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER)
+ .logDuration("User" + id + "Unlock", unlockTime);
}
}
};
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 0dc73d9..6df60d6 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -21,6 +21,8 @@
import android.annotation.NonNull;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.content.ContentResolver;
import android.content.Context;
@@ -424,11 +426,28 @@
}
/*package*/ void postDisconnectHearingAid() {
- sendMsgNoDelay(MSG_DISCONNECT_HEARING_AID, SENDMSG_QUEUE);
+ sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
}
/*package*/ void postDisconnectHeadset() {
- sendMsgNoDelay(MSG_DISCONNECT_HEADSET, SENDMSG_QUEUE);
+ sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
+ }
+
+ /*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) {
+ sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile);
+ }
+
+ /*package*/ void postBtA2dpSinkProfileConnected(BluetoothProfile profile) {
+ sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK, SENDMSG_QUEUE, profile);
+ }
+
+ /*package*/ void postBtHeasetProfileConnected(BluetoothHeadset headsetProfile) {
+ sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET, SENDMSG_QUEUE, headsetProfile);
+ }
+
+ /*package*/ void postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile) {
+ sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE,
+ hearingAidProfile);
}
//---------------------------------------------------------------------
@@ -460,16 +479,14 @@
}
}
+ @GuardedBy("mDeviceStateLock")
/*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state,
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
final int intState = (state == BluetoothA2dp.STATE_CONNECTED)
? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED;
- final int delay;
- synchronized (mDeviceStateLock) {
- delay = mDeviceInventory.checkSendBecomingNoisyIntent(
+ final int delay = mDeviceInventory.checkSendBecomingNoisyIntent(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
AudioSystem.DEVICE_NONE);
- }
final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress();
if (AudioService.DEBUG_DEVICES) {
@@ -719,16 +736,36 @@
mDeviceInventory.disconnectA2dpSink();
}
break;
- case MSG_DISCONNECT_HEARING_AID:
+ case MSG_DISCONNECT_BT_HEARING_AID:
synchronized (mDeviceStateLock) {
mDeviceInventory.disconnectHearingAid();
}
break;
- case MSG_DISCONNECT_HEADSET:
+ case MSG_DISCONNECT_BT_HEADSET:
synchronized (mDeviceStateLock) {
mBtHelper.disconnectHeadset();
}
break;
+ case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP:
+ synchronized (mDeviceStateLock) {
+ mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
+ }
+ break;
+ case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK:
+ synchronized (mDeviceStateLock) {
+ mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj);
+ }
+ break;
+ case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID:
+ synchronized (mDeviceStateLock) {
+ mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
+ }
+ break;
+ case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET:
+ synchronized (mDeviceStateLock) {
+ mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
+ }
+ break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -766,8 +803,12 @@
private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
private static final int MSG_DISCONNECT_A2DP = 19;
private static final int MSG_DISCONNECT_A2DP_SINK = 20;
- private static final int MSG_DISCONNECT_HEARING_AID = 21;
- private static final int MSG_DISCONNECT_HEADSET = 22;
+ private static final int MSG_DISCONNECT_BT_HEARING_AID = 21;
+ private static final int MSG_DISCONNECT_BT_HEADSET = 22;
+ private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP = 23;
+ private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
+ private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
+ private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
private static boolean isMessageHandledUnderWakelock(int msgId) {
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index e918997..58c1882 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -393,6 +393,84 @@
mBluetoothHeadset = null;
}
+ /*package*/ synchronized void onA2dpProfileConnected(BluetoothA2dp a2dp) {
+ mA2dp = a2dp;
+ final List<BluetoothDevice> deviceList = mA2dp.getConnectedDevices();
+ if (deviceList.isEmpty()) {
+ return;
+ }
+ final BluetoothDevice btDevice = deviceList.get(0);
+ final @BluetoothProfile.BtProfileState int state = mA2dp.getConnectionState(btDevice);
+ mDeviceBroker.handleSetA2dpSinkConnectionState(
+ state, new BluetoothA2dpDeviceInfo(btDevice));
+ }
+
+ /*package*/ synchronized void onA2dpSinkProfileConnected(BluetoothProfile profile) {
+ final List<BluetoothDevice> deviceList = profile.getConnectedDevices();
+ if (deviceList.isEmpty()) {
+ return;
+ }
+ final BluetoothDevice btDevice = deviceList.get(0);
+ final @BluetoothProfile.BtProfileState int state =
+ profile.getConnectionState(btDevice);
+ mDeviceBroker.postSetA2dpSourceConnectionState(
+ state, new BluetoothA2dpDeviceInfo(btDevice));
+ }
+
+ /*package*/ synchronized void onHearingAidProfileConnected(BluetoothHearingAid hearingAid) {
+ mHearingAid = hearingAid;
+ final List<BluetoothDevice> deviceList = mHearingAid.getConnectedDevices();
+ if (deviceList.isEmpty()) {
+ return;
+ }
+ final BluetoothDevice btDevice = deviceList.get(0);
+ final @BluetoothProfile.BtProfileState int state =
+ mHearingAid.getConnectionState(btDevice);
+ mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
+ btDevice, state,
+ /*suppressNoisyIntent*/ false,
+ /*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,
+ /*eventSource*/ "mBluetoothProfileServiceListener");
+ }
+
+ /*package*/ synchronized void onHeadsetProfileConnected(BluetoothHeadset headset) {
+ // Discard timeout message
+ mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
+ mBluetoothHeadset = headset;
+ setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
+ // Refresh SCO audio state
+ checkScoAudioState();
+ if (mScoAudioState != SCO_STATE_ACTIVATE_REQ
+ && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
+ return;
+ }
+ boolean status = false;
+ if (mBluetoothHeadsetDevice != null) {
+ switch (mScoAudioState) {
+ case SCO_STATE_ACTIVATE_REQ:
+ status = connectBluetoothScoAudioHelper(
+ mBluetoothHeadset,
+ mBluetoothHeadsetDevice, mScoAudioMode);
+ if (status) {
+ mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
+ }
+ break;
+ case SCO_STATE_DEACTIVATE_REQ:
+ status = disconnectBluetoothScoAudioHelper(
+ mBluetoothHeadset,
+ mBluetoothHeadsetDevice, mScoAudioMode);
+ if (status) {
+ mScoAudioState = SCO_STATE_DEACTIVATING;
+ }
+ break;
+ }
+ }
+ if (!status) {
+ mScoAudioState = SCO_STATE_INACTIVE;
+ broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+ }
+ }
+
//----------------------------------------------------------------------
private void broadcastScoConnectionState(int state) {
mDeviceBroker.postBroadcastScoConnectionState(state);
@@ -462,99 +540,36 @@
}
}
+ // NOTE this listener is NOT called from AudioDeviceBroker event thread, only call async
+ // methods inside listener.
private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
- final BluetoothDevice btDevice;
- List<BluetoothDevice> deviceList;
switch(profile) {
case BluetoothProfile.A2DP:
- synchronized (BtHelper.this) {
- mA2dp = (BluetoothA2dp) proxy;
- deviceList = mA2dp.getConnectedDevices();
- if (deviceList.size() > 0) {
- btDevice = deviceList.get(0);
- if (btDevice == null) {
- Log.e(TAG, "Invalid null device in BT profile listener");
- return;
- }
- final @BluetoothProfile.BtProfileState int state =
- mA2dp.getConnectionState(btDevice);
- mDeviceBroker.handleSetA2dpSinkConnectionState(
- state, new BluetoothA2dpDeviceInfo(btDevice));
- }
- }
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "BT profile service: connecting A2DP profile"));
+ mDeviceBroker.postBtA2dpProfileConnected((BluetoothA2dp) proxy);
break;
case BluetoothProfile.A2DP_SINK:
- deviceList = proxy.getConnectedDevices();
- if (deviceList.size() > 0) {
- btDevice = deviceList.get(0);
- final @BluetoothProfile.BtProfileState int state =
- proxy.getConnectionState(btDevice);
- mDeviceBroker.postSetA2dpSourceConnectionState(
- state, new BluetoothA2dpDeviceInfo(btDevice));
- }
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "BT profile service: connecting A2DP_SINK profile"));
+ mDeviceBroker.postBtA2dpSinkProfileConnected(proxy);
break;
case BluetoothProfile.HEADSET:
- synchronized (BtHelper.this) {
- // Discard timeout message
- mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
- mBluetoothHeadset = (BluetoothHeadset) proxy;
- setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
- // Refresh SCO audio state
- checkScoAudioState();
- // Continue pending action if any
- if (mScoAudioState == SCO_STATE_ACTIVATE_REQ
- || mScoAudioState == SCO_STATE_DEACTIVATE_REQ) {
- boolean status = false;
- if (mBluetoothHeadsetDevice != null) {
- switch (mScoAudioState) {
- case SCO_STATE_ACTIVATE_REQ:
- status = connectBluetoothScoAudioHelper(
- mBluetoothHeadset,
- mBluetoothHeadsetDevice, mScoAudioMode);
- if (status) {
- mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
- }
- break;
- case SCO_STATE_DEACTIVATE_REQ:
- status = disconnectBluetoothScoAudioHelper(
- mBluetoothHeadset,
- mBluetoothHeadsetDevice, mScoAudioMode);
- if (status) {
- mScoAudioState = SCO_STATE_DEACTIVATING;
- }
- break;
- }
- }
- if (!status) {
- mScoAudioState = SCO_STATE_INACTIVE;
- broadcastScoConnectionState(
- AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- }
- }
- }
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "BT profile service: connecting HEADSET profile"));
+ mDeviceBroker.postBtHeasetProfileConnected((BluetoothHeadset) proxy);
break;
case BluetoothProfile.HEARING_AID:
- synchronized (BtHelper.this) {
- mHearingAid = (BluetoothHearingAid) proxy;
- deviceList = mHearingAid.getConnectedDevices();
- if (deviceList.size() > 0) {
- btDevice = deviceList.get(0);
- final @BluetoothProfile.BtProfileState int state =
- mHearingAid.getConnectionState(btDevice);
- mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
- btDevice, state,
- /*suppressNoisyIntent*/ false,
- /*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,
- /*eventSource*/ "mBluetoothProfileServiceListener");
- }
- }
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "BT profile service: connecting HEARING_AID profile"));
+ mDeviceBroker.postBtHearingAidProfileConnected(
+ (BluetoothHearingAid) proxy);
break;
-
default:
break;
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index b50b800..bca84f7 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -391,10 +391,11 @@
private final Random mRandom = new Random();
// TODO(b/123378871): Remove when moved.
- // When BiometricPrompt#setEnableFallback is set to true, we need to store the client (app)
- // receiver. BiometricService internally launches CDCA which invokes BiometricService to
- // start authentication (normal path). When auth is success/rejected, CDCA will use an aidl
- // method to poke BiometricService - the result will then be forwarded to this receiver.
+ // When BiometricPrompt#setAllowDeviceCredentials is set to true, we need to store the
+ // client (app) receiver. BiometricService internally launches CDCA which invokes
+ // BiometricService to start authentication (normal path). When auth is success/rejected,
+ // CDCA will use an aidl method to poke BiometricService - the result will then be forwarded
+ // to this receiver.
private IBiometricServiceReceiver mConfirmDeviceCredentialReceiver;
// The current authentication session, null if idle/done. We need to track both the current
@@ -803,11 +804,21 @@
// we can't get activity results. Store the receiver somewhere so we can forward the
// result back to the client.
// TODO(b/123378871): Remove when moved.
- if (bundle.getBoolean(BiometricPrompt.KEY_ENABLE_FALLBACK)) {
+ if (bundle.getBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL)) {
mHandler.post(() -> {
- mConfirmDeviceCredentialReceiver = receiver;
final KeyguardManager kgm = getContext().getSystemService(
KeyguardManager.class);
+ if (!kgm.isDeviceSecure()) {
+ try {
+ receiver.onError(BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
+ getContext().getString(
+ R.string.biometric_error_device_not_secured));
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ return;
+ }
+ mConfirmDeviceCredentialReceiver = receiver;
// Use this so we don't need to duplicate logic..
final Intent intent = kgm.createConfirmDeviceCredentialIntent(null /* title */,
null /* description */);
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index b65535a..9e0f2fc 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -624,7 +624,8 @@
handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
0 /*vendorCode */);
- StatsLog.write(StatsLog.BIOMETRIC_HAL_DEATH_REPORTED, statsModality());
+ StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(),
+ BiometricsProtoEnums.ISSUE_HAL_DEATH);
}
protected ClientMonitor getCurrentClient() {
diff --git a/services/core/java/com/android/server/biometrics/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/LoggableMonitor.java
index 91c924d..3b75b95 100644
--- a/services/core/java/com/android/server/biometrics/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/LoggableMonitor.java
@@ -28,7 +28,7 @@
public abstract class LoggableMonitor {
public static final String TAG = "BiometricStats";
- public static final boolean DEBUG = true;
+ public static final boolean DEBUG = false;
private long mFirstAcquireTimeMs;
@@ -137,6 +137,8 @@
+ ", RequireConfirmation: " + requireConfirmation
+ ", State: " + authState
+ ", Latency: " + latency);
+ } else {
+ Slog.v(TAG, "Authentication latency: " + latency);
}
StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED,
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 017503a..8995068 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -705,6 +705,8 @@
public void serviceDied(long cookie) {
super.serviceDied(cookie);
mDaemon = null;
+
+ mCurrentUserId = UserHandle.USER_NULL; // Force updateActiveGroup() to re-evaluate
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 9e0a1c0c..d8544e3 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -49,6 +49,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
+import android.util.StatsLog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -554,6 +555,8 @@
+ " " + f.getDeviceId());
FingerprintUtils.getInstance().removeBiometricForUser(getContext(),
getTargetUserId(), f.getBiometricId());
+ StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
+ BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK);
}
mEnrolledList.clear();
}
@@ -1003,6 +1006,8 @@
mHalDeviceId, mToken, new ServiceListenerImpl(null), uf.f.getBiometricId(),
uf.f.getGroupId(), uf.userId, restricted, getContext().getOpPackageName());
removeInternal(client);
+ StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(),
+ BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL);
} else {
clearEnumerateState();
}
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index 9cb6eee..8171ad6 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -387,8 +387,10 @@
Slog.d(TAG, "Setting saturation level: " + saturationLevel);
if (saturationLevel == 100) {
+ setActivated(false);
Matrix.setIdentityM(mMatrixGlobalSaturation, 0);
} else {
+ setActivated(true);
float saturation = saturationLevel * 0.1f;
float desaturation = 1.0f - saturation;
float[] luminance = {0.231f * desaturation, 0.715f * desaturation,
@@ -674,6 +676,10 @@
if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
mDisplayWhiteBalanceTintController.endAnimator();
}
+
+ if (mGlobalSaturationTintController.isAvailable(getContext())) {
+ mGlobalSaturationTintController.setActivated(null);
+ }
}
private void onNightDisplayAutoModeChanged(int autoMode) {
@@ -1671,6 +1677,20 @@
}
@Override
+ public boolean isSaturationActivated() {
+ getContext().enforceCallingPermission(
+ Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
+ "Permission required to get display saturation level");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return !mGlobalSaturationTintController.isActivatedStateNotSet()
+ && mGlobalSaturationTintController.isActivated();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public boolean setAppSaturationLevel(String packageName, int level) {
getContext().enforceCallingPermission(
Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
diff --git a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
index cf84e22..1b23794 100644
--- a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
+++ b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
@@ -187,7 +187,7 @@
@Override
public boolean isDefaultServiceEnabled(int userId) {
synchronized (mLock) {
- return mDefaultServicesDisabled.get(userId);
+ return !mDefaultServicesDisabled.get(userId);
}
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 19d10ec..cefe583 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -509,7 +509,7 @@
private static final float DEFAULT_CONN_CONGESTION_DELAY_FRAC = 0.5f;
private static final float DEFAULT_CONN_PREFETCH_RELAX_FRAC = 0.5f;
private static final boolean DEFAULT_USE_HEARTBEATS = false;
- private static final boolean DEFAULT_TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
+ private static final boolean DEFAULT_TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
private static final long DEFAULT_QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS =
10 * 60 * 1000L; // 10 minutes
private static final long DEFAULT_QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS =
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 97c3bac..74628fb 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -110,6 +110,7 @@
final boolean jobWouldBeReady = jobStatus.wouldBeReadyWithConstraint(constraint);
if (DEBUG) {
Slog.v(TAG, "wouldBeReadyWithConstraintLocked: " + jobStatus.toShortString()
+ + " constraint=" + constraint
+ " readyWithConstraint=" + jobWouldBeReady);
}
if (!jobWouldBeReady) {
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index 26f3caf..70deb38 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -149,8 +149,8 @@
@Override
public void onConstantsUpdatedLocked() {
- checkExpiredDelaysAndResetAlarm();
checkExpiredDeadlinesAndResetAlarm();
+ checkExpiredDelaysAndResetAlarm();
}
@Override
@@ -159,20 +159,47 @@
return;
}
- if (job.hasTimingDelayConstraint()
- && job.getEarliestRunTime() <= mNextDelayExpiredElapsedMillis) {
- checkExpiredDelaysAndResetAlarm();
- }
+ final long nowElapsedMillis = sElapsedRealtimeClock.millis();
+
+ // Check deadline constraint first because if it's satisfied, we avoid a little bit of
+ // unnecessary processing of the timing delay.
if (job.hasDeadlineConstraint()
+ && !job.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE)
&& job.getLatestRunTimeElapsed() <= mNextJobExpiredElapsedMillis) {
- checkExpiredDeadlinesAndResetAlarm();
+ if (evaluateDeadlineConstraint(job, nowElapsedMillis)) {
+ checkExpiredDeadlinesAndResetAlarm();
+ checkExpiredDelaysAndResetAlarm();
+ } else {
+ final boolean isAlarmForJob =
+ job.getLatestRunTimeElapsed() == mNextJobExpiredElapsedMillis;
+ final boolean wouldBeReady = wouldBeReadyWithConstraintLocked(
+ job, JobStatus.CONSTRAINT_DEADLINE);
+ if ((isAlarmForJob && !wouldBeReady) || (!isAlarmForJob && wouldBeReady)) {
+ checkExpiredDeadlinesAndResetAlarm();
+ }
+ }
+ }
+ if (job.hasTimingDelayConstraint()
+ && !job.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY)
+ && job.getEarliestRunTime() <= mNextDelayExpiredElapsedMillis) {
+ if (evaluateTimingDelayConstraint(job, nowElapsedMillis)) {
+ checkExpiredDelaysAndResetAlarm();
+ } else {
+ final boolean isAlarmForJob =
+ job.getEarliestRunTime() == mNextDelayExpiredElapsedMillis;
+ final boolean wouldBeReady = wouldBeReadyWithConstraintLocked(
+ job, JobStatus.CONSTRAINT_TIMING_DELAY);
+ if ((isAlarmForJob && !wouldBeReady) || (!isAlarmForJob && wouldBeReady)) {
+ checkExpiredDelaysAndResetAlarm();
+ }
+ }
}
}
@Override
public void reevaluateStateLocked(int uid) {
- checkExpiredDelaysAndResetAlarm();
checkExpiredDeadlinesAndResetAlarm();
+ checkExpiredDelaysAndResetAlarm();
}
/**
@@ -182,10 +209,10 @@
* back and forth.
*/
private boolean canStopTrackingJobLocked(JobStatus job) {
- return (!job.hasTimingDelayConstraint() ||
- (job.satisfiedConstraints&JobStatus.CONSTRAINT_TIMING_DELAY) != 0) &&
- (!job.hasDeadlineConstraint() ||
- (job.satisfiedConstraints&JobStatus.CONSTRAINT_DEADLINE) != 0);
+ return (!job.hasTimingDelayConstraint()
+ || job.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY))
+ && (!job.hasDeadlineConstraint()
+ || job.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
}
private void ensureAlarmServiceLocked() {
@@ -241,6 +268,7 @@
}
}
+ /** @return true if the job's deadline constraint is satisfied */
private boolean evaluateDeadlineConstraint(JobStatus job, long nowElapsedMillis) {
final long jobDeadline = job.getLatestRunTimeElapsed();
@@ -279,7 +307,7 @@
if (job.isReady()) {
ready = true;
}
- } else if (!job.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY)) {
+ } else {
if (mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS
&& !wouldBeReadyWithConstraintLocked(
job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
@@ -319,6 +347,7 @@
}
}
+ /** @return true if the job's delay constraint is satisfied */
private boolean evaluateTimingDelayConstraint(JobStatus job, long nowElapsedMillis) {
final long jobDelayTime = job.getEarliestRunTime();
if (jobDelayTime <= nowElapsedMillis) {
@@ -347,6 +376,9 @@
*/
private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
+ if (mNextDelayExpiredElapsedMillis == alarmTimeElapsedMillis) {
+ return;
+ }
mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener,
mNextDelayExpiredElapsedMillis, ws);
@@ -359,6 +391,9 @@
*/
private void setDeadlineExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
+ if (mNextJobExpiredElapsedMillis == alarmTimeElapsedMillis) {
+ return;
+ }
mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis;
updateAlarmWithListenerLocked(DEADLINE_TAG, mDeadlineExpiredListener,
mNextJobExpiredElapsedMillis, ws);
diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java
index 7225926..91b5234 100644
--- a/services/core/java/com/android/server/location/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/GnssConfiguration.java
@@ -367,7 +367,7 @@
return defaultValue;
}
try {
- return Integer.parseInt(valueString);
+ return Integer.decode(valueString);
} catch (NumberFormatException e) {
Log.e(TAG, "Unable to parse config parameter " + configParameter + " value: "
+ valueString + ". Using default value: " + defaultValue);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index f368e7b..2f0b388 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -302,7 +302,7 @@
MAX_RETRY_INTERVAL);
// true if we are enabled, protected by this
- private boolean mEnabled = true;
+ private boolean mEnabled;
private boolean mShutdown;
diff --git a/services/core/java/com/android/server/location/LocationBasedCountryDetector.java b/services/core/java/com/android/server/location/LocationBasedCountryDetector.java
index 6527899f..8ee1285 100644
--- a/services/core/java/com/android/server/location/LocationBasedCountryDetector.java
+++ b/services/core/java/com/android/server/location/LocationBasedCountryDetector.java
@@ -235,18 +235,15 @@
* Start a new thread to query the country from Geocoder.
*/
private synchronized void queryCountryCode(final Location location) {
- if (location == null) {
- notifyListener(null);
- return;
- }
if (mQueryThread != null) return;
mQueryThread = new Thread(new Runnable() {
@Override
public void run() {
- String countryIso = null;
- if (location != null) {
- countryIso = getCountryFromLocation(location);
+ if (location == null) {
+ notifyListener(null);
+ return;
}
+ String countryIso = getCountryFromLocation(location);
if (countryIso != null) {
mDetectedCountry = new Country(countryIso, Country.COUNTRY_SOURCE_LOCATION);
} else {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 1f9b027..e7a71b9 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.os.RemoteException;
import android.security.Scrypt;
import android.security.keystore.recovery.KeyChainProtectionParams;
import android.security.keystore.recovery.KeyChainSnapshot;
@@ -162,7 +163,7 @@
}
}
- private void syncKeys() {
+ private void syncKeys() throws RemoteException {
if (mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
// Application keys for the user will not be available for sync.
Log.w(TAG, "Credentials are not set for user " + mUserId);
@@ -195,7 +196,7 @@
&& mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
}
- private void syncKeysForAgent(int recoveryAgentUid) throws IOException {
+ private void syncKeysForAgent(int recoveryAgentUid) throws IOException, RemoteException {
boolean shouldRecreateCurrentVersion = false;
if (!shouldCreateSnapshot(recoveryAgentUid)) {
shouldRecreateCurrentVersion =
@@ -412,7 +413,7 @@
private Map<String, Pair<SecretKey, byte[]>> getKeysToSync(int recoveryAgentUid)
throws InsecureUserException, KeyStoreException, UnrecoverableKeyException,
NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException,
- InvalidKeyException, InvalidAlgorithmParameterException, IOException {
+ InvalidKeyException, InvalidAlgorithmParameterException, IOException, RemoteException {
PlatformDecryptionKey decryptKey = mPlatformKeyManager.getDecryptKey(mUserId);;
Map<String, WrappedKey> wrappedKeys = mRecoverableKeyStoreDb.getAllKeys(
mUserId, recoveryAgentUid, decryptKey.getGenerationId());
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
index 9ca052b..1c18771 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
@@ -18,15 +18,21 @@
import android.app.KeyguardManager;
import android.content.Context;
+import android.os.RemoteException;
+import android.security.GateKeeper;
import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
+import android.service.gatekeeper.IGateKeeperService;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@@ -34,9 +40,11 @@
import java.security.cert.CertificateException;
import java.util.Locale;
+import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
-import javax.security.auth.DestroyFailedException;
+import javax.crypto.spec.GCMParameterSpec;
/**
* Manages creating and checking the validity of the platform key.
@@ -67,6 +75,10 @@
private static final String ENCRYPT_KEY_ALIAS_SUFFIX = "encrypt";
private static final String DECRYPT_KEY_ALIAS_SUFFIX = "decrypt";
private static final int USER_AUTHENTICATION_VALIDITY_DURATION_SECONDS = 15;
+ private static final String KEY_WRAP_CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+ private static final int GCM_TAG_LENGTH_BITS = 128;
+ // Only used for checking if a key is usable
+ private static final byte[] GCM_INSECURE_NONCE_BYTES = new byte[12];
private final Context mContext;
private final KeyStoreProxy mKeyStore;
@@ -158,12 +170,14 @@
* @throws KeyStoreException if there is an error in AndroidKeyStore.
* @throws InsecureUserException if the user does not have a lock screen set.
* @throws IOException if there was an issue with local database update.
+ * @throws RemoteException if there was an issue communicating with {@link IGateKeeperService}.
*
* @hide
*/
@VisibleForTesting
void regenerate(int userId)
- throws NoSuchAlgorithmException, KeyStoreException, InsecureUserException, IOException {
+ throws NoSuchAlgorithmException, KeyStoreException, InsecureUserException, IOException,
+ RemoteException {
if (!isAvailable(userId)) {
throw new InsecureUserException(String.format(
Locale.US, "%d does not have a lock screen set.", userId));
@@ -190,11 +204,13 @@
* @throws NoSuchAlgorithmException if AES is unavailable - should never occur.
* @throws InsecureUserException if the user does not have a lock screen set.
* @throws IOException if there was an issue with local database update.
+ * @throws RemoteException if there was an issue communicating with {@link IGateKeeperService}.
*
* @hide
*/
- public PlatformEncryptionKey getEncryptKey(int userId) throws KeyStoreException,
- UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException, IOException {
+ public PlatformEncryptionKey getEncryptKey(int userId)
+ throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException,
+ InsecureUserException, IOException, RemoteException {
init(userId);
try {
// Try to see if the decryption key is still accessible before using the encryption key.
@@ -243,14 +259,18 @@
* @throws NoSuchAlgorithmException if AES is unavailable - should never occur.
* @throws InsecureUserException if the user does not have a lock screen set.
* @throws IOException if there was an issue with local database update.
+ * @throws RemoteException if there was an issue communicating with {@link IGateKeeperService}.
*
* @hide
*/
- public PlatformDecryptionKey getDecryptKey(int userId) throws KeyStoreException,
- UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException, IOException {
+ public PlatformDecryptionKey getDecryptKey(int userId)
+ throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException,
+ InsecureUserException, IOException, RemoteException {
init(userId);
try {
- return getDecryptKeyInternal(userId);
+ PlatformDecryptionKey decryptionKey = getDecryptKeyInternal(userId);
+ ensureDecryptionKeyIsValid(userId, decryptionKey);
+ return decryptionKey;
} catch (UnrecoverableKeyException e) {
Log.i(TAG, String.format(Locale.US,
"Regenerating permanently invalid Platform key for user %d.",
@@ -284,6 +304,29 @@
}
/**
+ * Tries to use the decryption key to make sure it is not permanently invalidated. The exception
+ * {@code KeyPermanentlyInvalidatedException} is thrown only when the key is in use.
+ *
+ * <p>Note that we ignore all other InvalidKeyException exceptions, because such an exception
+ * may be thrown for auth-bound keys if there's no recent unlock event.
+ */
+ private void ensureDecryptionKeyIsValid(int userId, PlatformDecryptionKey decryptionKey)
+ throws UnrecoverableKeyException {
+ try {
+ Cipher.getInstance(KEY_WRAP_CIPHER_ALGORITHM).init(Cipher.UNWRAP_MODE,
+ decryptionKey.getKey(),
+ new GCMParameterSpec(GCM_TAG_LENGTH_BITS, GCM_INSECURE_NONCE_BYTES));
+ } catch (KeyPermanentlyInvalidatedException e) {
+ Log.e(TAG, String.format(Locale.US, "The platform key for user %d became invalid.",
+ userId));
+ throw new UnrecoverableKeyException(e.getMessage());
+ } catch (NoSuchAlgorithmException | InvalidKeyException
+ | InvalidAlgorithmParameterException | NoSuchPaddingException e) {
+ // Ignore all other exceptions
+ }
+ }
+
+ /**
* Initializes the class. If there is no current platform key, and the user has a lock screen
* set, will create the platform key and set the generation ID.
*
@@ -291,11 +334,13 @@
* @throws KeyStoreException if there was an error in AndroidKeyStore.
* @throws NoSuchAlgorithmException if AES is unavailable - should never happen.
* @throws IOException if there was an issue with local database update.
+ * @throws RemoteException if there was an issue communicating with {@link IGateKeeperService}.
*
* @hide
*/
void init(int userId)
- throws KeyStoreException, NoSuchAlgorithmException, InsecureUserException, IOException {
+ throws KeyStoreException, NoSuchAlgorithmException, InsecureUserException, IOException,
+ RemoteException {
if (!isAvailable(userId)) {
throw new InsecureUserException(String.format(
Locale.US, "%d does not have a lock screen set.", userId));
@@ -372,6 +417,11 @@
&& mKeyStore.containsAlias(getDecryptAlias(userId, generationId));
}
+ @VisibleForTesting
+ IGateKeeperService getGateKeeperService() {
+ return GateKeeper.getService();
+ }
+
/**
* Generates a new 256-bit AES key, and loads it into AndroidKeyStore with the given
* {@code generationId} determining its aliases.
@@ -380,15 +430,23 @@
* available since API version 1.
* @throws KeyStoreException if there was an issue loading the keys into AndroidKeyStore.
* @throws IOException if there was an issue with local database update.
+ * @throws RemoteException if there was an issue communicating with {@link IGateKeeperService}.
*/
private void generateAndLoadKey(int userId, int generationId)
- throws NoSuchAlgorithmException, KeyStoreException, IOException {
+ throws NoSuchAlgorithmException, KeyStoreException, IOException, RemoteException {
String encryptAlias = getEncryptAlias(userId, generationId);
String decryptAlias = getDecryptAlias(userId, generationId);
// SecretKey implementation doesn't provide reliable way to destroy the secret
// so it may live in memory for some time.
SecretKey secretKey = generateAesKey();
+ long secureUserId = getGateKeeperService().getSecureUserId(userId);
+ // TODO(b/124095438): Propagate this failure instead of silently failing.
+ if (secureUserId == GateKeeper.INVALID_SECURE_USER_ID) {
+ Log.e(TAG, "No SID available for user " + userId);
+ return;
+ }
+
// Store decryption key first since it is more likely to fail.
mKeyStore.setEntry(
decryptAlias,
@@ -399,7 +457,7 @@
USER_AUTHENTICATION_VALIDITY_DURATION_SECONDS)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
- .setBoundToSpecificSecureUserId(userId)
+ .setBoundToSpecificSecureUserId(secureUserId)
.build());
mKeyStore.setEntry(
encryptAlias,
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index a7f1146..e479a15 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -23,6 +23,9 @@
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.pm.PackageManager.SIGNATURE_MATCH;
+import static android.os.Trace.TRACE_TAG_RRO;
+import static android.os.Trace.traceBegin;
+import static android.os.Trace.traceEnd;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -223,36 +226,41 @@
public OverlayManagerService(@NonNull final Context context,
@NonNull final Installer installer) {
super(context);
- mSettingsFile = new AtomicFile(
- new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
- mPackageManager = new PackageManagerHelper();
- mUserManager = UserManagerService.getInstance();
- IdmapManager im = new IdmapManager(installer);
- mSettings = new OverlayManagerSettings();
- mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
- getDefaultOverlayPackages(), new OverlayChangeListener());
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService");
+ mSettingsFile = new AtomicFile(
+ new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
+ mPackageManager = new PackageManagerHelper();
+ mUserManager = UserManagerService.getInstance();
+ IdmapManager im = new IdmapManager(installer);
+ mSettings = new OverlayManagerSettings();
+ mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
+ getDefaultOverlayPackages(), new OverlayChangeListener());
- final IntentFilter packageFilter = new IntentFilter();
- packageFilter.addAction(ACTION_PACKAGE_ADDED);
- packageFilter.addAction(ACTION_PACKAGE_CHANGED);
- packageFilter.addAction(ACTION_PACKAGE_REMOVED);
- packageFilter.addDataScheme("package");
- getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
- packageFilter, null, null);
+ final IntentFilter packageFilter = new IntentFilter();
+ packageFilter.addAction(ACTION_PACKAGE_ADDED);
+ packageFilter.addAction(ACTION_PACKAGE_CHANGED);
+ packageFilter.addAction(ACTION_PACKAGE_REMOVED);
+ packageFilter.addDataScheme("package");
+ getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
+ packageFilter, null, null);
- final IntentFilter userFilter = new IntentFilter();
- userFilter.addAction(ACTION_USER_ADDED);
- userFilter.addAction(ACTION_USER_REMOVED);
- getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
- userFilter, null, null);
+ final IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(ACTION_USER_ADDED);
+ userFilter.addAction(ACTION_USER_REMOVED);
+ getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
+ userFilter, null, null);
- restoreSettings();
+ restoreSettings();
- initIfNeeded();
- onSwitchUser(UserHandle.USER_SYSTEM);
+ initIfNeeded();
+ onSwitchUser(UserHandle.USER_SYSTEM);
- publishBinderService(Context.OVERLAY_SERVICE, mService);
- publishLocalService(OverlayManagerService.class, this);
+ publishBinderService(Context.OVERLAY_SERVICE, mService);
+ publishLocalService(OverlayManagerService.class, this);
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
+ }
}
@Override
@@ -280,13 +288,18 @@
@Override
public void onSwitchUser(final int newUserId) {
- // ensure overlays in the settings are up-to-date, and propagate
- // any asset changes to the rest of the system
- synchronized (mLock) {
- final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
- updateAssets(newUserId, targets);
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onSwitchUser " + newUserId);
+ // ensure overlays in the settings are up-to-date, and propagate
+ // any asset changes to the rest of the system
+ synchronized (mLock) {
+ final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
+ updateAssets(newUserId, targets);
+ }
+ schedulePersistSettings();
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
- schedulePersistSettings();
}
private static String[] getDefaultOverlayPackages() {
@@ -350,85 +363,110 @@
private void onPackageAdded(@NonNull final String packageName,
@NonNull final int[] userIds) {
- for (final int userId : userIds) {
- synchronized (mLock) {
- final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
- false);
- if (pi != null) {
- mPackageManager.cachePackageInfo(packageName, userId, pi);
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageAdded(packageName, userId);
- } else {
- mImpl.onTargetPackageAdded(packageName, userId);
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName);
+ for (final int userId : userIds) {
+ synchronized (mLock) {
+ final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
+ false);
+ if (pi != null) {
+ mPackageManager.cachePackageInfo(packageName, userId, pi);
+ if (pi.isOverlayPackage()) {
+ mImpl.onOverlayPackageAdded(packageName, userId);
+ } else {
+ mImpl.onTargetPackageAdded(packageName, userId);
+ }
}
}
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
private void onPackageChanged(@NonNull final String packageName,
@NonNull final int[] userIds) {
- for (int userId : userIds) {
- synchronized (mLock) {
- final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
- false);
- if (pi != null) {
- mPackageManager.cachePackageInfo(packageName, userId, pi);
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageChanged(packageName, userId);
- } else {
- mImpl.onTargetPackageChanged(packageName, userId);
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName);
+ for (int userId : userIds) {
+ synchronized (mLock) {
+ final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
+ false);
+ if (pi != null) {
+ mPackageManager.cachePackageInfo(packageName, userId, pi);
+ if (pi.isOverlayPackage()) {
+ mImpl.onOverlayPackageChanged(packageName, userId);
+ } else {
+ mImpl.onTargetPackageChanged(packageName, userId);
+ }
}
}
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
private void onPackageUpgrading(@NonNull final String packageName,
@NonNull final int[] userIds) {
- for (int userId : userIds) {
- synchronized (mLock) {
- mPackageManager.forgetPackageInfo(packageName, userId);
- final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
- if (oi != null) {
- mImpl.onOverlayPackageUpgrading(packageName, userId);
- } else {
- mImpl.onTargetPackageUpgrading(packageName, userId);
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageUpgrading " + packageName);
+ for (int userId : userIds) {
+ synchronized (mLock) {
+ mPackageManager.forgetPackageInfo(packageName, userId);
+ final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
+ if (oi != null) {
+ mImpl.onOverlayPackageUpgrading(packageName, userId);
+ } else {
+ mImpl.onTargetPackageUpgrading(packageName, userId);
+ }
}
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
private void onPackageUpgraded(@NonNull final String packageName,
@NonNull final int[] userIds) {
- for (int userId : userIds) {
- synchronized (mLock) {
- final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
- false);
- if (pi != null) {
- mPackageManager.cachePackageInfo(packageName, userId, pi);
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageUpgraded(packageName, userId);
- } else {
- mImpl.onTargetPackageUpgraded(packageName, userId);
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageUpgraded " + packageName);
+ for (int userId : userIds) {
+ synchronized (mLock) {
+ final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
+ false);
+ if (pi != null) {
+ mPackageManager.cachePackageInfo(packageName, userId, pi);
+ if (pi.isOverlayPackage()) {
+ mImpl.onOverlayPackageUpgraded(packageName, userId);
+ } else {
+ mImpl.onTargetPackageUpgraded(packageName, userId);
+ }
}
}
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
private void onPackageRemoved(@NonNull final String packageName,
@NonNull final int[] userIds) {
- for (int userId : userIds) {
- synchronized (mLock) {
- mPackageManager.forgetPackageInfo(packageName, userId);
- final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
- if (oi != null) {
- mImpl.onOverlayPackageRemoved(packageName, userId);
- } else {
- mImpl.onTargetPackageRemoved(packageName, userId);
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName);
+ for (int userId : userIds) {
+ synchronized (mLock) {
+ mPackageManager.forgetPackageInfo(packageName, userId);
+ final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
+ if (oi != null) {
+ mImpl.onOverlayPackageRemoved(packageName, userId);
+ } else {
+ mImpl.onTargetPackageRemoved(packageName, userId);
+ }
}
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
}
@@ -440,19 +478,29 @@
switch (intent.getAction()) {
case ACTION_USER_ADDED:
if (userId != UserHandle.USER_NULL) {
- final ArrayList<String> targets;
- synchronized (mLock) {
- targets = mImpl.updateOverlaysForUser(userId);
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
+ final ArrayList<String> targets;
+ synchronized (mLock) {
+ targets = mImpl.updateOverlaysForUser(userId);
+ }
+ updateOverlayPaths(userId, targets);
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
- updateOverlayPaths(userId, targets);
}
break;
case ACTION_USER_REMOVED:
if (userId != UserHandle.USER_NULL) {
- synchronized (mLock) {
- mImpl.onUserRemoved(userId);
- mPackageManager.forgetAllPackageInfos(userId);
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_REMOVED");
+ synchronized (mLock) {
+ mImpl.onUserRemoved(userId);
+ mPackageManager.forgetAllPackageInfos(userId);
+ }
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
break;
@@ -466,152 +514,198 @@
private final IBinder mService = new IOverlayManager.Stub() {
@Override
public Map<String, List<OverlayInfo>> getAllOverlays(int userId) throws RemoteException {
- userId = handleIncomingUser(userId, "getAllOverlays");
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#getAllOverlays " + userId);
+ userId = handleIncomingUser(userId, "getAllOverlays");
- synchronized (mLock) {
- return mImpl.getOverlaysForUser(userId);
+ synchronized (mLock) {
+ return mImpl.getOverlaysForUser(userId);
+ }
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
@Override
public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
int userId) throws RemoteException {
- userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
- if (targetPackageName == null) {
- return Collections.emptyList();
- }
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfosForTarget " + targetPackageName);
+ userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
+ if (targetPackageName == null) {
+ return Collections.emptyList();
+ }
- synchronized (mLock) {
- return mImpl.getOverlayInfosForTarget(targetPackageName, userId);
+ synchronized (mLock) {
+ return mImpl.getOverlayInfosForTarget(targetPackageName, userId);
+ }
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
@Override
public OverlayInfo getOverlayInfo(@Nullable final String packageName,
int userId) throws RemoteException {
- userId = handleIncomingUser(userId, "getOverlayInfo");
- if (packageName == null) {
- return null;
- }
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfo " + packageName);
+ userId = handleIncomingUser(userId, "getOverlayInfo");
+ if (packageName == null) {
+ return null;
+ }
- synchronized (mLock) {
- return mImpl.getOverlayInfo(packageName, userId);
+ synchronized (mLock) {
+ return mImpl.getOverlayInfo(packageName, userId);
+ }
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
@Override
public boolean setEnabled(@Nullable final String packageName, final boolean enable,
int userId) throws RemoteException {
- enforceChangeOverlayPackagesPermission("setEnabled");
- userId = handleIncomingUser(userId, "setEnabled");
- if (packageName == null) {
- return false;
- }
-
- final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mLock) {
- return mImpl.setEnabled(packageName, enable, userId);
+ traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable);
+ enforceChangeOverlayPackagesPermission("setEnabled");
+ userId = handleIncomingUser(userId, "setEnabled");
+ if (packageName == null) {
+ return false;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mImpl.setEnabled(packageName, enable, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ traceEnd(TRACE_TAG_RRO);
}
}
@Override
public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
int userId) throws RemoteException {
- enforceChangeOverlayPackagesPermission("setEnabledExclusive");
- userId = handleIncomingUser(userId, "setEnabledExclusive");
- if (packageName == null || !enable) {
- return false;
- }
-
- final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mLock) {
- return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
- userId);
+ traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable);
+ enforceChangeOverlayPackagesPermission("setEnabledExclusive");
+ userId = handleIncomingUser(userId, "setEnabledExclusive");
+ if (packageName == null || !enable) {
+ return false;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
+ userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ traceEnd(TRACE_TAG_RRO);
}
}
@Override
public boolean setEnabledExclusiveInCategory(@Nullable String packageName, int userId)
throws RemoteException {
- enforceChangeOverlayPackagesPermission("setEnabledExclusiveInCategory");
- userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
- if (packageName == null) {
- return false;
- }
-
- final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mLock) {
- return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
- userId);
+ traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);
+ enforceChangeOverlayPackagesPermission("setEnabledExclusiveInCategory");
+ userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
+ if (packageName == null) {
+ return false;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
+ userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ traceEnd(TRACE_TAG_RRO);
}
}
@Override
public boolean setPriority(@Nullable final String packageName,
@Nullable final String parentPackageName, int userId) throws RemoteException {
- enforceChangeOverlayPackagesPermission("setPriority");
- userId = handleIncomingUser(userId, "setPriority");
- if (packageName == null || parentPackageName == null) {
- return false;
- }
-
- final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mLock) {
- return mImpl.setPriority(packageName, parentPackageName, userId);
+ traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " "
+ + parentPackageName);
+ enforceChangeOverlayPackagesPermission("setPriority");
+ userId = handleIncomingUser(userId, "setPriority");
+ if (packageName == null || parentPackageName == null) {
+ return false;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mImpl.setPriority(packageName, parentPackageName, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ traceEnd(TRACE_TAG_RRO);
}
}
@Override
public boolean setHighestPriority(@Nullable final String packageName, int userId)
throws RemoteException {
- enforceChangeOverlayPackagesPermission("setHighestPriority");
- userId = handleIncomingUser(userId, "setHighestPriority");
- if (packageName == null) {
- return false;
- }
-
- final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mLock) {
- return mImpl.setHighestPriority(packageName, userId);
+ traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName);
+ enforceChangeOverlayPackagesPermission("setHighestPriority");
+ userId = handleIncomingUser(userId, "setHighestPriority");
+ if (packageName == null) {
+ return false;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mImpl.setHighestPriority(packageName, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ traceEnd(TRACE_TAG_RRO);
}
}
@Override
public boolean setLowestPriority(@Nullable final String packageName, int userId)
throws RemoteException {
- enforceChangeOverlayPackagesPermission("setLowestPriority");
- userId = handleIncomingUser(userId, "setLowestPriority");
- if (packageName == null) {
- return false;
- }
-
- final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mLock) {
- return mImpl.setLowestPriority(packageName, userId);
+ traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName);
+ enforceChangeOverlayPackagesPermission("setLowestPriority");
+ userId = handleIncomingUser(userId, "setLowestPriority");
+ if (packageName == null) {
+ return false;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mImpl.setLowestPriority(packageName, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
} finally {
- Binder.restoreCallingIdentity(ident);
+ traceEnd(TRACE_TAG_RRO);
}
}
@@ -705,45 +799,52 @@
* Updates the target packages' set of enabled overlays in PackageManager.
*/
private void updateOverlayPaths(int userId, List<String> targetPackageNames) {
- if (DEBUG) {
- Slog.d(TAG, "Updating overlay assets");
- }
- final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
- final boolean updateFrameworkRes = targetPackageNames.contains("android");
- if (updateFrameworkRes) {
- targetPackageNames = pm.getTargetPackageNames(userId);
- }
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#updateOverlayPaths " + targetPackageNames);
+ if (DEBUG) {
+ Slog.d(TAG, "Updating overlay assets");
+ }
+ final PackageManagerInternal pm =
+ LocalServices.getService(PackageManagerInternal.class);
+ final boolean updateFrameworkRes = targetPackageNames.contains("android");
+ if (updateFrameworkRes) {
+ targetPackageNames = pm.getTargetPackageNames(userId);
+ }
- final Map<String, List<String>> pendingChanges = new ArrayMap<>(targetPackageNames.size());
- synchronized (mLock) {
- final List<String> frameworkOverlays =
- mImpl.getEnabledOverlayPackageNames("android", userId);
+ final Map<String, List<String>> pendingChanges =
+ new ArrayMap<>(targetPackageNames.size());
+ synchronized (mLock) {
+ final List<String> frameworkOverlays =
+ mImpl.getEnabledOverlayPackageNames("android", userId);
+ final int n = targetPackageNames.size();
+ for (int i = 0; i < n; i++) {
+ final String targetPackageName = targetPackageNames.get(i);
+ List<String> list = new ArrayList<>();
+ if (!"android".equals(targetPackageName)) {
+ list.addAll(frameworkOverlays);
+ }
+ list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId));
+ pendingChanges.put(targetPackageName, list);
+ }
+ }
+
final int n = targetPackageNames.size();
for (int i = 0; i < n; i++) {
final String targetPackageName = targetPackageNames.get(i);
- List<String> list = new ArrayList<>();
- if (!"android".equals(targetPackageName)) {
- list.addAll(frameworkOverlays);
+ if (DEBUG) {
+ Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=["
+ + TextUtils.join(",", pendingChanges.get(targetPackageName))
+ + "] userId=" + userId);
}
- list.addAll(mImpl.getEnabledOverlayPackageNames(targetPackageName, userId));
- pendingChanges.put(targetPackageName, list);
- }
- }
- final int n = targetPackageNames.size();
- for (int i = 0; i < n; i++) {
- final String targetPackageName = targetPackageNames.get(i);
- if (DEBUG) {
- Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=["
- + TextUtils.join(",", pendingChanges.get(targetPackageName))
- + "] userId=" + userId);
+ if (!pm.setEnabledOverlayPackages(
+ userId, targetPackageName, pendingChanges.get(targetPackageName))) {
+ Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
+ targetPackageName, userId));
+ }
}
-
- if (!pm.setEnabledOverlayPackages(
- userId, targetPackageName, pendingChanges.get(targetPackageName))) {
- Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
- targetPackageName, userId));
- }
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
@@ -785,32 +886,37 @@
}
private void restoreSettings() {
- synchronized (mLock) {
- if (!mSettingsFile.getBaseFile().exists()) {
- return;
- }
- try (FileInputStream stream = mSettingsFile.openRead()) {
- mSettings.restore(stream);
-
- // We might have data for dying users if the device was
- // restarted before we received USER_REMOVED. Remove data for
- // users that will not exist after the system is ready.
-
- final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/);
- final int[] liveUserIds = new int[liveUsers.size()];
- for (int i = 0; i < liveUsers.size(); i++) {
- liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier();
+ try {
+ traceBegin(TRACE_TAG_RRO, "OMS#restoreSettings");
+ synchronized (mLock) {
+ if (!mSettingsFile.getBaseFile().exists()) {
+ return;
}
- Arrays.sort(liveUserIds);
+ try (FileInputStream stream = mSettingsFile.openRead()) {
+ mSettings.restore(stream);
- for (int userId : mSettings.getUsers()) {
- if (Arrays.binarySearch(liveUserIds, userId) < 0) {
- mSettings.removeUser(userId);
+ // We might have data for dying users if the device was
+ // restarted before we received USER_REMOVED. Remove data for
+ // users that will not exist after the system is ready.
+
+ final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/);
+ final int[] liveUserIds = new int[liveUsers.size()];
+ for (int i = 0; i < liveUsers.size(); i++) {
+ liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier();
}
+ Arrays.sort(liveUserIds);
+
+ for (int userId : mSettings.getUsers()) {
+ if (Arrays.binarySearch(liveUserIds, userId) < 0) {
+ mSettings.removeUser(userId);
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ Slog.e(TAG, "failed to restore overlay state", e);
}
- } catch (IOException | XmlPullParserException e) {
- Slog.e(TAG, "failed to restore overlay state", e);
}
+ } finally {
+ traceEnd(TRACE_TAG_RRO);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index eaedec5..874d1a7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16321,7 +16321,6 @@
final boolean onExternal = args.volumeUuid != null;
final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
- final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0);
final boolean virtualPreload =
((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
@ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
@@ -16353,8 +16352,7 @@
// Retrieve PackageSettings and parse package
@ParseFlags final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
| PackageParser.PARSE_ENFORCE_CODE
- | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
- | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0);
+ | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
@@ -16775,19 +16773,6 @@
"replacePackageLI: new=" + pkg + ", old=" + oldPackage);
}
- // don't allow upgrade to target a release SDK from a pre-release SDK
- final boolean oldTargetsPreRelease = oldPackage.applicationInfo.targetSdkVersion
- == Build.VERSION_CODES.CUR_DEVELOPMENT;
- final boolean newTargetsPreRelease = pkg.applicationInfo.targetSdkVersion
- == Build.VERSION_CODES.CUR_DEVELOPMENT;
- if (oldTargetsPreRelease
- && !newTargetsPreRelease
- && ((parseFlags & PackageParser.PARSE_FORCE_SDK) == 0)) {
- Slog.w(TAG, "Can't install package targeting released sdk");
- throw new PrepareFailure(
- PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE);
- }
-
ps = mSettings.mPackages.get(pkgName11);
disabledPs = mSettings.getDisabledSystemPkgLPr(ps);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index dc18dfc..2eb762b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2383,8 +2383,7 @@
sessionParams.volumeUuid = null;
}
break;
- case "--force-sdk":
- sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
+ case "--force-sdk": // ignore
break;
case "--apex":
sessionParams.setInstallAsApex();
@@ -2961,8 +2960,6 @@
pw.println(" 0=unknown, 1=admin policy, 2=device restore,");
pw.println(" 3=device setup, 4=user request");
pw.println(" --force-uuid: force install on to disk volume with given UUID");
- pw.println(" --force-sdk: allow install even when existing app targets platform");
- pw.println(" codename but new one targets a final API level");
pw.println(" --apex: install an .apex file, not an .apk");
pw.println("");
pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 89aea36..fa8360b 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -220,6 +220,7 @@
session.setStagedSessionFailed(
SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"APEX staging failed, check logcat messages from apexd for more details.");
+ return;
}
if (apexInfoList.apexInfos != null && apexInfoList.apexInfos.length > 0) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 8d64b81..7e4365d 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -119,6 +119,7 @@
UserManager.DISALLOW_OEM_UNLOCK,
UserManager.DISALLOW_UNMUTE_DEVICE,
UserManager.DISALLOW_AUTOFILL,
+ UserManager.DISALLOW_CONTENT_CAPTURE,
UserManager.DISALLOW_USER_SWITCH,
UserManager.DISALLOW_UNIFIED_PASSWORD,
UserManager.DISALLOW_CONFIG_LOCATION,
@@ -743,6 +744,9 @@
case android.provider.Settings.Global.PRIVATE_DNS_MODE:
case android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER:
+ if (callingUid == Process.SYSTEM_UID) {
+ return false;
+ }
restriction = UserManager.DISALLOW_CONFIG_PRIVATE_DNS;
break;
default:
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 23705db..9948a3a 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -480,10 +480,13 @@
final String apkPath = pkg.baseCodePath;
final ApplicationInfo appInfo = pkg.applicationInfo;
final String outDexFile = appInfo.dataDir + "/code_cache/compiled_view.dex";
- if (appInfo.isPrivilegedApp() || appInfo.isEmbeddedDexUsed()) {
+ if (appInfo.isPrivilegedApp() || appInfo.isEmbeddedDexUsed()
+ || appInfo.isDefaultToDeviceProtectedStorage()) {
// Privileged apps prefer to load trusted code so they don't use compiled views.
// If the app is not privileged but prefers code integrity, also avoid compiling
// views.
+ // Also disable the view compiler for protected storage apps since there are
+ // selinux permissions required for writing to user_de.
return false;
}
Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath +
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index e7de8dd..3534cf3 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -67,8 +67,8 @@
mContext.getContentResolver(),
Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
- // TODO: STOPSHIP: Remove the following code once we remove default_sms_application
- // and use the new config_defaultRoleHolders.
+ // TODO: STOPSHIP: Remove the following code once we read the value of
+ // config_defaultSms in RoleControllerService.
if (result == null) {
Collection<SmsApplication.SmsApplicationData> applications =
SmsApplication.getApplicationCollectionAsUser(mContext, userId);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index af3bff0..1782b6a 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -197,7 +197,8 @@
// System Property indicating that retail demo mode is currently enabled.
private static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
- // Possible reasons for shutting down for use in data/misc/reboot/last_shutdown_reason
+ // Possible reasons for shutting down or reboot for use in REBOOT_PROPERTY(sys.boot.reason)
+ // which is set by bootstat
private static final String REASON_SHUTDOWN = "shutdown";
private static final String REASON_REBOOT = "reboot";
private static final String REASON_USERREQUESTED = "shutdown,userrequested";
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 3c6a54a..3a2b69f 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -16,8 +16,11 @@
package com.android.server.rollback;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
@@ -25,6 +28,7 @@
import android.content.rollback.RollbackManager;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.PowerManager;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
@@ -91,6 +95,7 @@
+ failedPackage.getVersionCode() + "]");
return false;
}
+
RollbackInfo rollback = rollbackPair.first;
// We only log mainline package rollbacks, so check if rollback contains the
// module metadata provider, if it does, the rollback is a mainline rollback
@@ -111,6 +116,12 @@
StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
moduleMetadataPackage.getPackageName(),
moduleMetadataPackage.getVersionCode());
+ if (rollback.isStaged()) {
+ int rollbackId = rollback.getRollbackId();
+ BroadcastReceiver listener =
+ listenForStagedSessionReady(rollbackManager, rollbackId);
+ handleStagedSessionChange(rollbackManager, rollbackId, listener);
+ }
} else {
StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
@@ -178,4 +189,42 @@
return null;
}
}
+
+ private BroadcastReceiver listenForStagedSessionReady(RollbackManager rollbackManager,
+ int rollbackId) {
+ BroadcastReceiver sessionUpdatedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ handleStagedSessionChange(rollbackManager,
+ rollbackId, this /* BroadcastReceiver */);
+ }
+ };
+ IntentFilter sessionUpdatedFilter =
+ new IntentFilter(PackageInstaller.ACTION_SESSION_UPDATED);
+ mContext.registerReceiver(sessionUpdatedReceiver, sessionUpdatedFilter);
+ return sessionUpdatedReceiver;
+ }
+
+ private void handleStagedSessionChange(RollbackManager rollbackManager, int rollbackId,
+ BroadcastReceiver listener) {
+ PackageInstaller packageInstaller =
+ mContext.getPackageManager().getPackageInstaller();
+ List<RollbackInfo> recentRollbacks =
+ rollbackManager.getRecentlyCommittedRollbacks();
+ for (int i = 0; i < recentRollbacks.size(); i++) {
+ RollbackInfo recentRollback = recentRollbacks.get(i);
+ int sessionId = recentRollback.getCommittedSessionId();
+ if ((rollbackId == recentRollback.getRollbackId())
+ && (sessionId != PackageInstaller.SessionInfo.INVALID_ID)) {
+ PackageInstaller.SessionInfo sessionInfo =
+ packageInstaller.getSessionInfo(sessionId);
+ if (sessionInfo.isSessionReady()) {
+ mContext.unregisterReceiver(listener);
+ mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
+ } else if (sessionInfo.isSessionFailed()) {
+ mContext.unregisterReceiver(listener);
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 3586772..dd2cda2 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -45,6 +45,8 @@
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
@@ -1419,23 +1421,35 @@
}
}
- private void pullNumFingerprints(int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
+ private void pullNumBiometricsEnrolled(int modality, int tagId, long elapsedNanos,
+ long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
- if (fingerprintManager == null) {
+ FaceManager faceManager = mContext.getSystemService(FaceManager.class);
+ if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT && fingerprintManager == null) {
+ return;
+ }
+ if (modality == BiometricsProtoEnums.MODALITY_FACE && faceManager == null) {
return;
}
UserManager userManager = mContext.getSystemService(UserManager.class);
if (userManager == null) {
return;
}
+
final long token = Binder.clearCallingIdentity();
for (UserInfo user : userManager.getUsers()) {
final int userId = user.getUserHandle().getIdentifier();
- final int numFingerprints = fingerprintManager.getEnrolledFingerprints(userId).size();
+ int numEnrolled = 0;
+ if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT) {
+ numEnrolled = fingerprintManager.getEnrolledFingerprints(userId).size();
+ } else if (modality == BiometricsProtoEnums.MODALITY_FACE) {
+ numEnrolled = faceManager.getEnrolledFaces(userId).size();
+ } else {
+ return;
+ }
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
e.writeInt(userId);
- e.writeInt(numFingerprints);
+ e.writeInt(numEnrolled);
pulledData.add(e);
}
Binder.restoreCallingIdentity(token);
@@ -2027,7 +2041,13 @@
break;
}
case StatsLog.NUM_FINGERPRINTS_ENROLLED: {
- pullNumFingerprints(tagId, elapsedNanos, wallClockNanos, ret);
+ pullNumBiometricsEnrolled(BiometricsProtoEnums.MODALITY_FINGERPRINT, tagId,
+ elapsedNanos, wallClockNanos, ret);
+ break;
+ }
+ case StatsLog.NUM_FACES_ENROLLED: {
+ pullNumBiometricsEnrolled(BiometricsProtoEnums.MODALITY_FACE, tagId, elapsedNanos,
+ wallClockNanos, ret);
break;
}
case StatsLog.PROC_STATS: {
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index 4adce58..ec62ec7 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
+import android.debug.AdbManagerInternal;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.IBinder;
@@ -42,6 +43,7 @@
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
@@ -49,7 +51,6 @@
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Set;
@@ -85,6 +86,7 @@
break;
case PHASE_BOOT_COMPLETED:
disableAutoSync();
+ configureSettings();
break;
}
super.onBootPhase(phase);
@@ -98,31 +100,19 @@
return;
}
mShouldSetUpTestHarnessMode = true;
+ setUpAdb(testHarnessModeData);
+ setDeviceProvisioned();
+ }
+
+ private void setUpAdb(byte[] testHarnessModeData) {
+ ContentResolver cr = getContext().getContentResolver();
+ // Disable the TTL for ADB keys before enabling ADB
+ Settings.Global.putLong(cr, Settings.Global.ADB_ALLOWED_CONNECTION_TIME, 0);
+
PersistentData persistentData = PersistentData.fromBytes(testHarnessModeData);
SystemProperties.set(TEST_HARNESS_MODE_PROPERTY, persistentData.mEnabled ? "1" : "0");
writeAdbKeysFile(persistentData);
- // Clear out the data block so that we don't revert the ADB keys on every boot.
- getPersistentDataBlock().clearTestHarnessModeData();
-
- ContentResolver cr = getContext().getContentResolver();
- if (Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0) == 0) {
- // Enable ADB
- Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 1);
- } else {
- // ADB is already enabled, we should restart the service so it picks up the new keys
- android.os.SystemService.restart("adbd");
- }
-
- Settings.Global.putInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
- Settings.Global.putInt(
- cr,
- Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
- BatteryManager.BATTERY_PLUGGED_ANY);
- Settings.Global.putInt(cr, Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE, 1);
- Settings.Global.putInt(cr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
-
- setDeviceProvisioned();
}
private void disableAutoSync() {
@@ -134,11 +124,36 @@
.setMasterSyncAutomaticallyAsUser(false, primaryUser.getUserHandle().getIdentifier());
}
+ private void configureSettings() {
+ if (!mShouldSetUpTestHarnessMode) {
+ return;
+ }
+ ContentResolver cr = getContext().getContentResolver();
+
+ Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 1);
+ Settings.Global.putInt(cr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+ Settings.Global.putInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
+ Settings.Global.putInt(
+ cr,
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
+ BatteryManager.BATTERY_PLUGGED_ANY);
+ Settings.Global.putInt(cr, Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE, 1);
+ }
+
private void writeAdbKeysFile(PersistentData persistentData) {
- Path adbKeys = Paths.get("/data/misc/adb/adb_keys");
+ AdbManagerInternal adbManager = LocalServices.getService(AdbManagerInternal.class);
+
+ writeBytesToFile(persistentData.mAdbKeys, adbManager.getAdbKeysFile().toPath());
+ writeBytesToFile(persistentData.mAdbTempKeys, adbManager.getAdbTempKeysFile().toPath());
+
+ // Clear out the data block so that we don't revert the ADB keys on every boot.
+ getPersistentDataBlock().clearTestHarnessModeData();
+ }
+
+ private void writeBytesToFile(byte[] keys, Path adbKeys) {
try {
OutputStream fileOutputStream = Files.newOutputStream(adbKeys);
- fileOutputStream.write(persistentData.mAdbKeys);
+ fileOutputStream.write(keys);
fileOutputStream.close();
Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(adbKeys);
@@ -219,23 +234,22 @@
}
private int handleEnable() {
- Path adbKeys = Paths.get("/data/misc/adb/adb_keys");
- if (!Files.exists(adbKeys)) {
+ AdbManagerInternal adbManager = LocalServices.getService(AdbManagerInternal.class);
+ File adbKeys = adbManager.getAdbKeysFile();
+ File adbTempKeys = adbManager.getAdbTempKeysFile();
+ if (adbKeys == null && adbTempKeys == null) {
// This should only be accessible on eng builds that haven't yet set up ADB keys
getErrPrintWriter()
.println("No ADB keys stored; not enabling test harness mode");
return 1;
}
- try (InputStream inputStream = Files.newInputStream(adbKeys)) {
- long size = Files.size(adbKeys);
- byte[] adbKeysBytes = new byte[(int) size];
- int numBytes = inputStream.read(adbKeysBytes);
- if (numBytes != size) {
- getErrPrintWriter().println("Failed to read all bytes of adb_keys");
- return 1;
- }
- PersistentData persistentData = new PersistentData(true, adbKeysBytes);
+ try {
+ byte[] adbKeysBytes = getBytesFromFile(adbKeys);
+ byte[] adbTempKeysBytes = getBytesFromFile(adbTempKeys);
+
+ PersistentData persistentData =
+ new PersistentData(true, adbKeysBytes, adbTempKeysBytes);
getPersistentDataBlock().setTestHarnessModeData(persistentData.toBytes());
} catch (IOException e) {
Slog.e(TAG, "Failed to store ADB keys.", e);
@@ -252,6 +266,22 @@
return 0;
}
+ private byte[] getBytesFromFile(File file) throws IOException {
+ if (file == null || !file.exists()) {
+ return new byte[0];
+ }
+ Path path = file.toPath();
+ try (InputStream inputStream = Files.newInputStream(path)) {
+ int size = (int) Files.size(path);
+ byte[] bytes = new byte[size];
+ int numBytes = inputStream.read(bytes);
+ if (numBytes != size) {
+ throw new IOException("Failed to read the whole file");
+ }
+ return bytes;
+ }
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -290,15 +320,17 @@
final int mVersion;
final boolean mEnabled;
final byte[] mAdbKeys;
+ final byte[] mAdbTempKeys;
- PersistentData(boolean enabled, byte[] adbKeys) {
- this(VERSION_1, enabled, adbKeys);
+ PersistentData(boolean enabled, byte[] adbKeys, byte[] adbTempKeys) {
+ this(VERSION_1, enabled, adbKeys, adbTempKeys);
}
- PersistentData(int version, boolean enabled, byte[] adbKeys) {
+ PersistentData(int version, boolean enabled, byte[] adbKeys, byte[] adbTempKeys) {
this.mVersion = version;
this.mEnabled = enabled;
this.mAdbKeys = adbKeys;
+ this.mAdbTempKeys = adbTempKeys;
}
static PersistentData fromBytes(byte[] bytes) {
@@ -309,7 +341,10 @@
int adbKeysLength = is.readInt();
byte[] adbKeys = new byte[adbKeysLength];
is.readFully(adbKeys);
- return new PersistentData(version, enabled, adbKeys);
+ int adbTempKeysLength = is.readInt();
+ byte[] adbTempKeys = new byte[adbTempKeysLength];
+ is.readFully(adbTempKeys);
+ return new PersistentData(version, enabled, adbKeys, adbTempKeys);
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -323,6 +358,8 @@
dos.writeBoolean(mEnabled);
dos.writeInt(mAdbKeys.length);
dos.write(mAdbKeys);
+ dos.writeInt(mAdbTempKeys.length);
+ dos.write(mAdbTempKeys);
dos.close();
return os.toByteArray();
} catch (IOException e) {
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 62421ac..f882fde 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -40,6 +40,7 @@
import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
import static com.android.server.am.ActivityDisplayProto.STACKS;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
@@ -575,7 +576,8 @@
final ActivityStack stack = mStacks.get(stackNdx);
final ActivityRecord resumedActivity = stack.getResumedActivity();
if (resumedActivity != null
- && (!stack.shouldBeVisible(resuming) || !stack.isFocusable())) {
+ && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
+ || !stack.isFocusable())) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + resumedActivity);
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ef40648..4faf910 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -109,6 +109,7 @@
import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
@@ -2054,8 +2055,10 @@
* @param activeActivity the activity that is active or just completed pause action. We won't
* resume if this activity is active.
*/
- private boolean shouldResumeActivity(ActivityRecord activeActivity) {
- return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED);
+ @VisibleForTesting
+ boolean shouldResumeActivity(ActivityRecord activeActivity) {
+ return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED)
+ && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE;
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 6f07be8..cc78588 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -108,6 +108,7 @@
import static java.lang.Integer.MAX_VALUE;
+import android.annotation.IntDef;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -223,6 +224,22 @@
// How many activities have to be scheduled to stop to force a stop pass.
private static final int MAX_STOPPING_TO_FORCE = 3;
+ @IntDef(prefix = {"STACK_VISIBILITY"}, value = {
+ STACK_VISIBILITY_VISIBLE,
+ STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ STACK_VISIBILITY_INVISIBLE,
+ })
+ @interface StackVisibility {}
+
+ /** Stack is visible. No other stacks on top that fully or partially occlude it. */
+ static final int STACK_VISIBILITY_VISIBLE = 0;
+
+ /** Stack is partially occluded by other translucent stack(s) on top of it. */
+ static final int STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT = 1;
+
+ /** Stack is completely invisible. */
+ static final int STACK_VISIBILITY_INVISIBLE = 2;
+
@Override
protected int getChildCount() {
return mTaskHistory.size();
@@ -1959,14 +1976,28 @@
* @param starting The currently starting activity or null if there is none.
*/
boolean shouldBeVisible(ActivityRecord starting) {
+ return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
+ }
+
+ /**
+ * Returns true if the stack should be visible.
+ *
+ * @param starting The currently starting activity or null if there is none.
+ */
+ @StackVisibility
+ int getVisibility(ActivityRecord starting) {
if (!isAttached() || mForceHidden) {
- return false;
+ return STACK_VISIBILITY_INVISIBLE;
}
final ActivityDisplay display = getDisplay();
boolean gotSplitScreenStack = false;
boolean gotOpaqueSplitScreenPrimary = false;
boolean gotOpaqueSplitScreenSecondary = false;
+ boolean gotTranslucentFullscreen = false;
+ boolean gotTranslucentSplitScreenPrimary = false;
+ boolean gotTranslucentSplitScreenSecondary = false;
+ boolean shouldBeVisible = true;
final int windowingMode = getWindowingMode();
final boolean isAssistantType = isActivityTypeAssistant();
for (int i = display.getChildCount() - 1; i >= 0; --i) {
@@ -1975,8 +2006,9 @@
if (other == this) {
// Should be visible if there is no other stack occluding it, unless it doesn't
// have any running activities, not starting one and not home stack.
- return hasRunningActivities || isInStackLocked(starting) != null
+ shouldBeVisible = hasRunningActivities || isInStackLocked(starting) != null
|| isActivityTypeHome();
+ break;
}
if (!hasRunningActivities) {
@@ -1996,51 +2028,79 @@
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
if (activityType == ACTIVITY_TYPE_HOME
|| (activityType == ACTIVITY_TYPE_ASSISTANT
- && mWindowManager.getRecentsAnimationController() != null)) {
- return true;
+ && mWindowManager.getRecentsAnimationController() != null)) {
+ break;
}
}
if (other.isStackTranslucent(starting)) {
// Can be visible behind a translucent fullscreen stack.
+ gotTranslucentFullscreen = true;
continue;
}
- return false;
+ return STACK_VISIBILITY_INVISIBLE;
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& !gotOpaqueSplitScreenPrimary) {
gotSplitScreenStack = true;
- gotOpaqueSplitScreenPrimary =
- !other.isStackTranslucent(starting);
+ gotTranslucentSplitScreenPrimary = other.isStackTranslucent(starting);
+ gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& gotOpaqueSplitScreenPrimary) {
// Can not be visible behind another opaque stack in split-screen-primary mode.
- return false;
+ return STACK_VISIBILITY_INVISIBLE;
}
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& !gotOpaqueSplitScreenSecondary) {
gotSplitScreenStack = true;
- gotOpaqueSplitScreenSecondary =
- !other.isStackTranslucent(starting);
+ gotTranslucentSplitScreenSecondary = other.isStackTranslucent(starting);
+ gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& gotOpaqueSplitScreenSecondary) {
// Can not be visible behind another opaque stack in split-screen-secondary mode.
- return false;
+ return STACK_VISIBILITY_INVISIBLE;
}
}
if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
// Can not be visible if we are in split-screen windowing mode and both halves of
// the screen are opaque.
- return false;
+ return STACK_VISIBILITY_INVISIBLE;
}
if (isAssistantType && gotSplitScreenStack) {
// Assistant stack can't be visible behind split-screen. In addition to this not
// making sense, it also works around an issue here we boost the z-order of the
// assistant window surfaces in window manager whenever it is visible.
- return false;
+ return STACK_VISIBILITY_INVISIBLE;
}
}
- // Well, nothing is stopping you from being visible...
- return true;
+ if (!shouldBeVisible) {
+ return STACK_VISIBILITY_INVISIBLE;
+ }
+
+ // Handle cases when there can be a translucent split-screen stack on top.
+ switch (windowingMode) {
+ case WINDOWING_MODE_FULLSCREEN:
+ if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) {
+ // At least one of the split-screen stacks that covers this one is translucent.
+ return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
+ }
+ break;
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
+ if (gotTranslucentSplitScreenPrimary) {
+ // Covered by translucent primary split-screen on top.
+ return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
+ }
+ break;
+ case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
+ if (gotTranslucentSplitScreenSecondary) {
+ // Covered by translucent secondary split-screen on top.
+ return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
+ }
+ break;
+ }
+
+ // Lastly - check if there is a translucent fullscreen stack on top.
+ return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
+ : STACK_VISIBILITY_VISIBLE;
}
final int rankTaskLayers(int baseLayer) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 7aa3481..875fc4e 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1383,6 +1383,7 @@
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
+ .setAllowBackgroundActivityStart(true)
.execute();
}
@@ -1398,6 +1399,7 @@
.setResolvedType(resolvedType)
.setActivityOptions(bOptions)
.setMayWait(userId)
+ .setAllowBackgroundActivityStart(true)
.execute();
}
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 0e14e46..5519729 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -143,7 +143,7 @@
void destroy() {
mSurfaceAnimator.cancelAnimation();
- mSurfaceControl.remove();
+ getPendingTransaction().remove(mSurfaceControl);
}
/**
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2cc85e2..bcf6aba 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1275,7 +1275,19 @@
void onDisplayChanged(DisplayContent dc) {
DisplayContent prevDc = mDisplayContent;
super.onDisplayChanged(dc);
- if (prevDc != null && prevDc.mFocusedApp == this) {
+ if (prevDc == null) {
+ return;
+ }
+ if (prevDc.mChangingApps.contains(this)) {
+ // This gets called *after* the AppWindowToken has been reparented to the new display.
+ // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
+ // so this token is now "frozen" while waiting for the animation to start on prevDc
+ // (which will be cancelled since the window is no-longer a child). However, since this
+ // is no longer a child of prevDc, this won't be notified of the cancelled animation,
+ // so we need to cancel the change transition here.
+ clearChangeLeash(getPendingTransaction(), true /* cancel */);
+ }
+ if (prevDc.mFocusedApp == this) {
prevDc.setFocusedApp(null);
final TaskStack stack = dc.getTopStack();
if (stack != null) {
@@ -1584,7 +1596,10 @@
}
private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
- if (!isVisible() || getDisplayContent().mAppTransition.isTransitionSet()) {
+ if (mWmService.mDisableTransitionAnimation
+ || !isVisible()
+ || getDisplayContent().mAppTransition.isTransitionSet()
+ || getSurfaceControl() == null) {
return false;
}
// Only do an animation into and out-of freeform mode for now. Other mode
@@ -2561,9 +2576,7 @@
return;
} else if (mTransitChangeLeash != null) {
// unparent mTransitChangeLeash for clean-up
- t.hide(mTransitChangeLeash);
- t.reparent(mTransitChangeLeash, null);
- mTransitChangeLeash = null;
+ clearChangeLeash(t, false /* cancel */);
}
if (mAnimatingAppWindowTokenRegistry != null) {
@@ -2659,15 +2672,36 @@
return super.isSelfAnimating();
}
+ /**
+ * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
+ * to another leash.
+ */
+ private void clearChangeLeash(Transaction t, boolean cancel) {
+ if (mTransitChangeLeash == null) {
+ return;
+ }
+ if (cancel) {
+ clearThumbnail();
+ SurfaceControl sc = getSurfaceControl();
+ SurfaceControl parentSc = getParentSurfaceControl();
+ // Don't reparent if surface is getting destroyed
+ if (parentSc != null && sc != null) {
+ t.reparent(sc, getParentSurfaceControl());
+ }
+ }
+ t.hide(mTransitChangeLeash);
+ t.reparent(mTransitChangeLeash, null);
+ mTransitChangeLeash = null;
+ if (cancel) {
+ onAnimationLeashDestroyed(t);
+ }
+ }
+
@Override
void cancelAnimation() {
cancelAnimationOnly();
clearThumbnail();
- if (mTransitChangeLeash != null) {
- getPendingTransaction().hide(mTransitChangeLeash);
- getPendingTransaction().reparent(mTransitChangeLeash, null);
- mTransitChangeLeash = null;
- }
+ clearChangeLeash(getPendingTransaction(), true /* cancel */);
}
/**
@@ -3003,7 +3037,9 @@
void removeFromPendingTransition() {
if (isWaitingForTransitionStart() && mDisplayContent != null) {
mDisplayContent.mOpeningApps.remove(this);
- mDisplayContent.mChangingApps.remove(this);
+ if (mDisplayContent.mChangingApps.remove(this)) {
+ clearChangeLeash(getPendingTransaction(), true /* cancel */);
+ }
mDisplayContent.mClosingApps.remove(this);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 928b57c..5cfc20b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -23,7 +23,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -38,6 +37,7 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
@@ -138,6 +138,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -172,6 +173,7 @@
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
import android.view.View;
+import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
@@ -3251,6 +3253,36 @@
mInputMethodTargetWaitingAnim = targetWaitingAnim;
assignWindowLayers(false /* setLayoutNeeded */);
mInsetsStateController.onImeTargetChanged(target);
+ updateImeParent();
+ }
+
+ private void updateImeParent() {
+ if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE) {
+ return;
+ }
+ final SurfaceControl newParent = computeImeParent();
+ if (newParent != null) {
+ mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent);
+ scheduleAnimation();
+ }
+ }
+
+ /**
+ * Computes the window the IME should be attached to.
+ */
+ @VisibleForTesting
+ SurfaceControl computeImeParent() {
+
+ // Attach it to app if the target is part of an app and such app is covering the entire
+ // screen. If it's not covering the entire screen the IME might extend beyond the apps
+ // bounds.
+ if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null &&
+ mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ return mInputMethodTarget.mAppToken.getSurfaceControl();
+ }
+
+ // Otherwise, we just attach it to the display.
+ return mWindowingLayer;
}
boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
@@ -4885,6 +4917,11 @@
.reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
}
+ @VisibleForTesting
+ SurfaceControl getWindowingLayer() {
+ return mWindowingLayer;
+ }
+
/**
* Create a portal window handle for input. This window transports any touch to the display
* indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
@@ -4909,4 +4946,19 @@
portalWindowHandle.portalToDisplayId = mDisplayId;
return portalWindowHandle;
}
+
+ /**
+ * @see IWindowManager#setForwardedInsets
+ */
+ public void setForwardedInsets(Insets insets) {
+ if (insets == null) {
+ insets = Insets.NONE;
+ }
+ if (mDisplayPolicy.getForwardedInsets().equals(insets)) {
+ return;
+ }
+ mDisplayPolicy.setForwardedInsets(insets);
+ setLayoutNeeded();
+ mWmService.mWindowPlacerLocked.requestTraversal();
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index bbf115f..2ee30ac 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -27,6 +27,7 @@
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
@@ -103,6 +104,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.localLOGV;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityThread;
@@ -110,6 +112,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.graphics.Insets;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.hardware.power.V1_0.PowerHint;
@@ -134,6 +137,7 @@
import android.view.PointerIcon;
import android.view.Surface;
import android.view.View;
+import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
@@ -339,6 +343,16 @@
private InputConsumer mInputConsumer = null;
+ /**
+ * The area covered by system windows which belong to another display. Forwarded insets is set
+ * in case this is a virtual display, this is displayed on another display that has insets, and
+ * the bounds of this display is overlapping with the insets of the host display (e.g. IME is
+ * displayed on the host display, and it covers a part of this virtual display.)
+ * The forwarded insets is used to compute display frames of this virtual display, which will
+ * be then used to layout windows in the virtual display.
+ */
+ @NonNull private Insets mForwardedInsets = Insets.NONE;
+
// -------- PolicyHandler --------
private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 1;
private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
@@ -1362,6 +1376,15 @@
displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top,
displayFrames.mStable.top);
}
+
+ // In case this is a virtual display, and the host display has insets that overlap this
+ // virtual display, apply the insets of the overlapped area onto the current and content
+ // frame of this virtual display. This let us layout windows in the virtual display as
+ // expected when the window needs to avoid overlap with the system windows.
+ // TODO: Generalize the forwarded insets, so that we can handle system windows other than
+ // IME.
+ displayFrames.mCurrent.inset(mForwardedInsets);
+ displayFrames.mContent.inset(mForwardedInsets);
}
private void layoutScreenDecorWindows(DisplayFrames displayFrames) {
@@ -1900,7 +1923,10 @@
if (win.isVoiceInteraction()) {
cf.set(displayFrames.mVoiceContent);
} else {
- if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
+ // IME Insets are handled on the client for ADJUST_RESIZE in the new
+ // insets world
+ if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
+ || adjust != SOFT_INPUT_ADJUST_RESIZE) {
cf.set(displayFrames.mDock);
} else {
cf.set(displayFrames.mContent);
@@ -1991,7 +2017,11 @@
of.set(displayFrames.mRestricted);
df.set(displayFrames.mRestricted);
pf.set(displayFrames.mRestricted);
- if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
+
+ // IME Insets are handled on the client for ADJUST_RESIZE in the new insets
+ // world
+ if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
+ || adjust != SOFT_INPUT_ADJUST_RESIZE) {
cf.set(displayFrames.mDock);
} else {
cf.set(displayFrames.mContent);
@@ -2718,6 +2748,18 @@
}
}
+ /**
+ * @see IWindowManager#setForwardedInsets
+ */
+ public void setForwardedInsets(@NonNull Insets forwardedInsets) {
+ mForwardedInsets = forwardedInsets;
+ }
+
+ @NonNull
+ public Insets getForwardedInsets() {
+ return mForwardedInsets;
+ }
+
@NavigationBarPosition
int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
if (navigationBarCanMove() && displayWidth > displayHeight) {
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index afae9c4..a1b52f4 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -112,6 +112,7 @@
* Called when a layout pass has occurred.
*/
void onPostLayout() {
+ mState.setDisplayFrame(mDisplayContent.getBounds());
for (int i = mControllers.size() - 1; i>= 0; i--) {
mControllers.valueAt(i).onPostLayout();
}
diff --git a/services/core/java/com/android/server/wm/TEST_MAPPING b/services/core/java/com/android/server/wm/TEST_MAPPING
index bbe5424..b2e8bbe 100644
--- a/services/core/java/com/android/server/wm/TEST_MAPPING
+++ b/services/core/java/com/android/server/wm/TEST_MAPPING
@@ -1,34 +1,4 @@
{
- "presubmit": [
- {
- "name": "FrameworksServicesTests",
- "options": [
- {
- "include-filter": "com.android.server.wm."
- },
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- }
- ]
- },
- {
- "name": "WmTests",
- "options": [
- {
- "include-filter": "com.android.server.wm."
- },
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- }
- ]
- }
- ],
"postsubmit": [
{
"name": "CtsWindowManagerDeviceTestCases"
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3bb6608..00105be 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -134,6 +134,7 @@
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Bitmap;
+import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
@@ -187,6 +188,7 @@
import android.util.TimeUtils;
import android.util.TypedValue;
import android.util.proto.ProtoOutputStream;
+import android.view.Choreographer;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
@@ -842,7 +844,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
synchronized (mGlobalLock) {
SurfaceControl.closeTransaction();
- traceStateLocked(where);
+ mWindowTracing.logState(where);
}
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -966,7 +968,8 @@
mWindowPlacerLocked = new WindowSurfacePlacer(this);
mTaskSnapshotController = new TaskSnapshotController(this);
- mWindowTracing = WindowTracing.createDefaultAndStartLooper(context);
+ mWindowTracing = WindowTracing.createDefaultAndStartLooper(this,
+ Choreographer.getInstance());
LocalServices.addService(WindowManagerPolicy.class, mPolicy);
@@ -5764,17 +5767,6 @@
proto.write(LAST_ORIENTATION, defaultDisplayContent.getLastOrientation());
}
- void traceStateLocked(String where) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "traceStateLocked");
- try {
- mWindowTracing.traceStateLocked(where, this);
- } catch (Exception e) {
- Log.wtf(TAG, "Exception while tracing state", e);
- } finally {
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- }
- }
-
private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
ArrayList<WindowState> windows) {
pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
@@ -6438,6 +6430,23 @@
}
}
+ @Override
+ public void setForwardedInsets(int displayId, Insets insets) throws RemoteException {
+ synchronized (mGlobalLock) {
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
+ if (dc == null) {
+ return;
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int displayOwnerUid = dc.getDisplay().getOwnerUid();
+ if (callingUid != displayOwnerUid) {
+ throw new SecurityException(
+ "Only owner of the display can set ForwardedInsets to it.");
+ }
+ dc.setForwardedInsets(insets);
+ }
+ }
+
void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
mTmpRect3.set(display);
mTmpRect3.inset(insets);
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index 8b1ffa8..abc474d 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -24,12 +24,14 @@
import static com.android.server.wm.WindowManagerTraceProto.WINDOW_MANAGER_SERVICE;
import android.annotation.Nullable;
-import android.content.Context;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.Trace;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
+import android.view.Choreographer;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
import java.io.IOException;
@@ -48,6 +50,10 @@
private static final int WINDOW_TRACE_BUFFER_SIZE = 512 * 1024;
private static final String TAG = "WindowTracing";
+ private final WindowManagerService mService;
+ private final Choreographer mChoreographer;
+ private final WindowManagerGlobalLock mGlobalLock;
+
private final Object mLock = new Object();
private final WindowTraceBuffer.Builder mBufferBuilder;
@@ -57,11 +63,24 @@
private boolean mContinuousMode;
private boolean mEnabled;
private volatile boolean mEnabledLockFree;
+ private boolean mScheduled;
+ private Choreographer.FrameCallback mFrameCallback = (frameTimeNanos) ->
+ log("onFrame" /* where */);
- WindowTracing(File file) {
+ private WindowTracing(File file, WindowManagerService service, Choreographer choreographer) {
+ this(file, service, choreographer, service.mGlobalLock);
+ }
+
+ @VisibleForTesting
+ WindowTracing(File file, WindowManagerService service, Choreographer choreographer,
+ WindowManagerGlobalLock globalLock) {
mBufferBuilder = new WindowTraceBuffer.Builder()
.setTraceFile(file)
.setBufferCapacity(WINDOW_TRACE_BUFFER_SIZE);
+
+ mChoreographer = choreographer;
+ mService = service;
+ mGlobalLock = globalLock;
}
void startTrace(@Nullable PrintWriter pw) throws IOException {
@@ -111,7 +130,8 @@
}
}
- private void setContinuousMode(boolean continuous, PrintWriter pw) {
+ @VisibleForTesting
+ void setContinuousMode(boolean continuous, PrintWriter pw) {
logAndPrintln(pw, "Setting window tracing continuous mode to " + continuous);
if (mEnabled) {
@@ -123,21 +143,14 @@
WindowTraceLogLevel.TRIM;
}
- private void appendTraceEntry(ProtoOutputStream proto) {
- if (!mEnabledLockFree) {
- return;
- }
-
- mTraceBuffer.add(proto);
- }
-
boolean isEnabled() {
return mEnabledLockFree;
}
- static WindowTracing createDefaultAndStartLooper(Context context) {
+ static WindowTracing createDefaultAndStartLooper(WindowManagerService service,
+ Choreographer choreographer) {
File file = new File("/data/misc/wmtrace/wm_trace.pb");
- return new WindowTracing(file);
+ return new WindowTracing(file, service, choreographer);
}
int onShellCommand(ShellCommand shell) {
@@ -164,28 +177,65 @@
}
}
- void traceStateLocked(String where, WindowManagerService service) {
+ /**
+ * If tracing is enabled, log the current state or schedule the next frame to be logged,
+ * according to {@link #mContinuousMode}.
+ *
+ * @param where Logging point descriptor
+ */
+ void logState(String where) {
if (!isEnabled()) {
return;
}
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToBufferLocked");
- try {
- ProtoOutputStream os = new ProtoOutputStream();
- long tokenOuter = os.start(ENTRY);
- os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
- os.write(WHERE, where);
+ if (mContinuousMode) {
+ schedule();
+ } else {
+ log(where);
+ }
+ }
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked");
- try {
- long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
- service.writeToProtoLocked(os, mWindowTraceLogLevel);
- os.end(tokenInner);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ /**
+ * Schedule the log to trace the next frame
+ */
+ private void schedule() {
+ if (mScheduled) {
+ return;
+ }
+
+ mScheduled = true;
+ mChoreographer.postFrameCallback(mFrameCallback);
+ }
+
+ /**
+ * Write the current frame to the buffer
+ *
+ * @param where Logging point descriptor
+ */
+ private void log(String where) {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "traceStateLocked");
+ try {
+ synchronized (mGlobalLock) {
+ ProtoOutputStream os = new ProtoOutputStream();
+ long tokenOuter = os.start(ENTRY);
+ os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
+ os.write(WHERE, where);
+
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked");
+ try {
+ long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
+ mService.writeToProtoLocked(os, mWindowTraceLogLevel);
+ os.end(tokenInner);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
+ os.end(tokenOuter);
+ mTraceBuffer.add(os);
+
+ mScheduled = false;
}
- os.end(tokenOuter);
- appendTraceEntry(os);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Exception while tracing state", e);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 33317b5..c18e98b 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -373,6 +373,9 @@
mInputManager->getReader()->dump(dump);
dump += "\n";
+ mInputManager->getClassifier()->dump(dump);
+ dump += "\n";
+
mInputManager->getDispatcher()->dump(dump);
dump += "\n";
}
diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp
index bf96f9a..6cd9f2c 100644
--- a/services/core/jni/com_android_server_security_VerityUtils.cpp
+++ b/services/core/jni/com_android_server_security_VerityUtils.cpp
@@ -122,7 +122,7 @@
}
~JavaByteArrayHolder() {
- LOG_ALWAYS_FATAL_IF(mElements == nullptr, "Elements are not released");
+ LOG_ALWAYS_FATAL_IF(mElements != nullptr, "Elements are not released");
}
private:
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1155f49..e30acf7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -12790,10 +12790,6 @@
}
}
- // TODO(b/22388012): When backup is available for secondary users and profiles, consider
- // whether there are any privacy/security implications of enabling the backup service here
- // if there are other users or profiles unmanaged or managed by a different entity (i.e. not
- // affiliated).
@Override
public void setBackupServiceEnabled(ComponentName admin, boolean enabled) {
if (!mHasFeature) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ab30cda..a6017f2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -64,6 +64,7 @@
import android.util.Slog;
import android.util.TimingsTraceLog;
import android.view.WindowManager;
+import android.view.contentcapture.ContentCaptureManager;
import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.R;
@@ -2214,33 +2215,30 @@
}
private void startContentCaptureService(@NonNull Context context) {
- // Check if it was explicitly enabled by DeviceConfig
- final String settings = DeviceConfig.getProperty(DeviceConfig.ContentCapture.NAMESPACE,
- DeviceConfig.ContentCapture.PROPERTY_CONTENTCAPTURE_ENABLED);
- if (settings == null) {
- // Better be safe than sorry...
- Slog.d(TAG, "ContentCaptureService disabled because its not set by OEM");
- return;
- }
- switch (settings) {
- case "always":
- // Should be used only during development
+ // First check if it was explicitly enabled by DeviceConfig
+ boolean explicitlySupported = false;
+ String settings = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
+ if (settings != null && !settings.equalsIgnoreCase("default")) {
+ explicitlySupported = Boolean.parseBoolean(settings);
+ if (explicitlySupported) {
Slog.d(TAG, "ContentCaptureService explicitly enabled by DeviceConfig");
- break;
- case "default":
- // Default case: check if OEM overlaid the resource that defines the service.
- final String serviceName = context.getString(
- com.android.internal.R.string.config_defaultContentCaptureService);
- if (TextUtils.isEmpty(serviceName)) {
- Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
- return;
- }
- break;
- default:
- // Kill switch for OEMs
- Slog.d(TAG, "ContentCaptureService disabled because its set to: " + settings);
+ } else {
+ Slog.d(TAG, "ContentCaptureService explicitly disabled by DeviceConfig");
return;
+ }
}
+
+ // Then check if OEM overlaid the resource that defines the service.
+ if (!explicitlySupported) {
+ final String serviceName = context
+ .getString(com.android.internal.R.string.config_defaultContentCaptureService);
+ if (TextUtils.isEmpty(serviceName)) {
+ Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
+ return;
+ }
+ }
+
traceBeginAndSlog("StartContentCaptureService");
mSystemServiceManager.startService(CONTENT_CAPTURE_MANAGER_SERVICE_CLASS);
traceEnd();
diff --git a/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java b/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
index 2f8e545..63015be6 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
@@ -147,10 +147,10 @@
KEY_USE_COMPACTION, "true", false);
DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
KEY_COMPACT_ACTION_1,
- Integer.toString((AppCompactor.DEFAULT_COMPACT_ACTION_1 + 1 % 3) + 1), false);
+ Integer.toString((AppCompactor.DEFAULT_COMPACT_ACTION_1 + 1 % 4) + 1), false);
DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
KEY_COMPACT_ACTION_2,
- Integer.toString((AppCompactor.DEFAULT_COMPACT_ACTION_2 + 1 % 3) + 1), false);
+ Integer.toString((AppCompactor.DEFAULT_COMPACT_ACTION_2 + 1 % 4) + 1), false);
DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
KEY_COMPACT_THROTTLE_1,
Long.toString(AppCompactor.DEFAULT_COMPACT_THROTTLE_1 + 1), false);
@@ -173,9 +173,9 @@
assertThat(mCompactorUnderTest.mCompactionThread.isAlive(), is(true));
assertThat(mCompactorUnderTest.mCompactActionSome,
- is(compactActionIntToString((AppCompactor.DEFAULT_COMPACT_ACTION_1 + 1 % 3) + 1)));
+ is(compactActionIntToString((AppCompactor.DEFAULT_COMPACT_ACTION_1 + 1 % 4) + 1)));
assertThat(mCompactorUnderTest.mCompactActionFull,
- is(compactActionIntToString((AppCompactor.DEFAULT_COMPACT_ACTION_2 + 1 % 3) + 1)));
+ is(compactActionIntToString((AppCompactor.DEFAULT_COMPACT_ACTION_2 + 1 % 4) + 1)));
assertThat(mCompactorUnderTest.mCompactThrottleSomeSome,
is(AppCompactor.DEFAULT_COMPACT_THROTTLE_1 + 1));
assertThat(mCompactorUnderTest.mCompactThrottleSomeFull,
@@ -233,13 +233,13 @@
// When we override new values for the compaction action with reasonable values...
- // There are three possible values for compactAction[Some|Full].
- for (int i = 1; i < 4; i++) {
+ // There are four possible values for compactAction[Some|Full].
+ for (int i = 1; i < 5; i++) {
mCountDown = new CountDownLatch(2);
- int expectedSome = (mCompactorUnderTest.DEFAULT_COMPACT_ACTION_1 + i) % 3 + 1;
+ int expectedSome = (mCompactorUnderTest.DEFAULT_COMPACT_ACTION_1 + i) % 4 + 1;
DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
KEY_COMPACT_ACTION_1, Integer.toString(expectedSome), false);
- int expectedFull = (mCompactorUnderTest.DEFAULT_COMPACT_ACTION_2 + i) % 3 + 1;
+ int expectedFull = (mCompactorUnderTest.DEFAULT_COMPACT_ACTION_2 + i) % 4 + 1;
DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
KEY_COMPACT_ACTION_2, Integer.toString(expectedFull), false);
assertThat(mCountDown.await(5, TimeUnit.SECONDS), is(true));
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
index 13436e7..821d97a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
@@ -24,14 +24,21 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.testng.Assert.expectThrows;
import android.app.KeyguardManager;
import android.content.Context;
+import android.os.RemoteException;
+import android.security.GateKeeper;
+import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
+import android.service.gatekeeper.IGateKeeperService;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -53,6 +60,8 @@
import java.security.UnrecoverableKeyException;
import java.util.List;
+import javax.crypto.KeyGenerator;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class PlatformKeyManagerTest {
@@ -60,10 +69,15 @@
private static final String DATABASE_FILE_NAME = "recoverablekeystore.db";
private static final int USER_AUTHENTICATION_VALIDITY_DURATION_SECONDS = 15;
private static final int USER_ID_FIXTURE = 42;
+ private static final long USER_SID = 4200L;
+ private static final String KEY_ALGORITHM = "AES";
+ private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+ private static final String TESTING_KEYSTORE_KEY_ALIAS = "testing-key-store-key-alias";
@Mock private Context mContext;
@Mock private KeyStoreProxy mKeyStoreProxy;
@Mock private KeyguardManager mKeyguardManager;
+ @Mock private IGateKeeperService mGateKeeperService;
@Captor private ArgumentCaptor<KeyStore.ProtectionParameter> mProtectionParameterCaptor;
@Captor private ArgumentCaptor<KeyStore.Entry> mEntryArgumentCaptor;
@@ -74,18 +88,19 @@
private PlatformKeyManager mPlatformKeyManager;
@Before
- public void setUp() {
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Context context = InstrumentationRegistry.getTargetContext();
mDatabaseFile = context.getDatabasePath(DATABASE_FILE_NAME);
mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context);
- mPlatformKeyManager = new PlatformKeyManager(
- mContext, mKeyStoreProxy, mRecoverableKeyStoreDb);
+ mPlatformKeyManager = new PlatformKeyManagerTestable(
+ mContext, mKeyStoreProxy, mRecoverableKeyStoreDb, mGateKeeperService);
when(mContext.getSystemService(anyString())).thenReturn(mKeyguardManager);
when(mContext.getSystemServiceName(any())).thenReturn("test");
when(mKeyguardManager.isDeviceSecure(USER_ID_FIXTURE)).thenReturn(true);
+ when(mGateKeeperService.getSecureUserId(USER_ID_FIXTURE)).thenReturn(USER_SID);
}
@After
@@ -192,11 +207,36 @@
mPlatformKeyManager.init(USER_ID_FIXTURE);
assertEquals(
- USER_ID_FIXTURE,
+ USER_SID,
getDecryptKeyProtection().getBoundToSpecificSecureUserId());
}
@Test
+ public void init_doesNotCreateDecryptKeyIfNoSid() throws Exception {
+ when(mGateKeeperService.getSecureUserId(USER_ID_FIXTURE))
+ .thenReturn(GateKeeper.INVALID_SECURE_USER_ID);
+
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
+
+ verify(mKeyStoreProxy, never()).setEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
+ any(),
+ any());
+ }
+
+ @Test
+ public void init_doesNotCreateDecryptKeyOnGateKeeperException() throws Exception {
+ when(mGateKeeperService.getSecureUserId(USER_ID_FIXTURE)).thenThrow(new RemoteException());
+
+ expectThrows(RemoteException.class, () -> mPlatformKeyManager.init(USER_ID_FIXTURE));
+
+ verify(mKeyStoreProxy, never()).setEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
+ any(),
+ any());
+ }
+
+ @Test
public void init_createsBothKeysWithSameMaterial() throws Exception {
mPlatformKeyManager.init(USER_ID_FIXTURE);
@@ -259,6 +299,9 @@
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(true);
+ when(mKeyStoreProxy.getKey(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
+ any())).thenReturn(generateAndroidKeyStoreKey());
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
@@ -281,6 +324,9 @@
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true);
+ when(mKeyStoreProxy.getKey(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
+ any())).thenReturn(generateAndroidKeyStoreKey());
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
@@ -352,6 +398,9 @@
doThrow(new UnrecoverableKeyException()).when(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
any());
+ when(mKeyStoreProxy.getKey(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
+ any())).thenReturn(generateAndroidKeyStoreKey());
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
@@ -536,4 +585,34 @@
mProtectionParameterCaptor.capture());
return (KeyProtection) mProtectionParameterCaptor.getValue();
}
+
+ private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(
+ KEY_ALGORITHM,
+ ANDROID_KEY_STORE_PROVIDER);
+ keyGenerator.init(new KeyGenParameterSpec.Builder(TESTING_KEYSTORE_KEY_ALIAS,
+ KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build());
+ return (AndroidKeyStoreSecretKey) keyGenerator.generateKey();
+ }
+
+ class PlatformKeyManagerTestable extends PlatformKeyManager {
+ private IGateKeeperService mGateKeeperService;
+
+ PlatformKeyManagerTestable(
+ Context context,
+ KeyStoreProxy keyStoreProxy,
+ RecoverableKeyStoreDb database,
+ IGateKeeperService gateKeeperService) {
+ super(context, keyStoreProxy, database);
+ mGateKeeperService = gateKeeperService;
+ }
+
+ @Override
+ IGateKeeperService getGateKeeperService() {
+ return mGateKeeperService;
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
index 4e43d00..8caa39d 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
@@ -1035,6 +1035,15 @@
0L, group.getUsageRemaining());
}
+ /** Verify that a limit of 0 is allowed for the special case of re-registering an observer. */
+ @Test
+ public void testAppUsageLimitObserver_ZeroTimeLimitIsAllowed() {
+ addAppUsageLimitObserver(OBS_ID1, GROUP1, 0);
+ AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
+ assertNotNull("Observer wasn't added", group);
+ assertEquals("Usage remaining was not 0.", 0, group.getUsageRemaining());
+ }
+
private void startUsage(String packageName) {
mController.noteUsageStart(packageName, USER_ID);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 192915f..4073ff1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -24,6 +24,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
@@ -34,6 +35,9 @@
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -381,6 +385,21 @@
}
@Test
+ public void testShouldResume_stackVisibility() {
+ mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
+ spyOn(mStack);
+
+ doReturn(STACK_VISIBILITY_VISIBLE).when(mStack).getVisibility(null);
+ assertEquals(true, mActivity.shouldResumeActivity(null /* activeActivity */));
+
+ doReturn(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT).when(mStack).getVisibility(null);
+ assertEquals(false, mActivity.shouldResumeActivity(null /* activeActivity */));
+
+ doReturn(STACK_VISIBILITY_INVISIBLE).when(mStack).getVisibility(null);
+ assertEquals(false, mActivity.shouldResumeActivity(null /* activeActivity */));
+ }
+
+ @Test
public void testPushConfigurationWhenLaunchTaskBehind() throws Exception {
mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 986943a..822700f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -37,6 +37,9 @@
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
@@ -321,12 +324,23 @@
assertFalse(homeStack.shouldBeVisible(null /* starting */));
assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE, homeStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenPrimary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenSecondary.getVisibility(null /* starting */));
// Home stack should be visible if one of the halves of split-screen is translucent.
splitScreenPrimary.setIsTranslucent(true);
assertTrue(homeStack.shouldBeVisible(null /* starting */));
assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ homeStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenPrimary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenSecondary.getVisibility(null /* starting */));
final TestActivityStack splitScreenSecondary2 =
createStackForShouldBeVisibleTest(mDefaultDisplay,
@@ -336,12 +350,20 @@
splitScreenSecondary2.setIsTranslucent(false);
assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenSecondary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenSecondary2.getVisibility(null /* starting */));
// First split-screen secondary should be visible behind another translucent split-screen
// secondary.
splitScreenSecondary2.setIsTranslucent(true);
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ splitScreenSecondary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenSecondary2.getVisibility(null /* starting */));
final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
@@ -352,6 +374,14 @@
assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
assertFalse(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ assistantStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenPrimary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenSecondary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenSecondary2.getVisibility(null /* starting */));
// Split-screen stacks should be visible behind a translucent fullscreen stack.
assistantStack.setIsTranslucent(true);
@@ -359,6 +389,14 @@
assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ assistantStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ splitScreenPrimary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ splitScreenSecondary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ splitScreenSecondary2.getVisibility(null /* starting */));
// Assistant stack shouldn't be visible behind translucent split-screen stack
assistantStack.setIsTranslucent(false);
@@ -369,6 +407,113 @@
assertFalse(assistantStack.shouldBeVisible(null /* starting */));
assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ assistantStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenPrimary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ splitScreenSecondary.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ splitScreenSecondary2.getVisibility(null /* starting */));
+ }
+
+ @Test
+ public void testGetVisibility_FullscreenBehindTranslucent() {
+ final TestActivityStack bottomStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ false /* translucent */);
+ final TestActivityStack translucentStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ true /* translucent */);
+
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ bottomStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ translucentStack.getVisibility(null /* starting */));
+ }
+
+ @Test
+ public void testGetVisibility_FullscreenBehindTranslucentAndOpaque() {
+ final TestActivityStack bottomStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ false /* translucent */);
+ final TestActivityStack translucentStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ true /* translucent */);
+ final TestActivityStack opaqueStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ false /* translucent */);
+
+ assertEquals(STACK_VISIBILITY_INVISIBLE, bottomStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ translucentStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE, opaqueStack.getVisibility(null /* starting */));
+ }
+
+ @Test
+ public void testGetVisibility_FullscreenBehindOpaqueAndTranslucent() {
+ final TestActivityStack bottomStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ false /* translucent */);
+ final TestActivityStack opaqueStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ false /* translucent */);
+ final TestActivityStack translucentStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ true /* translucent */);
+
+ assertEquals(STACK_VISIBILITY_INVISIBLE, bottomStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ opaqueStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ translucentStack.getVisibility(null /* starting */));
+ }
+
+ @Test
+ public void testGetVisibility_FullscreenTranslucentBehindTranslucent() {
+ final TestActivityStack bottomTranslucentStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ true /* translucent */);
+ final TestActivityStack translucentStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ true /* translucent */);
+
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ bottomTranslucentStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ translucentStack.getVisibility(null /* starting */));
+ }
+
+ @Test
+ public void testGetVisibility_FullscreenTranslucentBehindOpaque() {
+ final TestActivityStack bottomTranslucentStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ true /* translucent */);
+ final TestActivityStack opaqueStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ false /* translucent */);
+
+ assertEquals(STACK_VISIBILITY_INVISIBLE,
+ bottomTranslucentStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE, opaqueStack.getVisibility(null /* starting */));
+ }
+
+ @Test
+ public void testGetVisibility_FullscreenBehindTranslucentAndPip() {
+ final TestActivityStack bottomStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ false /* translucent */);
+ final TestActivityStack translucentStack =
+ createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+ true /* translucent */);
+ final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+ assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+ bottomStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE,
+ translucentStack.getVisibility(null /* starting */));
+ assertEquals(STACK_VISIBILITY_VISIBLE, pinnedStack.getVisibility(null /* starting */));
}
@Test
@@ -628,6 +773,14 @@
assertFalse(assistantStack.shouldBeVisible(null /* starting */));
}
+ private TestActivityStack createStandardStackForVisibilityTest(int windowingMode,
+ boolean translucent) {
+ final TestActivityStack stack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ windowingMode, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ stack.setIsTranslucent(translucent);
+ return stack;
+ }
+
@SuppressWarnings("TypeParameterUnusedInFormals")
private <T extends ActivityStack> T createStackForShouldBeVisibleTest(
ActivityDisplay display, int windowingMode, int activityType, boolean onTop) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index e27dd94..21a4e84 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -72,8 +72,10 @@
import com.android.server.appop.AppOpsService;
import com.android.server.firewall.IntentFirewall;
import com.android.server.uri.UriGrantsManagerInternal;
+import com.android.server.wm.utils.MockTracker;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
@@ -88,6 +90,8 @@
class ActivityTestsBase {
private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
+ private static MockTracker sMockTracker;
+
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
@@ -107,9 +111,17 @@
@BeforeClass
public static void setUpOnceBase() {
+ sMockTracker = new MockTracker();
+
AttributeCache.init(getInstrumentation().getTargetContext());
}
+ @AfterClass
+ public static void tearDownOnceBase() {
+ sMockTracker.close();
+ sMockTracker = null;
+ }
+
@Before
public void setUpBase() {
mTestInjector.setUp();
@@ -657,12 +669,11 @@
private static WindowManagerService sMockWindowManagerService;
private static WindowManagerService prepareMockWindowManager() {
- if (sMockWindowManagerService != null) {
- return sMockWindowManagerService;
+ if (sMockWindowManagerService == null) {
+ sMockWindowManagerService = mock(WindowManagerService.class);
}
- final WindowManagerService service = mock(WindowManagerService.class);
- service.mRoot = mock(RootWindowContainer.class);
+ sMockWindowManagerService.mRoot = mock(RootWindowContainer.class);
doAnswer((InvocationOnMock invocationOnMock) -> {
final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
@@ -670,10 +681,9 @@
runnable.run();
}
return null;
- }).when(service).inSurfaceTransaction(any());
+ }).when(sMockWindowManagerService).inSurfaceTransaction(any());
- sMockWindowManagerService = service;
- return service;
+ return sMockWindowManagerService;
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index defe981..a7520dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -16,24 +16,29 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
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 android.graphics.Rect;
import android.os.IBinder;
+import android.view.Display;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationTarget;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
-import org.junit.Before;
import org.junit.Test;
/**
@@ -49,14 +54,20 @@
private Task mTask;
private WindowTestUtils.TestAppWindowToken mToken;
- @Before
- public void setUp() throws Exception {
- mStack = createTaskStackOnDisplay(mDisplayContent);
+ public void setUpOnDisplay(DisplayContent dc) {
+ mStack = createTaskStackOnDisplay(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, dc);
mTask = createTaskInStack(mStack, 0 /* userId */);
- mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+ mToken = WindowTestUtils.createTestAppWindowToken(dc);
mToken.mSkipOnParentChanged = false;
mTask.addChild(mToken, 0);
+
+ // Set a remote animator with snapshot disabled. Snapshots don't work in wmtests.
+ RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
+ RemoteAnimationAdapter adapter =
+ new RemoteAnimationAdapter(new TestRemoteAnimationRunner(), 10, 1, false);
+ definition.addRemoteAnimation(TRANSIT_TASK_CHANGE_WINDOWING_MODE, adapter);
+ dc.registerRemoteAnimations(definition);
}
class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
@@ -85,14 +96,58 @@
@Test
public void testModeChangeRemoteAnimatorNoSnapshot() {
- RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
- RemoteAnimationAdapter adapter =
- new RemoteAnimationAdapter(new TestRemoteAnimationRunner(), 10, 1, false);
- definition.addRemoteAnimation(TRANSIT_TASK_CHANGE_WINDOWING_MODE, adapter);
- mDisplayContent.registerRemoteAnimations(definition);
+ // setup currently defaults to no snapshot.
+ setUpOnDisplay(mDisplayContent);
mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertEquals(1, mDisplayContent.mChangingApps.size());
+
+ // Verify we are in a change transition, but without a snapshot.
+ // Though, the test will actually have crashed by now if a snapshot is attempted.
+ assertNull(mToken.getThumbnail());
+ assertTrue(mToken.isInChangeTransition());
+
+ waitUntilHandlersIdle();
+ mToken.removeImmediately();
+ }
+
+ @Test
+ public void testCancelPendingChangeOnRemove() {
+ // setup currently defaults to no snapshot.
+ setUpOnDisplay(mDisplayContent);
+
+ mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ assertEquals(1, mDisplayContent.mChangingApps.size());
+ assertTrue(mToken.isInChangeTransition());
+
+ // Removing the app-token from the display should clean-up the
+ // the change leash.
+ mDisplayContent.removeAppToken(mToken.token);
+ assertEquals(0, mDisplayContent.mChangingApps.size());
+ assertFalse(mToken.isInChangeTransition());
+
+ waitUntilHandlersIdle();
+ mToken.removeImmediately();
+ }
+
+ @Test
+ public void testNoChangeWhenMoveDisplay() {
+ mDisplayContent.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ final DisplayContent dc1 = createNewDisplay(Display.STATE_ON);
+ dc1.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ setUpOnDisplay(dc1);
+
+ assertEquals(WINDOWING_MODE_FREEFORM, mTask.getWindowingMode());
+
+ // Reparenting to a display with different windowing mode may trigger
+ // a change transition internally, but it should be cleaned-up once
+ // the display change is complete.
+ mStack.reparent(mDisplayContent.getDisplayId(), new Rect(), true);
+
+ assertEquals(WINDOWING_MODE_FULLSCREEN, mTask.getWindowingMode());
+
+ // Make sure we're not waiting for a change animation (no leash)
+ assertFalse(mToken.isInChangeTransition());
assertNull(mToken.getThumbnail());
waitUntilHandlersIdle();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 3826fac..a62bc71 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -51,17 +51,22 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
import android.annotation.SuppressLint;
+import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
import android.view.DisplayCutout;
+import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.Surface;
+import android.view.ViewRootImpl;
+import android.view.test.InsetsModeSession;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
@@ -628,6 +633,39 @@
eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
}
+ @Test
+ public void testComputeImeParent_app() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+ final DisplayContent dc = createNewDisplay();
+ dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
+ assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
+ dc.computeImeParent());
+ }
+ }
+
+ @Test
+ public void testComputeImeParent_app_notFullscreen() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+ final DisplayContent dc = createNewDisplay();
+ dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
+ dc.mInputMethodTarget.setWindowingMode(
+ WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
+ }
+ }
+
+ @Test
+ public void testComputeImeParent_noApp() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+ final DisplayContent dc = createNewDisplay();
+ dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
+ assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
+ }
+ }
+
private boolean isOptionsPanelAtRight(int displayId) {
return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 845a09f..4279c41 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -28,6 +28,8 @@
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
@@ -37,6 +39,7 @@
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
+import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -350,6 +353,48 @@
}
@Test
+ public void layoutWindowLw_withForwardInset_SoftInputAdjustResize() {
+ synchronized (mWm.mGlobalLock) {
+ mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
+ addWindow(mWindow);
+
+ final int forwardedInsetBottom = 50;
+ mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom));
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0);
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(),
+ STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT + forwardedInsetBottom);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(),
+ STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT + forwardedInsetBottom);
+ assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0);
+ assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
+ }
+ }
+
+ @Test
+ public void layoutWindowLw_withForwardInset_SoftInputAdjustNothing() {
+ synchronized (mWm.mGlobalLock) {
+ mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING;
+ addWindow(mWindow);
+
+ final int forwardedInsetBottom = 50;
+ mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom));
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0);
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0);
+ assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
+ }
+ }
+
+ @Test
public void layoutHint_appWindow() {
synchronized (mWm.mGlobalLock) {
// Initialize DisplayFrames
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 67ee4ad..94def2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -67,6 +67,7 @@
import org.junit.Test;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -142,7 +143,8 @@
private static void ensureStackPlacement(ActivityStack stack, TaskRecord... tasks) {
final ArrayList<TaskRecord> stackTasks = stack.getAllTasks();
- assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0);
+ assertEquals("Expecting " + Arrays.deepToString(tasks) + " got " + stackTasks,
+ stackTasks.size(), tasks != null ? tasks.length : 0);
if (tasks == null) {
return;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
index b151fb7..1c1fe29 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
@@ -88,6 +88,7 @@
sPolicy = null;
sMockitoSession.finishMocking();
+ sMockitoSession = null;
}
private static void setUpTestWindowService() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 8876214..3eb9085 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -39,6 +39,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.hamcrest.Matchers.is;
@@ -53,6 +54,7 @@
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
import android.graphics.Insets;
import android.graphics.Matrix;
@@ -65,11 +67,13 @@
import android.view.ViewRootImpl;
import android.view.WindowManager;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -88,6 +92,7 @@
@BeforeClass
public static void setUpOnce() {
+ // TODO: Make use of SettingsSession when it becomes feasible for this.
sPreviousNewInsetsMode = ViewRootImpl.sNewInsetsMode;
// To let the insets provider control the insets visibility, the insets mode has to be
// NEW_INSETS_MODE_FULL.
@@ -99,6 +104,15 @@
ViewRootImpl.sNewInsetsMode = sPreviousNewInsetsMode;
}
+ @Before
+ public void setUp() {
+ // TODO: Let the insets source with new mode keep the visibility control, and remove this
+ // setup code. Now mTopFullscreenOpaqueWindowState will take back the control of insets
+ // visibility.
+ spyOn(mDisplayContent);
+ doNothing().when(mDisplayContent).layoutAndAssignWindowLayersIfNeeded();
+ }
+
@Test
public void testIsParentWindowHidden() {
final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -345,6 +359,7 @@
assertFalse(app.canAffectSystemUiFlags());
}
+ @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
@Test
public void testVisibleWithInsetsProvider() throws Exception {
final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar");
@@ -356,6 +371,7 @@
mDisplayContent.getInsetsStateController().onBarControllingWindowChanged(app);
mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
.onInsetsModified(app, new InsetsSource(TYPE_TOP_BAR));
+ waitUntilHandlersIdle();
assertFalse(topBar.isVisible());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 3cb2814..a83bf2a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -50,6 +50,7 @@
import android.view.WindowManager;
import com.android.server.AttributeCache;
+import com.android.server.wm.utils.MockTracker;
import org.junit.After;
import org.junit.AfterClass;
@@ -77,6 +78,8 @@
private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
static int sNextStackId = 1000;
+ private static MockTracker sMockTracker;
+
/** Non-default display. */
DisplayContent mDisplayContent;
DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -109,11 +112,18 @@
TestSystemServices.setUpWindowManagerService();
+ // MockTracker needs to be initialized after TestSystemServices because we don't want to
+ // track static mocks.
+ sMockTracker = new MockTracker();
+
sPowerManagerWrapper = mock(WindowState.PowerManagerWrapper.class);
}
@AfterClass
- public static void tearDonwOnceBase() {
+ public static void tearDownOnceBase() {
+ sMockTracker.close();
+ sMockTracker = null;
+
TestSystemServices.tearDownWindowManagerService();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
index b6b9a86..2970c21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
@@ -34,8 +34,8 @@
import android.platform.test.annotations.Presubmit;
import android.testing.DexmakerShareClassLoaderRule;
import android.util.proto.ProtoOutputStream;
+import android.view.Choreographer;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.internal.util.Preconditions;
@@ -74,6 +74,8 @@
@Mock
private WindowManagerService mWmMock;
+ @Mock
+ private Choreographer mChoreographer;
private WindowTracing mWindowTracing;
private File mFile;
@@ -85,7 +87,9 @@
mFile = testContext.getFileStreamPath("tracing_test.dat");
mFile.delete();
- mWindowTracing = new WindowTracing(mFile);
+ mWindowTracing = new WindowTracing(mFile, mWmMock, mChoreographer,
+ new WindowManagerGlobalLock());
+ mWindowTracing.setContinuousMode(false /* continuous */, null /* pw */);
}
@After
@@ -113,15 +117,14 @@
@Test
public void trace_discared_whenNotTracing() {
- mWindowTracing.traceStateLocked("where", mWmMock);
+ mWindowTracing.logState("where");
verifyZeroInteractions(mWmMock);
}
@Test
public void trace_dumpsWindowManagerState_whenTracing() throws Exception {
mWindowTracing.startTrace(mock(PrintWriter.class));
- mWindowTracing.traceStateLocked("where", mWmMock);
-
+ mWindowTracing.logState("where");
verify(mWmMock).writeToProtoLocked(any(), eq(WindowTraceLogLevel.TRIM));
}
@@ -147,7 +150,7 @@
WindowManagerTraceProto.WHERE, "TEST_WM_PROTO");
return null;
}).when(mWmMock).writeToProtoLocked(any(), any());
- mWindowTracing.traceStateLocked("TEST_WHERE", mWmMock);
+ mWindowTracing.logState("TEST_WHERE");
mWindowTracing.stopTrace(mock(PrintWriter.class));
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/MockTracker.java b/services/tests/wmtests/src/com/android/server/wm/utils/MockTracker.java
new file mode 100644
index 0000000..1ce463b
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/MockTracker.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.utils;
+
+import android.util.Log;
+
+import org.mockito.Mockito;
+import org.mockito.MockitoFramework;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.listeners.MockCreationListener;
+import org.mockito.mock.MockCreationSettings;
+
+import java.lang.reflect.Field;
+import java.util.IdentityHashMap;
+
+/**
+ * An util class used to track mock creation, and reset them when closing. Note only one instance is
+ * allowed at anytime, as Mockito framework throws exception if there is already a listener of the
+ * same type registered.
+ */
+public class MockTracker implements MockCreationListener, AutoCloseable {
+ private static final String TAG = "MockTracker";
+
+ private static final Field SPIED_INSTANCE_FIELD;
+
+ static {
+ try {
+ SPIED_INSTANCE_FIELD = CreationSettings.class.getDeclaredField("spiedInstance");
+ SPIED_INSTANCE_FIELD.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private final MockitoFramework mMockitoFramework = Mockito.framework();
+
+ private final IdentityHashMap<Object, Void> mMocks = new IdentityHashMap<>();
+
+ public MockTracker() {
+ mMockitoFramework.addListener(this);
+ }
+
+ @Override
+ public void onMockCreated(Object mock, MockCreationSettings settings) {
+ mMocks.put(mock, null);
+ clearSpiedInstanceIfNeeded(mock, settings);
+ }
+
+ // HACK: Changing Mockito core implementation details.
+ // TODO(b/123984854): Remove this once there is a real fix.
+ private void clearSpiedInstanceIfNeeded(Object mock, MockCreationSettings settings) {
+ if (mock != settings.getSpiedInstance()) {
+ // Not a spyOn instance.
+ return;
+ }
+ if (!(settings instanceof CreationSettings)) {
+ throw new IllegalStateException("Unexpected type of settings: " + settings.getClass());
+ }
+ try {
+ SPIED_INSTANCE_FIELD.set(settings, null);
+ Log.d(TAG, "Setting spiedInstance for " + mock + " to null.");
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void close() {
+ mMockitoFramework.removeListener(this);
+
+ for (final Object mock : mMocks.keySet()) {
+ try {
+ Mockito.reset(mock);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to reset " + mock, e);
+ }
+ }
+ mMocks.clear();
+ }
+}
diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
index 873ada0..731cbf4 100644
--- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java
+++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
@@ -840,7 +840,8 @@
*/
public void addAppUsageLimitObserver(int requestingUid, int observerId, String[] observed,
long timeLimit, PendingIntent callbackIntent, @UserIdInt int userId) {
- if (timeLimit < getMinTimeLimit()) {
+ // Allow the special case of the limit being 0, but with no callback.
+ if (timeLimit != 0L && timeLimit < getMinTimeLimit()) {
throw new IllegalArgumentException("Time limit must be >= " + getMinTimeLimit());
}
synchronized (mLock) {
@@ -858,7 +859,7 @@
"Too many app usage observers added by uid " + requestingUid);
}
group = new AppUsageLimitGroup(user, observerApp, observerId, observed, timeLimit,
- callbackIntent);
+ timeLimit == 0L ? null : callbackIntent);
observerApp.appUsageLimitGroups.append(observerId, group);
if (DEBUG) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index df2f455..af5278f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1377,7 +1377,7 @@
if (packages == null || packages.length == 0) {
throw new IllegalArgumentException("Must specify at least one package");
}
- if (callbackIntent == null) {
+ if (callbackIntent == null && timeLimitMs != 0L) {
throw new NullPointerException("callbackIntent can't be null");
}
final int callingUid = Binder.getCallingUid();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 7cab432..93f758c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1307,13 +1307,15 @@
List<String> roleHolders = mRm.getRoleHoldersAsUser(roleName, user);
+ int userId = user.getIdentifier();
if (roleHolders.isEmpty()) {
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.ASSISTANT, "");
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.VOICE_INTERACTION_SERVICE, "");
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer(user));
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ Settings.Secure.ASSISTANT, "", userId);
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ Settings.Secure.VOICE_INTERACTION_SERVICE, "", userId);
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer(user),
+ userId);
} else {
// Assistant is singleton role
String pkg = roleHolders.get(0);
@@ -1321,7 +1323,7 @@
// Try to set role holder as VoiceInteractionService
List<ResolveInfo> services = mPm.queryIntentServicesAsUser(
new Intent(VoiceInteractionService.SERVICE_INTERFACE).setPackage(pkg),
- PackageManager.GET_META_DATA, user.getIdentifier());
+ PackageManager.GET_META_DATA, userId);
for (ResolveInfo resolveInfo : services) {
ServiceInfo serviceInfo = resolveInfo.serviceInfo;
@@ -1339,12 +1341,14 @@
voiceInteractionServiceInfo.getRecognitionService())
.flattenToShortString();
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.ASSISTANT, serviceComponentName);
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName);
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName);
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ Settings.Secure.ASSISTANT, serviceComponentName, userId);
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName,
+ userId);
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName,
+ userId);
return;
}
@@ -1352,19 +1356,19 @@
// If no service could be found try to set assist activity
final List<ResolveInfo> activities = mPm.queryIntentActivitiesAsUser(
new Intent(Intent.ACTION_ASSIST).setPackage(pkg),
- PackageManager.MATCH_DEFAULT_ONLY, user.getIdentifier());
+ PackageManager.MATCH_DEFAULT_ONLY, userId);
for (ResolveInfo resolveInfo : activities) {
ActivityInfo activityInfo = resolveInfo.activityInfo;
- Settings.Secure.putString(getContext().getContentResolver(),
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
Settings.Secure.ASSISTANT,
- activityInfo.getComponentName().flattenToShortString());
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.VOICE_INTERACTION_SERVICE, "");
- Settings.Secure.putString(getContext().getContentResolver(),
+ activityInfo.getComponentName().flattenToShortString(), userId);
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ Settings.Secure.VOICE_INTERACTION_SERVICE, "", userId);
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE,
- getDefaultRecognizer(user));
+ getDefaultRecognizer(user), userId);
}
}
}
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 818ebd9..2fa388f 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -75,7 +75,7 @@
*
* public void requestRole() {
* RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
- * Intent intent = roleManager.createRequestRoleIntent("android.app.role.CALL_SCREENING_APP");
+ * Intent intent = roleManager.createRequestRoleIntent("android.app.role.CALL_SCREENING");
* startActivityForResult(intent, REQUEST_ID);
* }
*
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 7d1f8ce..6382acf 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
@@ -571,6 +572,7 @@
* @return The primary connection.
* @hide
*/
+ @TestApi
@SystemApi
public Connection getPrimaryConnection() {
if (mUnmodifiableChildConnections == null || mUnmodifiableChildConnections.isEmpty()) {
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index f5f0af7..cbcd40f 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -35,7 +35,6 @@
import com.android.internal.telecom.IInCallAdapter;
import com.android.internal.telecom.IInCallService;
-import java.lang.String;
import java.util.Collections;
import java.util.List;
@@ -212,7 +211,7 @@
* {@link android.Manifest.permission.CALL_COMPANION_APP}.</li>
* </ul>
* <p>
- * Your app should request to fill the role {@code android.app.role.CAR_MODE_DIALER_APP} in order to
+ * Your app should request to fill the role {@code android.app.role.CAR_MODE_DIALER} in order to
* become the default (see <a href="#requestRole">above</a> for how to request your app fills this
* role).
*
@@ -232,7 +231,7 @@
* {@link android.Manifest.permission.CALL_COMPANION_APP}.</li>
* </ul>
* <p>
- * Your app should request to fill the role {@code android.app.role.CALL_COMPANION_APP} in order to
+ * Your app should request to fill the role {@code android.app.role.CALL_COMPANION} in order to
* become a call companion app (see <a href="#requestRole">above</a> for how to request your app
* fills this role).
*/
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 0e17a33..e99a289 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -22,6 +22,7 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.role.RoleManagerCallback;
import android.content.ComponentName;
@@ -552,6 +553,7 @@
*
* @hide
*/
+ @TestApi
@SystemApi
public static final int TTY_MODE_OFF = 0;
@@ -561,6 +563,7 @@
*
* @hide
*/
+ @TestApi
@SystemApi
public static final int TTY_MODE_FULL = 1;
@@ -571,6 +574,7 @@
*
* @hide
*/
+ @TestApi
@SystemApi
public static final int TTY_MODE_HCO = 2;
@@ -581,6 +585,7 @@
*
* @hide
*/
+ @TestApi
@SystemApi
public static final int TTY_MODE_VCO = 3;
@@ -819,6 +824,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @TestApi
@SystemApi
public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
try {
@@ -1521,6 +1527,7 @@
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @TtyMode int getCurrentTtyMode() {
try {
@@ -1969,6 +1976,7 @@
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean isInEmergencyCall() {
try {
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 9c64cf6..75165af 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -54,8 +54,15 @@
*/
@SystemApi
public static final class TransportType {
+ /**
+ * Invalid transport type.
+ * @hide
+ */
+ public static final int INVALID = -1;
+
/** Wireless Wide Area Networks (i.e. Cellular) */
public static final int WWAN = 1;
+
/** Wireless Local Area Networks (i.e. Wifi) */
public static final int WLAN = 2;
@@ -65,6 +72,7 @@
/** @hide */
public static String toString(int type) {
switch (type) {
+ case INVALID: return "INVALID";
case WWAN: return "WWAN";
case WLAN: return "WLAN";
default: return Integer.toString(type);
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 30e641d..a4207c9 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -63,6 +63,10 @@
public CellSignalStrengthGsm(android.hardware.radio.V1_0.GsmSignalStrength gsm) {
// Convert from HAL values as part of construction.
this(getRssiDbmFromAsu(gsm.signalStrength), gsm.bitErrorRate, gsm.timingAdvance);
+
+ if (mRssi == CellInfo.UNAVAILABLE) {
+ setDefaultValues();
+ }
}
/** @hide */
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
index 6f52b85..5ae89b0 100644
--- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -72,6 +72,10 @@
// Convert from HAL values as part of construction.
this(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
tdscdma.rscp != CellInfo.UNAVAILABLE ? -tdscdma.rscp : tdscdma.rscp);
+
+ if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
+ setDefaultValues();
+ }
}
/** @hide */
@@ -79,6 +83,10 @@
// Convert from HAL values as part of construction.
this(getRssiDbmFromAsu(tdscdma.signalStrength),
tdscdma.bitErrorRate, getRscpDbmFromAsu(tdscdma.rscp));
+
+ if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
+ setDefaultValues();
+ }
}
/** @hide */
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 0760407..efa3647 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -92,8 +92,12 @@
/** @hide */
public CellSignalStrengthWcdma(android.hardware.radio.V1_0.WcdmaSignalStrength wcdma) {
// Convert from HAL values as part of construction.
- this(getRssiDbmFromAsu(wcdma.signalStrength),
- wcdma.bitErrorRate, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE);
+ this(getRssiDbmFromAsu(wcdma.signalStrength), wcdma.bitErrorRate,
+ CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE);
+
+ if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
+ setDefaultValues();
+ }
}
/** @hide */
@@ -103,6 +107,10 @@
wcdma.base.bitErrorRate,
getRscpDbmFromAsu(wcdma.rscp),
getEcNoDbFromAsu(wcdma.ecno));
+
+ if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
+ setDefaultValues();
+ }
}
/** @hide */
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index e40bae1..099015f 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -187,15 +187,7 @@
int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
String format = (PHONE_TYPE_CDMA == activePhone) ?
SmsConstants.FORMAT_3GPP2 : SmsConstants.FORMAT_3GPP;
- message = createFromPdu(pdu, format);
-
- if (null == message || null == message.mWrappedSmsMessage) {
- // decoding pdu failed based on activePhone type, must be other format
- format = (PHONE_TYPE_CDMA == activePhone) ?
- SmsConstants.FORMAT_3GPP : SmsConstants.FORMAT_3GPP2;
- message = createFromPdu(pdu, format);
- }
- return message;
+ return createFromPdu(pdu, format);
}
/**
@@ -211,11 +203,18 @@
* {@link android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION} intent
*/
public static SmsMessage createFromPdu(byte[] pdu, String format) {
- SmsMessageBase wrappedMessage;
+ return createFromPdu(pdu, format, true);
+ }
+
+ private static SmsMessage createFromPdu(byte[] pdu, String format,
+ boolean fallbackToOtherFormat) {
if (pdu == null) {
Rlog.i(LOG_TAG, "createFromPdu(): pdu is null");
return null;
}
+ SmsMessageBase wrappedMessage;
+ String otherFormat = SmsConstants.FORMAT_3GPP2.equals(format) ? SmsConstants.FORMAT_3GPP :
+ SmsConstants.FORMAT_3GPP2;
if (SmsConstants.FORMAT_3GPP2.equals(format)) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
} else if (SmsConstants.FORMAT_3GPP.equals(format)) {
@@ -228,8 +227,12 @@
if (wrappedMessage != null) {
return new SmsMessage(wrappedMessage);
} else {
- Rlog.e(LOG_TAG, "createFromPdu(): wrappedMessage is null");
- return null;
+ if (fallbackToOtherFormat) {
+ return createFromPdu(pdu, otherFormat, false);
+ } else {
+ Rlog.e(LOG_TAG, "createFromPdu(): wrappedMessage is null");
+ return null;
+ }
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index dfe36ef..313146d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2047,6 +2047,8 @@
putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]);
} else {
logd("putPhoneIdAndSubIdExtra: no valid subs");
+ intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
+ intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index eab536f..f5d452e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4920,12 +4920,13 @@
*
* <p>Apps targeting {@link android.os.Build.VERSION_CODES#Q Android Q} or higher will no
* longer trigger a refresh of the cached CellInfo by invoking this API. Instead, those apps
- * will receive the latest cached results. Apps targeting
+ * will receive the latest cached results, which may not be current. Apps targeting
* {@link android.os.Build.VERSION_CODES#Q Android Q} or higher that wish to request updated
* CellInfo should call
- * {android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()} and
- * listen for responses via {@link android.telephony.PhoneStateListener#onCellInfoChanged
- * onCellInfoChanged()}.
+ * {@link android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()};
+ * however, in all cases, updates will be rate-limited and are not guaranteed. To determine the
+ * recency of CellInfo data, callers should check
+ * {@link android.telephony.CellInfo#getTimeStamp CellInfo#getTimeStamp()}.
*
* <p>This method returns valid data for devices with
* {@link android.content.pm.PackageManager#FEATURE_TELEPHONY FEATURE_TELEPHONY}. In cases
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
index cc28ee0..3255f8d 100644
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
@@ -23,7 +23,7 @@
* {@link RcsParticipant}s. Please see Section 5 (1-to-1 Messaging) - GSMA RCC.71 (RCS Universal
* Profile Service Definition Document)
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public class Rcs1To1Thread extends RcsThread {
private int mThreadId;
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
index 744ac76..ef359a1 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ b/telephony/java/android/telephony/ims/RcsEvent.java
@@ -16,14 +16,17 @@
package android.telephony.ims;
import android.os.Parcel;
-import android.os.Parcelable;
/**
* The base class for events that can happen on {@link RcsParticipant}s and {@link RcsThread}s.
- * @hide - TODO(109759350) make this public
+ *
+ * @hide - TODO: make public
*/
-public abstract class RcsEvent implements Parcelable {
- protected long mTimestamp;
+public abstract class RcsEvent {
+ /**
+ * @hide
+ */
+ protected final long mTimestamp;
protected RcsEvent(long timestamp) {
mTimestamp = timestamp;
@@ -44,17 +47,17 @@
*/
abstract void persist() throws RcsMessageStoreException;
+ /**
+ * @hide
+ */
RcsEvent(Parcel in) {
mTimestamp = in.readLong();
}
- @Override
+ /**
+ * @hide
+ */
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mTimestamp);
}
-
- @Override
- public int describeContents() {
- return 0;
- }
}
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsEventQueryParameters.aidl
deleted file mode 100644
index 9a3600b..0000000
--- a/telephony/java/android/telephony/ims/RcsEventQueryParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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.telephony.ims;
-
-parcelable RcsEventQueryParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsEventQueryParams.aidl
similarity index 94%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsEventQueryParams.aidl
index 52e73ce..f18c4df 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsEventQueryParams.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsThreadQueryParameters;
+parcelable RcsEventQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryParameters.java b/telephony/java/android/telephony/ims/RcsEventQueryParams.java
similarity index 83%
rename from telephony/java/android/telephony/ims/RcsEventQueryParameters.java
rename to telephony/java/android/telephony/ims/RcsEventQueryParams.java
index 6aee56f..5249bec 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryParameters.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryParams.java
@@ -35,29 +35,29 @@
/**
* The parameters to pass into
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} in order to select a
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} in order to select a
* subset of {@link RcsEvent}s present in the message store.
*
- * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ * @hide - TODO: make public
*/
-public class RcsEventQueryParameters implements Parcelable {
+public final class RcsEventQueryParams implements Parcelable {
/**
* Flag to be used with {@link Builder#setEventType(int)} to make
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return all types of
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return all types of
* {@link RcsEvent}s
*/
public static final int ALL_EVENTS = -1;
/**
* Flag to be used with {@link Builder#setEventType(int)} to make
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return sub-types of
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return sub-types of
* {@link RcsGroupThreadEvent}s
*/
public static final int ALL_GROUP_THREAD_EVENTS = 0;
/**
* Flag to be used with {@link Builder#setEventType(int)} to make
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
* {@link RcsParticipantAliasChangedEvent}s
*/
public static final int PARTICIPANT_ALIAS_CHANGED_EVENT =
@@ -65,7 +65,7 @@
/**
* Flag to be used with {@link Builder#setEventType(int)} to make
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
* {@link RcsGroupThreadParticipantJoinedEvent}s
*/
public static final int GROUP_THREAD_PARTICIPANT_JOINED_EVENT =
@@ -73,7 +73,7 @@
/**
* Flag to be used with {@link Builder#setEventType(int)} to make
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
* {@link RcsGroupThreadParticipantLeftEvent}s
*/
public static final int GROUP_THREAD_PARTICIPANT_LEFT_EVENT =
@@ -81,14 +81,14 @@
/**
* Flag to be used with {@link Builder#setEventType(int)} to make
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
* {@link RcsGroupThreadNameChangedEvent}s
*/
public static final int GROUP_THREAD_NAME_CHANGED_EVENT = NAME_CHANGED_EVENT_TYPE;
/**
* Flag to be used with {@link Builder#setEventType(int)} to make
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
* {@link RcsGroupThreadIconChangedEvent}s
*/
public static final int GROUP_THREAD_ICON_CHANGED_EVENT = ICON_CHANGED_EVENT_TYPE;
@@ -134,7 +134,7 @@
// The thread that the results are limited to
private int mThreadId;
- RcsEventQueryParameters(@EventType int eventType, int threadId,
+ RcsEventQueryParams(@EventType int eventType, int threadId,
@SortingProperty int sortingProperty, boolean isAscending, int limit) {
mEventType = eventType;
mSortingProperty = sortingProperty;
@@ -144,7 +144,7 @@
}
/**
- * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParameters} is
+ * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParams} is
* set to query for.
*/
public @EventType int getEventType() {
@@ -152,7 +152,7 @@
}
/**
- * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParameters} is
+ * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParams} is
* set to query for.
*/
public int getLimit() {
@@ -186,7 +186,7 @@
}
/**
- * A helper class to build the {@link RcsEventQueryParameters}.
+ * A helper class to build the {@link RcsEventQueryParams}.
*/
public static class Builder {
private @EventType int mEventType;
@@ -196,8 +196,8 @@
private int mThreadId;
/**
- * Creates a new builder for {@link RcsEventQueryParameters} to be used in
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)}
+ * Creates a new builder for {@link RcsEventQueryParams} to be used in
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
*/
public Builder() {
// empty implementation
@@ -236,7 +236,7 @@
/**
* Sets the property where the results should be sorted against. Defaults to
- * {@link RcsEventQueryParameters.SortingProperty#SORT_BY_CREATION_ORDER}
+ * {@link RcsEventQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
*
* @param sortingProperty against which property the results should be sorted
* @return The same instance of the builder to chain parameters.
@@ -273,18 +273,18 @@
}
/**
- * Builds the {@link RcsEventQueryParameters} to use in
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)}
+ * Builds the {@link RcsEventQueryParams} to use in
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
*
- * @return An instance of {@link RcsEventQueryParameters} to use with the event query.
+ * @return An instance of {@link RcsEventQueryParams} to use with the event query.
*/
- public RcsEventQueryParameters build() {
- return new RcsEventQueryParameters(mEventType, mThreadId, mSortingProperty,
+ public RcsEventQueryParams build() {
+ return new RcsEventQueryParams(mEventType, mThreadId, mSortingProperty,
mIsAscending, mLimit);
}
}
- protected RcsEventQueryParameters(Parcel in) {
+ private RcsEventQueryParams(Parcel in) {
mEventType = in.readInt();
mThreadId = in.readInt();
mSortingProperty = in.readInt();
@@ -292,20 +292,19 @@
mLimit = in.readInt();
}
- public static final Creator<RcsEventQueryParameters> CREATOR =
- new Creator<RcsEventQueryParameters>() {
+ public static final Creator<RcsEventQueryParams> CREATOR =
+ new Creator<RcsEventQueryParams>() {
@Override
- public RcsEventQueryParameters createFromParcel(Parcel in) {
- return new RcsEventQueryParameters(in);
+ public RcsEventQueryParams createFromParcel(Parcel in) {
+ return new RcsEventQueryParams(in);
}
@Override
- public RcsEventQueryParameters[] newArray(int size) {
- return new RcsEventQueryParameters[size];
+ public RcsEventQueryParams[] newArray(int size) {
+ return new RcsEventQueryParams[size];
}
};
-
@Override
public int describeContents() {
return 0;
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResult.java b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
index 27898ab..f8d57fa 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
@@ -22,13 +22,13 @@
import java.util.List;
/**
- * The result of a {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)}
+ * The result of a {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
* call. This class allows getting the token for querying the next batch of events in order to
* prevent handling large amounts of data at once.
*
- * @hide
+ * @hide - TODO: make public
*/
-public class RcsEventQueryResult implements Parcelable {
+public final class RcsEventQueryResult implements Parcelable {
private RcsQueryContinuationToken mContinuationToken;
private List<RcsEvent> mEvents;
@@ -63,7 +63,8 @@
return mEvents;
}
- protected RcsEventQueryResult(Parcel in) {
+ private RcsEventQueryResult(Parcel in) {
+ mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
}
public static final Creator<RcsEventQueryResult> CREATOR = new Creator<RcsEventQueryResult>() {
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.aidl b/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.aidl
deleted file mode 100644
index 5fec021..0000000
--- a/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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.telephony.ims;
-
-parcelable RcsFileTransferCreationParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl
similarity index 93%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl
index 52e73ce..1552190 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsThreadQueryParameters;
+parcelable RcsFileTransferCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.java b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
similarity index 92%
rename from telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.java
rename to telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
index bd7cb4b..663def5 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
@@ -22,12 +22,12 @@
/**
* Pass an instance of this class to
- * {@link RcsMessage#insertFileTransfer(RcsFileTransferCreationParameters)} create an
+ * {@link RcsMessage#insertFileTransfer(RcsFileTransferCreationParams)} create an
* {@link RcsFileTransferPart} and save it into storage.
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
-public class RcsFileTransferCreationParameters implements Parcelable {
+public final class RcsFileTransferCreationParams implements Parcelable {
private String mRcsFileTransferSessionId;
private Uri mContentUri;
private String mContentMimeType;
@@ -128,7 +128,7 @@
/**
* @hide
*/
- RcsFileTransferCreationParameters(Builder builder) {
+ RcsFileTransferCreationParams(Builder builder) {
mRcsFileTransferSessionId = builder.mRcsFileTransferSessionId;
mContentUri = builder.mContentUri;
mContentMimeType = builder.mContentMimeType;
@@ -143,7 +143,7 @@
}
/**
- * A builder to create instances of {@link RcsFileTransferCreationParameters}
+ * A builder to create instances of {@link RcsFileTransferCreationParams}
*/
public class Builder {
private String mRcsFileTransferSessionId;
@@ -300,18 +300,18 @@
}
/**
- * Creates an instance of {@link RcsFileTransferCreationParameters} with the given
+ * Creates an instance of {@link RcsFileTransferCreationParams} with the given
* parameters.
*
* @return The same instance of {@link Builder} to chain methods
- * @see RcsMessage#insertFileTransfer(RcsFileTransferCreationParameters)
+ * @see RcsMessage#insertFileTransfer(RcsFileTransferCreationParams)
*/
- public RcsFileTransferCreationParameters build() {
- return new RcsFileTransferCreationParameters(this);
+ public RcsFileTransferCreationParams build() {
+ return new RcsFileTransferCreationParams(this);
}
}
- protected RcsFileTransferCreationParameters(Parcel in) {
+ private RcsFileTransferCreationParams(Parcel in) {
mRcsFileTransferSessionId = in.readString();
mContentUri = in.readParcelable(Uri.class.getClassLoader());
mContentMimeType = in.readString();
@@ -325,16 +325,16 @@
mFileTransferStatus = in.readInt();
}
- public static final Creator<RcsFileTransferCreationParameters> CREATOR =
- new Creator<RcsFileTransferCreationParameters>() {
+ public static final Creator<RcsFileTransferCreationParams> CREATOR =
+ new Creator<RcsFileTransferCreationParams>() {
@Override
- public RcsFileTransferCreationParameters createFromParcel(Parcel in) {
- return new RcsFileTransferCreationParameters(in);
+ public RcsFileTransferCreationParams createFromParcel(Parcel in) {
+ return new RcsFileTransferCreationParams(in);
}
@Override
- public RcsFileTransferCreationParameters[] newArray(int size) {
- return new RcsFileTransferCreationParameters[size];
+ public RcsFileTransferCreationParams[] newArray(int size) {
+ return new RcsFileTransferCreationParams[size];
}
};
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferPart.java b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
index 2eadc4a..1ce7999 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
@@ -27,7 +27,7 @@
* A part of a composite {@link RcsMessage} that holds a file transfer. Please see Section 7
* (File Transfer) - GSMA RCC.71 (RCS Universal Profile Service Definition Document)
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public class RcsFileTransferPart {
/**
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
index 6f6258e..2c42494 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThread.java
@@ -30,7 +30,7 @@
* or leave. Please see Section 6 (Group Chat) - GSMA RCC.71 (RCS Universal Profile Service
* Definition Document)
*
- * @hide - TODO(sahinc) make this public
+ * @hide - TODO: make public
*/
public class RcsGroupThread extends RcsThread {
/**
@@ -166,8 +166,8 @@
@WorkerThread
@NonNull
public Set<RcsParticipant> getParticipants() throws RcsMessageStoreException {
- RcsParticipantQueryParameters queryParameters =
- new RcsParticipantQueryParameters.Builder().setThread(this).build();
+ RcsParticipantQueryParams queryParameters =
+ new RcsParticipantQueryParams.Builder().setThread(this).build();
RcsParticipantQueryResult queryResult = RcsControllerCall.call(
iRcs -> iRcs.getParticipants(queryParameters));
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
index a18437b..bc61877 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
@@ -21,7 +21,7 @@
/**
* An event that happened on an {@link RcsGroupThread}.
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public abstract class RcsGroupThreadEvent extends RcsEvent {
private final int mRcsGroupThreadId;
@@ -50,13 +50,18 @@
return new RcsParticipant(mOriginatingParticipantId);
}
+ /**
+ * @hide
+ */
RcsGroupThreadEvent(Parcel in) {
super(in);
mRcsGroupThreadId = in.readInt();
mOriginatingParticipantId = in.readInt();
}
- @Override
+ /**
+ * @hide
+ */
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mRcsGroupThreadId);
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
index 7beed3b..74af973 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
@@ -19,14 +19,16 @@
import android.annotation.Nullable;
import android.net.Uri;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* An event that indicates an {@link RcsGroupThread}'s icon was changed. Please see R6-2-5 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
-public class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent {
+public final class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent implements
+ Parcelable {
private final Uri mNewIcon;
/**
@@ -91,7 +93,7 @@
}
};
- protected RcsGroupThreadIconChangedEvent(Parcel in) {
+ private RcsGroupThreadIconChangedEvent(Parcel in) {
super(in);
mNewIcon = in.readParcelable(Uri.class.getClassLoader());
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
index 0d2ea4f..06f4d5b 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
@@ -18,15 +18,17 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* An event that indicates an {@link RcsGroupThread}'s name was changed. Please see R6-2-5 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
-public class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent {
- private String mNewName;
+public final class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent implements
+ Parcelable {
+ private final String mNewName;
/**
* Creates a new {@link RcsGroupThreadNameChangedEvent}. This event is not persisted into
@@ -89,7 +91,7 @@
}
};
- protected RcsGroupThreadNameChangedEvent(Parcel in) {
+ private RcsGroupThreadNameChangedEvent(Parcel in) {
super(in);
mNewName = in.readString();
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
index 2adafc7..4932707 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
@@ -17,15 +17,17 @@
import android.annotation.NonNull;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* An event that indicates an RCS participant has joined an {@link RcsThread}. Please see US6-3 -
* GSMA RCC.71 (RCS Universal Profile Service Definition Document)
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
-public class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEvent {
- private int mJoinedParticipantId;
+public final class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEvent implements
+ Parcelable {
+ private final int mJoinedParticipantId;
/**
* Creates a new {@link RcsGroupThreadParticipantJoinedEvent}. This event is not persisted into
@@ -89,7 +91,7 @@
}
};
- protected RcsGroupThreadParticipantJoinedEvent(Parcel in) {
+ private RcsGroupThreadParticipantJoinedEvent(Parcel in) {
super(in);
mJoinedParticipantId = in.readInt();
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
index 87c1852..970a046 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
@@ -17,15 +17,17 @@
import android.annotation.NonNull;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* An event that indicates an RCS participant has left an {@link RcsThread}. Please see US6-23 -
* GSMA RCC.71 (RCS Universal Profile Service Definition Document)
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
-public class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEvent {
- private int mLeavingParticipantId;
+public final class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEvent implements
+ Parcelable {
+ private final int mLeavingParticipantId;
/**
* Creates a new {@link RcsGroupThreadParticipantLeftEvent}. his event is not persisted into
@@ -88,7 +90,7 @@
}
};
- protected RcsGroupThreadParticipantLeftEvent(Parcel in) {
+ private RcsGroupThreadParticipantLeftEvent(Parcel in) {
super(in);
mLeavingParticipantId = in.readInt();
}
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessage.java b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
index 2ea115b..f3b7815 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
@@ -20,7 +20,7 @@
/**
* This is a single instance of a message received over RCS.
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public class RcsIncomingMessage extends RcsMessage {
/**
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.aidl b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.aidl
deleted file mode 100644
index 76073c2..0000000
--- a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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.telephony.ims;
-
-parcelable RcsIncomingMessageCreationParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl
similarity index 93%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl
index 52e73ce..1f1d4f6 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsThreadQueryParameters;
+parcelable RcsIncomingMessageCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.java b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
similarity index 81%
rename from telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.java
rename to telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
index acde8af..64b2339 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
@@ -21,13 +21,13 @@
import android.os.Parcelable;
/**
- * {@link RcsIncomingMessageCreationParameters} is a collection of parameters that should be passed
- * into {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParameters)} to generate an
+ * {@link RcsIncomingMessageCreationParams} is a collection of parameters that should be passed
+ * into {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)} to generate an
* {@link RcsIncomingMessage} on that {@link RcsThread}
*
- * @hide TODO:make public
+ * @hide - TODO: make public
*/
-public class RcsIncomingMessageCreationParameters extends RcsMessageCreationParameters implements
+public final class RcsIncomingMessageCreationParams extends RcsMessageCreationParams implements
Parcelable {
// The arrival timestamp for the RcsIncomingMessage to be created
private final long mArrivalTimestamp;
@@ -37,18 +37,18 @@
private final int mSenderParticipantId;
/**
- * Builder to help create an {@link RcsIncomingMessageCreationParameters}
+ * Builder to help create an {@link RcsIncomingMessageCreationParams}
*
- * @see RcsThread#addIncomingMessage(RcsIncomingMessageCreationParameters)
+ * @see RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)
*/
- public static class Builder extends RcsMessageCreationParameters.Builder {
+ public static class Builder extends RcsMessageCreationParams.Builder {
private RcsParticipant mSenderParticipant;
private long mArrivalTimestamp;
private long mSeenTimestamp;
/**
* Creates a {@link Builder} to create an instance of
- * {@link RcsIncomingMessageCreationParameters}
+ * {@link RcsIncomingMessageCreationParams}
*
* @param originationTimestamp The timestamp of {@link RcsMessage} creation. The origination
* timestamp value in milliseconds passed after midnight,
@@ -103,22 +103,22 @@
/**
* Creates parameters for creating a new incoming message.
- * @return A new instance of {@link RcsIncomingMessageCreationParameters} to create a new
+ * @return A new instance of {@link RcsIncomingMessageCreationParams} to create a new
* {@link RcsIncomingMessage}
*/
- public RcsIncomingMessageCreationParameters build() {
- return new RcsIncomingMessageCreationParameters(this);
+ public RcsIncomingMessageCreationParams build() {
+ return new RcsIncomingMessageCreationParams(this);
}
}
- private RcsIncomingMessageCreationParameters(Builder builder) {
+ private RcsIncomingMessageCreationParams(Builder builder) {
super(builder);
mArrivalTimestamp = builder.mArrivalTimestamp;
mSeenTimestamp = builder.mSeenTimestamp;
mSenderParticipantId = builder.mSenderParticipant.getId();
}
- protected RcsIncomingMessageCreationParameters(Parcel in) {
+ private RcsIncomingMessageCreationParams(Parcel in) {
super(in);
mArrivalTimestamp = in.readLong();
mSeenTimestamp = in.readLong();
@@ -152,16 +152,16 @@
return mSenderParticipantId;
}
- public static final Creator<RcsIncomingMessageCreationParameters> CREATOR =
- new Creator<RcsIncomingMessageCreationParameters>() {
+ public static final Creator<RcsIncomingMessageCreationParams> CREATOR =
+ new Creator<RcsIncomingMessageCreationParams>() {
@Override
- public RcsIncomingMessageCreationParameters createFromParcel(Parcel in) {
- return new RcsIncomingMessageCreationParameters(in);
+ public RcsIncomingMessageCreationParams createFromParcel(Parcel in) {
+ return new RcsIncomingMessageCreationParams(in);
}
@Override
- public RcsIncomingMessageCreationParameters[] newArray(int size) {
- return new RcsIncomingMessageCreationParameters[size];
+ public RcsIncomingMessageCreationParams[] newArray(int size) {
+ return new RcsIncomingMessageCreationParams[size];
}
};
@@ -172,7 +172,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
+ super.writeToParcel(dest);
dest.writeLong(mArrivalTimestamp);
dest.writeLong(mSeenTimestamp);
dest.writeInt(mSenderParticipantId);
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
index e84d4ed..90bd044 100644
--- a/telephony/java/android/telephony/ims/RcsManager.java
+++ b/telephony/java/android/telephony/ims/RcsManager.java
@@ -20,11 +20,19 @@
/**
* The manager class for RCS related utilities.
- * @hide
+ *
+ * @hide - TODO: make public
*/
@SystemService(Context.TELEPHONY_RCS_SERVICE)
public class RcsManager {
+ /**
+ * @hide
+ */
+ public RcsManager() {
+ // empty constructor
+ }
+
private static final RcsMessageStore sRcsMessageStoreInstance = new RcsMessageStore();
/**
diff --git a/telephony/java/android/telephony/ims/RcsMessage.java b/telephony/java/android/telephony/ims/RcsMessage.java
index b70a9a7..1700941 100644
--- a/telephony/java/android/telephony/ims/RcsMessage.java
+++ b/telephony/java/android/telephony/ims/RcsMessage.java
@@ -28,7 +28,7 @@
/**
* This is a single instance of a message sent or received over RCS.
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public abstract class RcsMessage {
/**
@@ -83,7 +83,10 @@
*/
public static final int SEEN = 9;
- protected int mId;
+ /**
+ * @hide
+ */
+ protected final int mId;
@IntDef({
DRAFT, QUEUED, SENDING, SENT, RETRYING, FAILED, RECEIVED, SEEN
@@ -277,7 +280,7 @@
@NonNull
@WorkerThread
public RcsFileTransferPart insertFileTransfer(
- RcsFileTransferCreationParameters fileTransferCreationParameters)
+ RcsFileTransferCreationParams fileTransferCreationParameters)
throws RcsMessageStoreException {
return new RcsFileTransferPart(RcsControllerCall.call(
iRcs -> iRcs.storeFileTransfer(mId, isIncoming(), fileTransferCreationParameters)));
diff --git a/telephony/java/android/telephony/ims/RcsMessageCreationParameters.aidl b/telephony/java/android/telephony/ims/RcsMessageCreationParameters.aidl
deleted file mode 100644
index 5774d00..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageCreationParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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.telephony.ims;
-
-parcelable RcsMessageCreationParameters;
diff --git a/telephony/java/android/telephony/ims/RcsMessageCreationParameters.java b/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
similarity index 80%
rename from telephony/java/android/telephony/ims/RcsMessageCreationParameters.java
rename to telephony/java/android/telephony/ims/RcsMessageCreationParams.java
index ff3f33e..9ac4dcd 100644
--- a/telephony/java/android/telephony/ims/RcsMessageCreationParameters.java
+++ b/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
@@ -21,18 +21,16 @@
import android.annotation.CheckResult;
import android.annotation.Nullable;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.SubscriptionInfo;
/**
* The collection of parameters to be passed into
- * {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParameters)} and
- * {@link RcsThread#addOutgoingMessage(RcsMessageCreationParameters)} to create and persist
+ * {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)} and
+ * {@link RcsThread#addOutgoingMessage(RcsOutgoingMessageCreationParams)} to create and persist
* {@link RcsMessage}s on an {@link RcsThread}
*
- * @hide TODO - make public
+ * @hide - TODO: make public
*/
-public class RcsMessageCreationParameters implements Parcelable {
+public class RcsMessageCreationParams {
// The globally unique id of the RcsMessage to be created.
private final String mRcsMessageGlobalId;
@@ -110,7 +108,7 @@
/**
* The base builder for creating {@link RcsMessage}s on {@link RcsThread}s.
*
- * @see RcsIncomingMessageCreationParameters
+ * @see RcsIncomingMessageCreationParams
*/
public static class Builder {
private String mRcsMessageGlobalId;
@@ -122,15 +120,7 @@
private double mLongitude = LOCATION_NOT_SET;
/**
- * Creates a new {@link Builder} to create an instance of
- * {@link RcsMessageCreationParameters}.
- *
- * @param originationTimestamp The timestamp of {@link RcsMessage} creation. The origination
- * timestamp value in milliseconds passed after midnight,
- * January 1, 1970 UTC
- * @param subscriptionId The subscription ID that was used to send or receive this
- * {@link RcsMessage}
- * @see SubscriptionInfo#getSubscriptionId()
+ * @hide
*/
public Builder(long originationTimestamp, int subscriptionId) {
mOriginationTimestamp = originationTimestamp;
@@ -207,14 +197,14 @@
}
/**
- * @hide
+ * @return Builds and returns a newly created {@link RcsMessageCreationParams}
*/
- public RcsMessageCreationParameters build() {
- return new RcsMessageCreationParameters(this);
+ public RcsMessageCreationParams build() {
+ return new RcsMessageCreationParams(this);
}
}
- protected RcsMessageCreationParameters(Builder builder) {
+ protected RcsMessageCreationParams(Builder builder) {
mRcsMessageGlobalId = builder.mRcsMessageGlobalId;
mSubId = builder.mSubId;
mMessageStatus = builder.mMessageStatus;
@@ -224,7 +214,10 @@
mLongitude = builder.mLongitude;
}
- protected RcsMessageCreationParameters(Parcel in) {
+ /**
+ * @hide
+ */
+ RcsMessageCreationParams(Parcel in) {
mRcsMessageGlobalId = in.readString();
mSubId = in.readInt();
mMessageStatus = in.readInt();
@@ -234,26 +227,10 @@
mLongitude = in.readDouble();
}
- public static final Creator<RcsMessageCreationParameters> CREATOR =
- new Creator<RcsMessageCreationParameters>() {
- @Override
- public RcsMessageCreationParameters createFromParcel(Parcel in) {
- return new RcsMessageCreationParameters(in);
- }
-
- @Override
- public RcsMessageCreationParameters[] newArray(int size) {
- return new RcsMessageCreationParameters[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
+ /**
+ * @hide
+ */
+ public void writeToParcel(Parcel dest) {
dest.writeString(mRcsMessageGlobalId);
dest.writeInt(mSubId);
dest.writeInt(mMessageStatus);
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryParameters.aidl
deleted file mode 100644
index c325c23..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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.telephony.ims;
-
-parcelable RcsMessageQueryParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
similarity index 94%
rename from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
rename to telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
index 52e73ce..e9cbd9c 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsThreadQueryParameters;
+parcelable RcsMessageQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParameters.java b/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
similarity index 86%
rename from telephony/java/android/telephony/ims/RcsMessageQueryParameters.java
rename to telephony/java/android/telephony/ims/RcsMessageQueryParams.java
index c964cf9..fae0d97 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParameters.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
@@ -29,12 +29,12 @@
/**
* The parameters to pass into
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} in order to select a
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} in order to select a
* subset of {@link RcsMessage}s present in the message store.
*
- * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ * @hide - TODO: make public
*/
-public class RcsMessageQueryParameters implements Parcelable {
+public final class RcsMessageQueryParams implements Parcelable {
/**
* @hide - not meant for public use
*/
@@ -60,28 +60,28 @@
/**
* Bitmask flag to be used with {@link Builder#setMessageType(int)} to make
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} return
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return
* {@link RcsIncomingMessage}s.
*/
public static final int MESSAGE_TYPE_INCOMING = 0x0001;
/**
* Bitmask flag to be used with {@link Builder#setMessageType(int)} to make
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} return
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return
* {@link RcsOutgoingMessage}s.
*/
public static final int MESSAGE_TYPE_OUTGOING = 0x0002;
/**
* Bitmask flag to be used with {@link Builder#setFileTransferPresence(int)} to make
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} return {@link RcsMessage}s
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return {@link RcsMessage}s
* that have an {@link RcsFileTransferPart} attached.
*/
public static final int MESSAGES_WITH_FILE_TRANSFERS = 0x0004;
/**
* Bitmask flag to be used with {@link Builder#setFileTransferPresence(int)} to make
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} return {@link RcsMessage}s
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return {@link RcsMessage}s
* that don't have an {@link RcsFileTransferPart} attached.
*/
public static final int MESSAGES_WITHOUT_FILE_TRANSFERS = 0x0008;
@@ -106,7 +106,7 @@
// The thread that the results should be limited to
private int mThreadId;
- RcsMessageQueryParameters(int messageType, int fileTransferPresence, String messageLike,
+ RcsMessageQueryParams(int messageType, int fileTransferPresence, String messageLike,
int threadId, @SortingProperty int sortingProperty, boolean isAscending, int limit) {
mMessageType = messageType;
mFileTransferPresence = fileTransferPresence;
@@ -118,7 +118,7 @@
}
/**
- * @return Returns the type of {@link RcsMessage}s that this {@link RcsMessageQueryParameters}
+ * @return Returns the type of {@link RcsMessage}s that this {@link RcsMessageQueryParams}
* is set to query for.
*/
public int getMessageType() {
@@ -177,7 +177,7 @@
}
/**
- * A helper class to build the {@link RcsMessageQueryParameters}.
+ * A helper class to build the {@link RcsMessageQueryParams}.
*/
public static class Builder {
private @SortingProperty int mSortingProperty;
@@ -189,8 +189,8 @@
private int mThreadId = THREAD_ID_NOT_SET;
/**
- * Creates a new builder for {@link RcsMessageQueryParameters} to be used in
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)}
+ * Creates a new builder for {@link RcsMessageQueryParams} to be used in
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
*
*/
public Builder() {
@@ -221,8 +221,8 @@
*
* @param messageType The type of message to be returned.
* @return The same instance of the builder to chain parameters.
- * @see RcsMessageQueryParameters#MESSAGE_TYPE_INCOMING
- * @see RcsMessageQueryParameters#MESSAGE_TYPE_OUTGOING
+ * @see RcsMessageQueryParams#MESSAGE_TYPE_INCOMING
+ * @see RcsMessageQueryParams#MESSAGE_TYPE_OUTGOING
*/
@CheckResult
public Builder setMessageType(int messageType) {
@@ -235,8 +235,8 @@
*
* @param fileTransferPresence Whether file transfers should be included in the result
* @return The same instance of the builder to chain parameters.
- * @see RcsMessageQueryParameters#MESSAGES_WITH_FILE_TRANSFERS
- * @see RcsMessageQueryParameters#MESSAGES_WITHOUT_FILE_TRANSFERS
+ * @see RcsMessageQueryParams#MESSAGES_WITH_FILE_TRANSFERS
+ * @see RcsMessageQueryParams#MESSAGES_WITHOUT_FILE_TRANSFERS
*/
@CheckResult
public Builder setFileTransferPresence(int fileTransferPresence) {
@@ -264,7 +264,7 @@
/**
* Sets the property where the results should be sorted against. Defaults to
- * {@link RcsMessageQueryParameters.SortingProperty#SORT_BY_CREATION_ORDER}
+ * {@link RcsMessageQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
*
* @param sortingProperty against which property the results should be sorted
* @return The same instance of the builder to chain parameters.
@@ -305,14 +305,14 @@
}
/**
- * Builds the {@link RcsMessageQueryParameters} to use in
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)}
+ * Builds the {@link RcsMessageQueryParams} to use in
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
*
- * @return An instance of {@link RcsMessageQueryParameters} to use with the message
+ * @return An instance of {@link RcsMessageQueryParams} to use with the message
* query.
*/
- public RcsMessageQueryParameters build() {
- return new RcsMessageQueryParameters(mMessageType, mFileTransferPresence, mMessageLike,
+ public RcsMessageQueryParams build() {
+ return new RcsMessageQueryParams(mMessageType, mFileTransferPresence, mMessageLike,
mThreadId, mSortingProperty, mIsAscending, mLimit);
}
}
@@ -320,7 +320,7 @@
/**
* Parcelable boilerplate below.
*/
- protected RcsMessageQueryParameters(Parcel in) {
+ private RcsMessageQueryParams(Parcel in) {
mMessageType = in.readInt();
mFileTransferPresence = in.readInt();
mMessageLike = in.readString();
@@ -330,16 +330,16 @@
mThreadId = in.readInt();
}
- public static final Creator<RcsMessageQueryParameters> CREATOR =
- new Creator<RcsMessageQueryParameters>() {
+ public static final Creator<RcsMessageQueryParams> CREATOR =
+ new Creator<RcsMessageQueryParams>() {
@Override
- public RcsMessageQueryParameters createFromParcel(Parcel in) {
- return new RcsMessageQueryParameters(in);
+ public RcsMessageQueryParams createFromParcel(Parcel in) {
+ return new RcsMessageQueryParams(in);
}
@Override
- public RcsMessageQueryParameters[] newArray(int size) {
- return new RcsMessageQueryParameters[size];
+ public RcsMessageQueryParams[] newArray(int size) {
+ return new RcsMessageQueryParams[size];
}
};
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
index c3846fd..5adab76 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
@@ -29,13 +29,13 @@
import java.util.List;
/**
- * The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)}
+ * The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
* call. This class allows getting the token for querying the next batch of messages in order to
* prevent handling large amounts of data at once.
*
- * @hide
+ * @hide - TODO: make public
*/
-public class RcsMessageQueryResult implements Parcelable {
+public final class RcsMessageQueryResult implements Parcelable {
// The token to continue the query to get the next batch of results
private RcsQueryContinuationToken mContinuationToken;
// The message type and message ID pairs for all the messages in this query result
@@ -83,7 +83,7 @@
return messages;
}
- protected RcsMessageQueryResult(Parcel in) {
+ private RcsMessageQueryResult(Parcel in) {
mContinuationToken = in.readParcelable(
RcsQueryContinuationToken.class.getClassLoader());
in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
diff --git a/telephony/java/android/telephony/ims/RcsMessageSnippet.java b/telephony/java/android/telephony/ims/RcsMessageSnippet.java
index 9399c20..565bb99 100644
--- a/telephony/java/android/telephony/ims/RcsMessageSnippet.java
+++ b/telephony/java/android/telephony/ims/RcsMessageSnippet.java
@@ -24,9 +24,9 @@
/**
* An immutable summary of the latest {@link RcsMessage} on an {@link RcsThread}
*
- * @hide TODO: make public
+ * @hide - TODO: make public
*/
-public class RcsMessageSnippet implements Parcelable {
+public final class RcsMessageSnippet implements Parcelable {
private final String mText;
private final @RcsMessageStatus int mStatus;
private final long mTimestamp;
@@ -65,7 +65,7 @@
return mTimestamp;
}
- protected RcsMessageSnippet(Parcel in) {
+ private RcsMessageSnippet(Parcel in) {
mText = in.readString();
mStatus = in.readInt();
mTimestamp = in.readLong();
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index c8c36a8..eca5ed5 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -27,7 +27,7 @@
* RcsMessageStore is the application interface to RcsProvider and provides access methods to
* RCS related database tables.
*
- * @hide - TODO make this public
+ * @hide - TODO: make public
*/
public class RcsMessageStore {
/**
@@ -39,7 +39,7 @@
*/
@WorkerThread
@NonNull
- public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParameters queryParameters)
+ public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParams queryParameters)
throws RcsMessageStoreException {
return RcsControllerCall.call(iRcs -> iRcs.getRcsThreads(queryParameters));
}
@@ -68,7 +68,7 @@
@WorkerThread
@NonNull
public RcsParticipantQueryResult getRcsParticipants(
- @Nullable RcsParticipantQueryParameters queryParameters)
+ @Nullable RcsParticipantQueryParams queryParameters)
throws RcsMessageStoreException {
return RcsControllerCall.call(iRcs -> iRcs.getParticipants(queryParameters));
}
@@ -99,7 +99,7 @@
@WorkerThread
@NonNull
public RcsMessageQueryResult getRcsMessages(
- @Nullable RcsMessageQueryParameters queryParameters) throws RcsMessageStoreException {
+ @Nullable RcsMessageQueryParams queryParameters) throws RcsMessageStoreException {
return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
}
@@ -127,7 +127,7 @@
@WorkerThread
@NonNull
public RcsEventQueryResult getRcsEvents(
- @Nullable RcsEventQueryParameters queryParameters) throws RcsMessageStoreException {
+ @Nullable RcsEventQueryParams queryParameters) throws RcsMessageStoreException {
return RcsControllerCall.call(iRcs -> iRcs.getEvents(queryParameters));
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStoreException.java b/telephony/java/android/telephony/ims/RcsMessageStoreException.java
index e158f1a..7c00749 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStoreException.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStoreException.java
@@ -20,7 +20,7 @@
* An exception that happened on {@link RcsMessageStore} or one of the derived storage classes in
* {@link android.telephony.ims}
*
- * @hide TODO: make public
+ * @hide - TODO: make public
*/
public class RcsMessageStoreException extends Exception {
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
index 0bd55ec..dfcdee4 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
@@ -24,7 +24,7 @@
/**
* This is a single instance of a message sent over RCS.
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public class RcsOutgoingMessage extends RcsMessage {
RcsOutgoingMessage(int id) {
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl
similarity index 93%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl
index 52e73ce..0c38d9f 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsThreadQueryParameters;
+parcelable RcsOutgoingMessageCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
new file mode 100644
index 0000000..ca466e8
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@link RcsOutgoingMessageCreationParams} is a collection of parameters that should be passed
+ * into {@link RcsThread#addOutgoingMessage(RcsOutgoingMessageCreationParams)} to generate an
+ * {@link RcsOutgoingMessage} on that {@link RcsThread}
+ *
+ * @hide - TODO: make public
+ */
+public final class RcsOutgoingMessageCreationParams extends RcsMessageCreationParams
+ implements Parcelable {
+ /**
+ * A builder to instantiate and persist an {@link RcsOutgoingMessage}
+ */
+ public static class Builder extends RcsMessageCreationParams.Builder {
+
+ /**
+ * Creates a new {@link Builder} to create an instance of
+ * {@link RcsOutgoingMessageCreationParams}.
+ *
+ * @param originationTimestamp The timestamp of {@link RcsMessage} creation. The origination
+ * timestamp value in milliseconds passed after midnight,
+ * January 1, 1970 UTC
+ * @param subscriptionId The subscription ID that was used to send or receive this
+ * {@link RcsMessage}
+ * @see android.telephony.SubscriptionInfo#getSubscriptionId()
+ */
+ public Builder(long originationTimestamp, int subscriptionId) {
+ super(originationTimestamp, subscriptionId);
+ }
+
+ /**
+ * Creates configuration parameters for a new message.
+ */
+ public RcsOutgoingMessageCreationParams build() {
+ return new RcsOutgoingMessageCreationParams(this);
+ }
+ }
+
+ private RcsOutgoingMessageCreationParams(Builder builder) {
+ super(builder);
+ }
+
+ private RcsOutgoingMessageCreationParams(Parcel in) {
+ super(in);
+ }
+
+ public static final Creator<RcsOutgoingMessageCreationParams> CREATOR =
+ new Creator<RcsOutgoingMessageCreationParams>() {
+ @Override
+ public RcsOutgoingMessageCreationParams createFromParcel(Parcel in) {
+ return new RcsOutgoingMessageCreationParams(in);
+ }
+
+ @Override
+ public RcsOutgoingMessageCreationParams[] newArray(int size) {
+ return new RcsOutgoingMessageCreationParams[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
index b93f892..5a3062a 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
@@ -22,7 +22,7 @@
* This class holds the delivery information of an {@link RcsOutgoingMessage} for each
* {@link RcsParticipant} that the message was intended for.
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public class RcsOutgoingMessageDelivery {
// The participant that this delivery is intended for
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
index ce0ad2c..37b827b 100644
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ b/telephony/java/android/telephony/ims/RcsParticipant.java
@@ -21,7 +21,7 @@
/**
* RcsParticipant is an RCS capable contact that can participate in {@link RcsThread}s.
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public class RcsParticipant {
// The row ID of this participant in the database
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
index 04cdf86..aa278b3 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
@@ -18,18 +18,19 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* An event that indicates an {@link RcsParticipant}'s alias was changed. Please see US18-2 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
-public class RcsParticipantAliasChangedEvent extends RcsEvent {
+public final class RcsParticipantAliasChangedEvent extends RcsEvent implements Parcelable {
// The ID of the participant that changed their alias
- private int mParticipantId;
+ private final int mParticipantId;
// The new alias of the above participant
- private String mNewAlias;
+ private final String mNewAlias;
/**
* Creates a new {@link RcsParticipantAliasChangedEvent}. This event is not persisted into
@@ -98,7 +99,7 @@
}
};
- protected RcsParticipantAliasChangedEvent(Parcel in) {
+ private RcsParticipantAliasChangedEvent(Parcel in) {
super(in);
mNewAlias = in.readString();
mParticipantId = in.readInt();
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.aidl
deleted file mode 100644
index ea8288c..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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.telephony.ims;
-
-parcelable RcsParticipantQueryParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl
similarity index 94%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl
index 52e73ce..b7c0f93 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsThreadQueryParameters;
+parcelable RcsParticipantQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.java b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
similarity index 89%
rename from telephony/java/android/telephony/ims/RcsParticipantQueryParameters.java
rename to telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
index 3611fc1..57c67fa 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
@@ -28,12 +28,12 @@
/**
* The parameters to pass into
- * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParameters)} in order to select a
+ * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)} in order to select a
* subset of {@link RcsThread}s present in the message store.
*
- * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ * @hide - TODO: make public
*/
-public class RcsParticipantQueryParameters implements Parcelable {
+public final class RcsParticipantQueryParams implements Parcelable {
/**
* Flag to set with {@link Builder#setSortProperty(int)} to sort the results in the order of
* creation time for faster query results
@@ -75,7 +75,7 @@
*/
public static final String PARTICIPANT_QUERY_PARAMETERS_KEY = "participant_query_parameters";
- RcsParticipantQueryParameters(int rcsThreadId, String aliasLike, String canonicalAddressLike,
+ RcsParticipantQueryParams(int rcsThreadId, String aliasLike, String canonicalAddressLike,
@SortingProperty int sortingProperty, boolean isAscending,
int limit) {
mThreadId = rcsThreadId;
@@ -143,7 +143,7 @@
}
/**
- * A helper class to build the {@link RcsParticipantQueryParameters}.
+ * A helper class to build the {@link RcsParticipantQueryParams}.
*/
public static class Builder {
private String mAliasLike;
@@ -154,8 +154,8 @@
private int mThreadId;
/**
- * Creates a new builder for {@link RcsParticipantQueryParameters} to be used in
- * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParameters)}
+ * Creates a new builder for {@link RcsParticipantQueryParams} to be used in
+ * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
*/
public Builder() {
// empty implementation
@@ -231,7 +231,7 @@
/**
* Sets the property where the results should be sorted against. Defaults to
- * {@link RcsParticipantQueryParameters.SortingProperty#SORT_BY_CREATION_ORDER}
+ * {@link RcsParticipantQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
*
* @param sortingProperty against which property the results should be sorted
* @return The same instance of the builder to chain parameters.
@@ -255,14 +255,14 @@
}
/**
- * Builds the {@link RcsParticipantQueryParameters} to use in
- * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParameters)}
+ * Builds the {@link RcsParticipantQueryParams} to use in
+ * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
*
- * @return An instance of {@link RcsParticipantQueryParameters} to use with the participant
+ * @return An instance of {@link RcsParticipantQueryParams} to use with the participant
* query.
*/
- public RcsParticipantQueryParameters build() {
- return new RcsParticipantQueryParameters(mThreadId, mAliasLike, mCanonicalAddressLike,
+ public RcsParticipantQueryParams build() {
+ return new RcsParticipantQueryParams(mThreadId, mAliasLike, mCanonicalAddressLike,
mSortingProperty, mIsAscending, mLimit);
}
}
@@ -270,7 +270,7 @@
/**
* Parcelable boilerplate below.
*/
- protected RcsParticipantQueryParameters(Parcel in) {
+ private RcsParticipantQueryParams(Parcel in) {
mAliasLike = in.readString();
mCanonicalAddressLike = in.readString();
mSortingProperty = in.readInt();
@@ -279,16 +279,16 @@
mThreadId = in.readInt();
}
- public static final Creator<RcsParticipantQueryParameters> CREATOR =
- new Creator<RcsParticipantQueryParameters>() {
+ public static final Creator<RcsParticipantQueryParams> CREATOR =
+ new Creator<RcsParticipantQueryParams>() {
@Override
- public RcsParticipantQueryParameters createFromParcel(Parcel in) {
- return new RcsParticipantQueryParameters(in);
+ public RcsParticipantQueryParams createFromParcel(Parcel in) {
+ return new RcsParticipantQueryParams(in);
}
@Override
- public RcsParticipantQueryParameters[] newArray(int size) {
- return new RcsParticipantQueryParameters[size];
+ public RcsParticipantQueryParams[] newArray(int size) {
+ return new RcsParticipantQueryParams[size];
}
};
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
index 2f4ab46..4eae39d 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
@@ -25,13 +25,13 @@
import java.util.List;
/**
- * The result of a {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParameters)}
+ * The result of a {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
* call. This class allows getting the token for querying the next batch of participants in order to
* prevent handling large amounts of data at once.
*
- * @hide
+ * @hide - TODO: make public
*/
-public class RcsParticipantQueryResult implements Parcelable {
+public final class RcsParticipantQueryResult implements Parcelable {
// A token for the caller to continue their query for the next batch of results
private RcsQueryContinuationToken mContinuationToken;
// The list of participant IDs returned with this query
@@ -75,7 +75,7 @@
return participantList;
}
- protected RcsParticipantQueryResult(Parcel in) {
+ private RcsParticipantQueryResult(Parcel in) {
mContinuationToken = in.readParcelable(
RcsQueryContinuationToken.class.getClassLoader());
}
diff --git a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java b/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
index e880651..c1ff396 100644
--- a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
+++ b/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
@@ -24,11 +24,17 @@
import java.lang.annotation.RetentionPolicy;
/**
- * This interface allows using the same implementation for continuation token usage in
- * {@link com.android.providers.telephony.RcsProvider}
- * @hide - TODO make getQueryType() and types public - the rest should stay internal
+ * A token for enabling continuation queries. Instances are acquired through
+ * {@code getContinuationToken} on result objects after initial query is done.
+ *
+ * @see RcsEventQueryResult#getContinuationToken()
+ * @see RcsMessageQueryResult#getContinuationToken()
+ * @see RcsParticipantQueryResult#getContinuationToken()
+ * @see RcsThreadQueryResult#getContinuationToken()
+ *
+ * @hide - TODO: make public
*/
-public class RcsQueryContinuationToken implements Parcelable {
+public final class RcsQueryContinuationToken implements Parcelable {
/**
* Denotes that this {@link RcsQueryContinuationToken} token is meant to allow continuing
* {@link RcsEvent} queries
@@ -116,7 +122,7 @@
return mQueryType;
}
- protected RcsQueryContinuationToken(Parcel in) {
+ private RcsQueryContinuationToken(Parcel in) {
mQueryType = in.readInt();
mRawQuery = in.readString();
mLimit = in.readInt();
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
index 238f5e7..8865586 100644
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -28,10 +28,13 @@
* RcsThread represents a single RCS conversation thread. It holds messages that were sent and
* received and events that occurred on that thread.
*
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
*/
public abstract class RcsThread {
- // The rcs_participant_thread_id that represents this thread in the database
+ /**
+ * The rcs_participant_thread_id that represents this thread in the database
+ * @hide
+ */
protected int mThreadId;
/**
@@ -59,10 +62,10 @@
@WorkerThread
@NonNull
public RcsIncomingMessage addIncomingMessage(
- @NonNull RcsIncomingMessageCreationParameters rcsIncomingMessageCreationParameters)
+ @NonNull RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams)
throws RcsMessageStoreException {
return new RcsIncomingMessage(RcsControllerCall.call(iRcs -> iRcs.addIncomingMessage(
- mThreadId, rcsIncomingMessageCreationParameters)));
+ mThreadId, rcsIncomingMessageCreationParams)));
}
/**
@@ -73,10 +76,10 @@
@WorkerThread
@NonNull
public RcsOutgoingMessage addOutgoingMessage(
- @NonNull RcsMessageCreationParameters rcsMessageCreationParameters)
+ @NonNull RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams)
throws RcsMessageStoreException {
int messageId = RcsControllerCall.call(iRcs -> iRcs.addOutgoingMessage(
- mThreadId, rcsMessageCreationParameters));
+ mThreadId, rcsOutgoingMessageCreationParams));
return new RcsOutgoingMessage(messageId);
}
@@ -97,7 +100,7 @@
/**
* Convenience function for loading all the {@link RcsMessage}s in this {@link RcsThread}. For
* a more detailed and paginated query, please use
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)}
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
*
* @return Loads the {@link RcsMessage}s in this thread and returns them in an immutable list.
* @throws RcsMessageStoreException if the messages could not be read from the storage
@@ -105,8 +108,8 @@
@WorkerThread
@NonNull
public RcsMessageQueryResult getMessages() throws RcsMessageStoreException {
- RcsMessageQueryParameters queryParameters =
- new RcsMessageQueryParameters.Builder().setThread(this).build();
+ RcsMessageQueryParams queryParameters =
+ new RcsMessageQueryParams.Builder().setThread(this).build();
return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
}
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl
similarity index 94%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl
index 52e73ce..3f351dc 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsThreadQueryParameters;
+parcelable RcsThreadQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.java b/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
similarity index 86%
rename from telephony/java/android/telephony/ims/RcsThreadQueryParameters.java
rename to telephony/java/android/telephony/ims/RcsThreadQueryParams.java
index 4aa4207..ba32e32 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
@@ -33,22 +33,22 @@
import java.util.Set;
/**
- * The parameters to pass into {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)} in
+ * The parameters to pass into {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} in
* order to select a subset of {@link RcsThread}s present in the message store.
*
- * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ * @hide - TODO: make public
*/
-public class RcsThreadQueryParameters implements Parcelable {
+public final class RcsThreadQueryParams implements Parcelable {
/**
* Bitmask flag to be used with {@link Builder#setThreadType(int)} to make
- * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)} return
+ * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} return
* {@link RcsGroupThread}s.
*/
public static final int THREAD_TYPE_GROUP = 0x0001;
/**
* Bitmask flag to be used with {@link Builder#setThreadType(int)} to make
- * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)} return
+ * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} return
* {@link Rcs1To1Thread}s.
*/
public static final int THREAD_TYPE_1_TO_1 = 0x0002;
@@ -86,7 +86,7 @@
*/
public static final String THREAD_QUERY_PARAMETERS_KEY = "thread_query_parameters";
- RcsThreadQueryParameters(int threadType, Set<RcsParticipant> participants,
+ RcsThreadQueryParams(int threadType, Set<RcsParticipant> participants,
int limit, int sortingProperty, boolean isAscending) {
mThreadType = threadType;
mRcsParticipantIds = convertParticipantSetToIdList(participants);
@@ -148,7 +148,7 @@
}
/**
- * A helper class to build the {@link RcsThreadQueryParameters}.
+ * A helper class to build the {@link RcsThreadQueryParams}.
*/
public static class Builder {
private int mThreadType;
@@ -158,8 +158,8 @@
private boolean mIsAscending;
/**
- * Constructs a {@link RcsThreadQueryParameters.Builder} to help build an
- * {@link RcsThreadQueryParameters}
+ * Constructs a {@link RcsThreadQueryParams.Builder} to help build an
+ * {@link RcsThreadQueryParams}
*/
public Builder() {
mParticipants = new HashSet<>();
@@ -170,8 +170,8 @@
*
* @param threadType Whether to limit the query result to group threads.
* @return The same instance of the builder to chain parameters.
- * @see RcsThreadQueryParameters#THREAD_TYPE_GROUP
- * @see RcsThreadQueryParameters#THREAD_TYPE_1_TO_1
+ * @see RcsThreadQueryParams#THREAD_TYPE_GROUP
+ * @see RcsThreadQueryParams#THREAD_TYPE_1_TO_1
*/
@CheckResult
public Builder setThreadType(int threadType) {
@@ -253,13 +253,13 @@
}
/**
- * Builds the {@link RcsThreadQueryParameters} to use in
- * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)}
+ * Builds the {@link RcsThreadQueryParams} to use in
+ * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)}
*
- * @return An instance of {@link RcsThreadQueryParameters} to use with the thread query.
+ * @return An instance of {@link RcsThreadQueryParams} to use with the thread query.
*/
- public RcsThreadQueryParameters build() {
- return new RcsThreadQueryParameters(mThreadType, mParticipants, mLimit,
+ public RcsThreadQueryParams build() {
+ return new RcsThreadQueryParams(mThreadType, mParticipants, mLimit,
mSortingProperty, mIsAscending);
}
}
@@ -267,7 +267,7 @@
/**
* Parcelable boilerplate below.
*/
- protected RcsThreadQueryParameters(Parcel in) {
+ private RcsThreadQueryParams(Parcel in) {
mThreadType = in.readInt();
mRcsParticipantIds = new ArrayList<>();
in.readList(mRcsParticipantIds, Integer.class.getClassLoader());
@@ -276,16 +276,16 @@
mIsAscending = in.readByte() == 1;
}
- public static final Creator<RcsThreadQueryParameters> CREATOR =
- new Creator<RcsThreadQueryParameters>() {
+ public static final Creator<RcsThreadQueryParams> CREATOR =
+ new Creator<RcsThreadQueryParams>() {
@Override
- public RcsThreadQueryParameters createFromParcel(Parcel in) {
- return new RcsThreadQueryParameters(in);
+ public RcsThreadQueryParams createFromParcel(Parcel in) {
+ return new RcsThreadQueryParams(in);
}
@Override
- public RcsThreadQueryParameters[] newArray(int size) {
- return new RcsThreadQueryParameters[size];
+ public RcsThreadQueryParams[] newArray(int size) {
+ return new RcsThreadQueryParams[size];
}
};
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
index 6515933..a91126b 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
@@ -29,13 +29,13 @@
import java.util.List;
/**
- * The result of a {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)}
+ * The result of a {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)}
* call. This class allows getting the token for querying the next batch of threads in order to
* prevent handling large amounts of data at once.
*
- * @hide
+ * @hide - TODO: make public
*/
-public class RcsThreadQueryResult implements Parcelable {
+public final class RcsThreadQueryResult implements Parcelable {
// A token for the caller to continue their query for the next batch of results
private RcsQueryContinuationToken mContinuationToken;
// The list of thread IDs returned with this query
@@ -84,7 +84,7 @@
return rcsThreads;
}
- protected RcsThreadQueryResult(Parcel in) {
+ private RcsThreadQueryResult(Parcel in) {
mContinuationToken = in.readParcelable(
RcsQueryContinuationToken.class.getClassLoader());
mRcsThreadIds = new ArrayList<>();
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
index a399786..2478f8c 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -17,18 +17,18 @@
package android.telephony.ims.aidl;
import android.net.Uri;
-import android.telephony.ims.RcsEventQueryParameters;
+import android.telephony.ims.RcsEventQueryParams;
import android.telephony.ims.RcsEventQueryResult;
-import android.telephony.ims.RcsFileTransferCreationParameters;
-import android.telephony.ims.RcsIncomingMessageCreationParameters;
-import android.telephony.ims.RcsMessageCreationParameters;
+import android.telephony.ims.RcsFileTransferCreationParams;
+import android.telephony.ims.RcsIncomingMessageCreationParams;
import android.telephony.ims.RcsMessageSnippet;
-import android.telephony.ims.RcsMessageQueryParameters;
+import android.telephony.ims.RcsMessageQueryParams;
import android.telephony.ims.RcsMessageQueryResult;
-import android.telephony.ims.RcsParticipantQueryParameters;
+import android.telephony.ims.RcsOutgoingMessageCreationParams;
+import android.telephony.ims.RcsParticipantQueryParams;
import android.telephony.ims.RcsParticipantQueryResult;
import android.telephony.ims.RcsQueryContinuationToken;
-import android.telephony.ims.RcsThreadQueryParameters;
+import android.telephony.ims.RcsThreadQueryParams;
import android.telephony.ims.RcsThreadQueryResult;
/**
@@ -39,22 +39,22 @@
/////////////////////////
// RcsMessageStore APIs
/////////////////////////
- RcsThreadQueryResult getRcsThreads(in RcsThreadQueryParameters queryParameters);
+ RcsThreadQueryResult getRcsThreads(in RcsThreadQueryParams queryParams);
RcsThreadQueryResult getRcsThreadsWithToken(
in RcsQueryContinuationToken continuationToken);
- RcsParticipantQueryResult getParticipants(in RcsParticipantQueryParameters queryParameters);
+ RcsParticipantQueryResult getParticipants(in RcsParticipantQueryParams queryParams);
RcsParticipantQueryResult getParticipantsWithToken(
in RcsQueryContinuationToken continuationToken);
- RcsMessageQueryResult getMessages(in RcsMessageQueryParameters queryParameters);
+ RcsMessageQueryResult getMessages(in RcsMessageQueryParams queryParams);
RcsMessageQueryResult getMessagesWithToken(
in RcsQueryContinuationToken continuationToken);
- RcsEventQueryResult getEvents(in RcsEventQueryParameters queryParameters);
+ RcsEventQueryResult getEvents(in RcsEventQueryParams queryParams);
RcsEventQueryResult getEventsWithToken(
in RcsQueryContinuationToken continuationToken);
@@ -74,11 +74,11 @@
// Creates a new RcsIncomingMessage on the given thread and returns its row ID
int addIncomingMessage(int rcsThreadId,
- in RcsIncomingMessageCreationParameters rcsIncomingMessageCreationParameters);
+ in RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams);
// Creates a new RcsOutgoingMessage on the given thread and returns its row ID
int addOutgoingMessage(int rcsThreadId,
- in RcsMessageCreationParameters rcsMessageCreationParameters);
+ in RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams);
// TODO: modify RcsProvider URI's to allow deleting a message without specifying its thread
void deleteMessage(int rcsMessageId, boolean isIncoming, int rcsThreadId, boolean isGroup);
@@ -203,7 +203,7 @@
// Performs the initial write to storage and returns the row ID.
int storeFileTransfer(int messageId, boolean isIncoming,
- in RcsFileTransferCreationParameters fileTransferCreationParameters);
+ in RcsFileTransferCreationParams fileTransferCreationParams);
void deleteFileTransfer(int partId);
diff --git a/test-base/api/TEST_MAPPING b/test-base/api/TEST_MAPPING
new file mode 100644
index 0000000..3535954
--- /dev/null
+++ b/test-base/api/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAndroidTestBase27ApiSignatureTestCases"
+ }
+ ]
+}
diff --git a/test-mock/api/TEST_MAPPING b/test-mock/api/TEST_MAPPING
new file mode 100644
index 0000000..d1bd9af
--- /dev/null
+++ b/test-mock/api/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAndroidTestMockCurrentApiSignatureTestCases"
+ },
+ {
+ "name": "CtsCurrentApiSignatureTestCases"
+ }
+ ]
+}
diff --git a/test-runner/api/TEST_MAPPING b/test-runner/api/TEST_MAPPING
new file mode 100644
index 0000000..76ade3c
--- /dev/null
+++ b/test-runner/api/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAndroidTestRunnerCurrentApiSignatureTestCases"
+ },
+ {
+ "name": "CtsCurrentApiSignatureTestCases"
+ }
+ ]
+}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParametersTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParametersTest.java
deleted file mode 100644
index b4bcb5d..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParametersTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsParticipantQueryParameters;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsParticipantQueryParametersTest {
-
- @Test
- public void testCanUnparcel() {
- RcsParticipantQueryParameters rcsParticipantQueryParameters =
- new RcsParticipantQueryParameters.Builder()
- .setAliasLike("%alias_")
- .setCanonicalAddressLike("_canonical%")
- .setSortProperty(RcsParticipantQueryParameters.SORT_BY_CANONICAL_ADDRESS)
- .setSortDirection(true)
- .setResultLimit(432)
- .build();
-
-
- Parcel parcel = Parcel.obtain();
- rcsParticipantQueryParameters.writeToParcel(parcel,
- rcsParticipantQueryParameters.describeContents());
-
- parcel.setDataPosition(0);
- rcsParticipantQueryParameters = RcsParticipantQueryParameters.CREATOR.createFromParcel(
- parcel);
-
- assertThat(rcsParticipantQueryParameters.getAliasLike()).isEqualTo("%alias_");
- assertThat(rcsParticipantQueryParameters.getCanonicalAddressLike()).contains("_canonical%");
- assertThat(rcsParticipantQueryParameters.getLimit()).isEqualTo(432);
- assertThat(rcsParticipantQueryParameters.getSortingProperty()).isEqualTo(
- RcsParticipantQueryParameters.SORT_BY_CANONICAL_ADDRESS);
- assertThat(rcsParticipantQueryParameters.getSortDirection()).isTrue();
- }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
new file mode 100644
index 0000000..6361a39
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.ims;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.ims.RcsParticipantQueryParams;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsParticipantQueryParamsTest {
+
+ @Test
+ public void testCanUnparcel() {
+ RcsParticipantQueryParams rcsParticipantQueryParams =
+ new RcsParticipantQueryParams.Builder()
+ .setAliasLike("%alias_")
+ .setCanonicalAddressLike("_canonical%")
+ .setSortProperty(RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS)
+ .setSortDirection(true)
+ .setResultLimit(432)
+ .build();
+
+
+ Parcel parcel = Parcel.obtain();
+ rcsParticipantQueryParams.writeToParcel(parcel,
+ rcsParticipantQueryParams.describeContents());
+
+ parcel.setDataPosition(0);
+ rcsParticipantQueryParams = RcsParticipantQueryParams.CREATOR.createFromParcel(
+ parcel);
+
+ assertThat(rcsParticipantQueryParams.getAliasLike()).isEqualTo("%alias_");
+ assertThat(rcsParticipantQueryParams.getCanonicalAddressLike()).contains("_canonical%");
+ assertThat(rcsParticipantQueryParams.getLimit()).isEqualTo(432);
+ assertThat(rcsParticipantQueryParams.getSortingProperty()).isEqualTo(
+ RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS);
+ assertThat(rcsParticipantQueryParams.getSortDirection()).isTrue();
+ }
+}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java
deleted file mode 100644
index 0a70eec..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static android.telephony.ims.RcsThreadQueryParameters.SORT_BY_TIMESTAMP;
-import static android.telephony.ims.RcsThreadQueryParameters.THREAD_TYPE_GROUP;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsParticipant;
-import android.telephony.ims.RcsThreadQueryParameters;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsThreadQueryParametersTest {
-
- @Test
- public void testCanUnparcel() {
- RcsParticipant rcsParticipant = new RcsParticipant(1);
- RcsThreadQueryParameters rcsThreadQueryParameters = new RcsThreadQueryParameters.Builder()
- .setThreadType(THREAD_TYPE_GROUP)
- .setParticipant(rcsParticipant)
- .setResultLimit(50)
- .setSortProperty(SORT_BY_TIMESTAMP)
- .setSortDirection(true)
- .build();
-
- Parcel parcel = Parcel.obtain();
- rcsThreadQueryParameters.writeToParcel(parcel, rcsThreadQueryParameters.describeContents());
-
- parcel.setDataPosition(0);
- rcsThreadQueryParameters = RcsThreadQueryParameters.CREATOR.createFromParcel(parcel);
-
- assertThat(rcsThreadQueryParameters.getThreadType()).isEqualTo(THREAD_TYPE_GROUP);
- assertThat(rcsThreadQueryParameters.getRcsParticipantsIds())
- .contains(rcsParticipant.getId());
- assertThat(rcsThreadQueryParameters.getLimit()).isEqualTo(50);
- assertThat(rcsThreadQueryParameters.getSortingProperty()).isEqualTo(SORT_BY_TIMESTAMP);
- assertThat(rcsThreadQueryParameters.getSortDirection()).isTrue();
- }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
new file mode 100644
index 0000000..beb4f8a
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.ims;
+
+import static android.telephony.ims.RcsThreadQueryParams.SORT_BY_TIMESTAMP;
+import static android.telephony.ims.RcsThreadQueryParams.THREAD_TYPE_GROUP;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.ims.RcsParticipant;
+import android.telephony.ims.RcsThreadQueryParams;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsThreadQueryParamsTest {
+
+ @Test
+ public void testCanUnparcel() {
+ RcsParticipant rcsParticipant = new RcsParticipant(1);
+ RcsThreadQueryParams rcsThreadQueryParams = new RcsThreadQueryParams.Builder()
+ .setThreadType(THREAD_TYPE_GROUP)
+ .setParticipant(rcsParticipant)
+ .setResultLimit(50)
+ .setSortProperty(SORT_BY_TIMESTAMP)
+ .setSortDirection(true)
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ rcsThreadQueryParams.writeToParcel(parcel, rcsThreadQueryParams.describeContents());
+
+ parcel.setDataPosition(0);
+ rcsThreadQueryParams = RcsThreadQueryParams.CREATOR.createFromParcel(parcel);
+
+ assertThat(rcsThreadQueryParams.getThreadType()).isEqualTo(THREAD_TYPE_GROUP);
+ assertThat(rcsThreadQueryParams.getRcsParticipantsIds())
+ .contains(rcsParticipant.getId());
+ assertThat(rcsThreadQueryParams.getLimit()).isEqualTo(50);
+ assertThat(rcsThreadQueryParams.getSortingProperty()).isEqualTo(SORT_BY_TIMESTAMP);
+ assertThat(rcsThreadQueryParams.getSortDirection()).isTrue();
+ }
+}
diff --git a/tests/utils/testutils/java/android/view/test/InsetsModeSession.java b/tests/utils/testutils/java/android/view/test/InsetsModeSession.java
new file mode 100644
index 0000000..c83dfa4
--- /dev/null
+++ b/tests/utils/testutils/java/android/view/test/InsetsModeSession.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.test;
+
+import android.view.ViewRootImpl;
+
+/**
+ * Session to set insets mode for {@link ViewRootImpl#sNewInsetsMode}.
+ */
+public class InsetsModeSession implements AutoCloseable {
+
+ private int mOldMode;
+
+ public InsetsModeSession(int flag) {
+ mOldMode = ViewRootImpl.sNewInsetsMode;
+ ViewRootImpl.sNewInsetsMode = flag;
+ }
+
+ @Override
+ public void close() throws Exception {
+ ViewRootImpl.sNewInsetsMode = mOldMode;
+ }
+}
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 55440d2..0270c72 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -688,7 +688,7 @@
build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
size_t i = 0;
- // Print constants
+ // Print atom constants
for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
atom != atoms.decls.end(); atom++) {
string constant = make_constant_name(atom->name);
@@ -714,6 +714,30 @@
fprintf(out, "};\n");
fprintf(out, "\n");
+ // Print constants for the enum values.
+ fprintf(out, "//\n");
+ fprintf(out, "// Constants for enum values\n");
+ fprintf(out, "//\n\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ for (vector<AtomField>::const_iterator field = atom->fields.begin();
+ field != atom->fields.end(); field++) {
+ if (field->javaType == JAVA_TYPE_ENUM) {
+ fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
+ field->name.c_str());
+ for (map<int, string>::const_iterator value = field->enumValues.begin();
+ value != field->enumValues.end(); value++) {
+ fprintf(out, "const int32_t %s__%s__%s = %d;\n",
+ make_constant_name(atom->message).c_str(),
+ make_constant_name(field->name).c_str(),
+ make_constant_name(value->second).c_str(),
+ value->first);
+ }
+ fprintf(out, "\n");
+ }
+ }
+ }
+
fprintf(out, "struct BytesField {\n");
fprintf(out,
" BytesField(char const* array, size_t len) : arg(array), "
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index c5b9cf1..3881e9e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -969,7 +969,8 @@
/**
* Returns MAC address set to be the local randomized MAC address.
- * Does not guarantee that the returned address is valid for use.
+ * Depending on user preference, the device may or may not use the returned MAC address for
+ * connections to this network.
* <p>
* Information is restricted to Device Owner, Profile Owner, and Carrier apps
* (which will only obtain addresses for configurations which they create). Other callers
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 289f99d..2cc1d83 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -981,7 +981,7 @@
* @deprecated This API is non-functional and will have no impact.
*/
@Deprecated
- public static final int WIFI_MODE_FULL = 1;
+ public static final int WIFI_MODE_FULL = WifiProtoEnums.WIFI_MODE_FULL; // 1
/**
* In this Wi-Fi lock mode, Wi-Fi will be kept active,
@@ -995,7 +995,7 @@
* @deprecated This API is non-functional and will have no impact.
*/
@Deprecated
- public static final int WIFI_MODE_SCAN_ONLY = 2;
+ public static final int WIFI_MODE_SCAN_ONLY = WifiProtoEnums.WIFI_MODE_SCAN_ONLY; // 2
/**
* In this Wi-Fi lock mode, Wi-Fi will not go to power save.
@@ -1013,7 +1013,7 @@
* When there is no support from the hardware, the {@link #WIFI_MODE_FULL_HIGH_PERF}
* lock will have no impact.
*/
- public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
+ public static final int WIFI_MODE_FULL_HIGH_PERF = WifiProtoEnums.WIFI_MODE_FULL_HIGH_PERF; // 3
/**
* In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency.
@@ -1037,15 +1037,13 @@
* Example use cases are real time gaming or virtual reality applications where
* low latency is a key factor for user experience.
* <p>
- * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_LOW_LATENCY}
- * lock will cause the device not to go power save.
- * <p>
* Note: For an app which acquires both {@link #WIFI_MODE_FULL_LOW_LATENCY} and
* {@link #WIFI_MODE_FULL_HIGH_PERF} locks, {@link #WIFI_MODE_FULL_LOW_LATENCY}
* lock will be effective when app is running in foreground and screen is on,
* while the {@link #WIFI_MODE_FULL_HIGH_PERF} lock will take effect otherwise.
*/
- public static final int WIFI_MODE_FULL_LOW_LATENCY = 4;
+ public static final int WIFI_MODE_FULL_LOW_LATENCY =
+ WifiProtoEnums.WIFI_MODE_FULL_LOW_LATENCY; // 4
/** Anything worse than or equal to this will show 0 bars. */
@UnsupportedAppUsage
@@ -4876,4 +4874,4 @@
throw e.rethrowFromSystemServer();
}
}
-}
\ No newline at end of file
+}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index a69c7a5..333b82c 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -421,7 +421,7 @@
* .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
* .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"),
* MacAddress.fromString("ff:ff:ff:00:00:00"))
- * .buildNetworkSpecifier()
+ * .build()
* final NetworkRequest request =
* new NetworkRequest.Builder()
* .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 460c633..233fa2c 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -413,17 +413,17 @@
* final WifiNetworkSuggestion suggestion1 =
* new Builder()
* .setSsid("test111111")
- * .buildNetworkSuggestion()
+ * .build()
* final WifiNetworkSuggestion suggestion2 =
* new Builder()
* .setSsid("test222222")
* .setWpa2Passphrase("test123456")
- * .buildNetworkSuggestion()
+ * .build()
* final WifiNetworkSuggestion suggestion3 =
* new Builder()
* .setSsid("test333333")
* .setWpa3Passphrase("test6789")
- * .buildNetworkSuggestion()
+ * .build()
* final List<WifiNetworkSuggestion> suggestionsList =
* new ArrayList<WifiNetworkSuggestion> {{
* add(suggestion1);
diff --git a/wifi/java/android/net/wifi/aware/TlvBufferUtils.java b/wifi/java/android/net/wifi/aware/TlvBufferUtils.java
index 29f10e9..b3b5b29 100644
--- a/wifi/java/android/net/wifi/aware/TlvBufferUtils.java
+++ b/wifi/java/android/net/wifi/aware/TlvBufferUtils.java
@@ -61,6 +61,7 @@
public static class TlvConstructor {
private int mTypeSize;
private int mLengthSize;
+ private ByteOrder mByteOrder = ByteOrder.BIG_ENDIAN;
private byte[] mArray;
private int mArrayLength;
@@ -84,6 +85,20 @@
}
mTypeSize = typeSize;
mLengthSize = lengthSize;
+ mPosition = 0;
+ }
+
+ /**
+ * Configure the TLV constructor to use a particular byte order. Should be
+ * {@link ByteOrder#BIG_ENDIAN} (the default at construction) or
+ * {@link ByteOrder#LITTLE_ENDIAN}.
+ *
+ * @return The constructor to facilitate chaining
+ * {@code ctr.putXXX(..).putXXX(..)}.
+ */
+ public TlvConstructor setByteOrder(ByteOrder byteOrder) {
+ mByteOrder = byteOrder;
+ return this;
}
/**
@@ -96,6 +111,7 @@
public TlvConstructor wrap(@Nullable byte[] array) {
mArray = array;
mArrayLength = (array == null) ? 0 : array.length;
+ mPosition = 0;
return this;
}
@@ -109,6 +125,7 @@
public TlvConstructor allocate(int capacity) {
mArray = new byte[capacity];
mArrayLength = capacity;
+ mPosition = 0;
return this;
}
@@ -155,6 +172,18 @@
}
/**
+ * Copies a raw byte into the TLV buffer - without a type or a length.
+ *
+ * @param b The byte to be inserted into the structure.
+ * @return The constructor to facilitate chaining {@code cts.putXXX(..).putXXX(..)}.
+ */
+ public TlvConstructor putRawByte(byte b) {
+ checkRawLength(1);
+ mArray[mPosition++] = b;
+ return this;
+ }
+
+ /**
* Copies a byte array into the TLV with the indicated type. For an LV
* formatted structure (i.e. typeLength=0 in {@link TlvConstructor
* TlvConstructor(int, int)} ) the type field is ignored.
@@ -193,6 +222,22 @@
}
/**
+ * Copies a byte array into the TLV - without a type or a length.
+ *
+ * @param array The array to be copied (in full) into the TLV structure.
+ * @return The constructor to facilitate chaining
+ * {@code ctr.putXXX(..).putXXX(..)}.
+ */
+ public TlvConstructor putRawByteArray(@Nullable byte[] array) {
+ if (array == null) return this;
+
+ checkRawLength(array.length);
+ System.arraycopy(array, 0, mArray, mPosition, array.length);
+ mPosition += array.length;
+ return this;
+ }
+
+ /**
* Places a zero length element (i.e. Length field = 0) into the TLV.
* For an LV formatted structure (i.e. typeLength=0 in
* {@link TlvConstructor TlvConstructor(int, int)} ) the type field is
@@ -221,7 +266,7 @@
public TlvConstructor putShort(int type, short data) {
checkLength(2);
addHeader(type, 2);
- Memory.pokeShort(mArray, mPosition, data, ByteOrder.BIG_ENDIAN);
+ Memory.pokeShort(mArray, mPosition, data, mByteOrder);
mPosition += 2;
return this;
}
@@ -239,7 +284,7 @@
public TlvConstructor putInt(int type, int data) {
checkLength(4);
addHeader(type, 4);
- Memory.pokeInt(mArray, mPosition, data, ByteOrder.BIG_ENDIAN);
+ Memory.pokeInt(mArray, mPosition, data, mByteOrder);
mPosition += 4;
return this;
}
@@ -294,18 +339,24 @@
}
}
+ private void checkRawLength(int dataLength) {
+ if (mPosition + dataLength > mArrayLength) {
+ throw new BufferOverflowException();
+ }
+ }
+
private void addHeader(int type, int length) {
if (mTypeSize == 1) {
mArray[mPosition] = (byte) type;
} else if (mTypeSize == 2) {
- Memory.pokeShort(mArray, mPosition, (short) type, ByteOrder.BIG_ENDIAN);
+ Memory.pokeShort(mArray, mPosition, (short) type, mByteOrder);
}
mPosition += mTypeSize;
if (mLengthSize == 1) {
mArray[mPosition] = (byte) length;
} else if (mLengthSize == 2) {
- Memory.pokeShort(mArray, mPosition, (short) length, ByteOrder.BIG_ENDIAN);
+ Memory.pokeShort(mArray, mPosition, (short) length, mByteOrder);
}
mPosition += mLengthSize;
}
@@ -330,13 +381,19 @@
public int length;
/**
+ * Control of the endianess of the TLV element - true for big-endian, false for little-
+ * endian.
+ */
+ public ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
+
+ /**
* The Value (V) field - a raw byte array representing the current TLV
* element where the entry starts at {@link TlvElement#offset}.
*/
- public byte[] refArray;
+ private byte[] mRefArray;
/**
- * The offset to be used into {@link TlvElement#refArray} to access the
+ * The offset to be used into {@link TlvElement#mRefArray} to access the
* raw data representing the current TLV element.
*/
public int offset;
@@ -344,7 +401,7 @@
private TlvElement(int type, int length, @Nullable byte[] refArray, int offset) {
this.type = type;
this.length = length;
- this.refArray = refArray;
+ mRefArray = refArray;
this.offset = offset;
if (offset + length > refArray.length) {
@@ -353,6 +410,15 @@
}
/**
+ * Return the raw byte array of the Value (V) field.
+ *
+ * @return The Value (V) field as a byte array.
+ */
+ public byte[] getRawData() {
+ return Arrays.copyOfRange(mRefArray, offset, offset + length);
+ }
+
+ /**
* Utility function to return a byte representation of a TLV element of
* length 1. Note: an attempt to call this function on a TLV item whose
* {@link TlvElement#length} is != 1 will result in an exception.
@@ -364,7 +430,7 @@
throw new IllegalArgumentException(
"Accesing a byte from a TLV element of length " + length);
}
- return refArray[offset];
+ return mRefArray[offset];
}
/**
@@ -379,7 +445,7 @@
throw new IllegalArgumentException(
"Accesing a short from a TLV element of length " + length);
}
- return Memory.peekShort(refArray, offset, ByteOrder.BIG_ENDIAN);
+ return Memory.peekShort(mRefArray, offset, byteOrder);
}
/**
@@ -394,7 +460,7 @@
throw new IllegalArgumentException(
"Accesing an int from a TLV element of length " + length);
}
- return Memory.peekInt(refArray, offset, ByteOrder.BIG_ENDIAN);
+ return Memory.peekInt(mRefArray, offset, byteOrder);
}
/**
@@ -403,7 +469,7 @@
* @return String repersentation of the current TLV element.
*/
public String getString() {
- return new String(refArray, offset, length);
+ return new String(mRefArray, offset, length);
}
}
@@ -413,6 +479,7 @@
public static class TlvIterable implements Iterable<TlvElement> {
private int mTypeSize;
private int mLengthSize;
+ private ByteOrder mByteOrder = ByteOrder.BIG_ENDIAN;
private byte[] mArray;
private int mArrayLength;
@@ -440,6 +507,13 @@
}
/**
+ * Configure the TLV iterator to use little-endian byte ordering.
+ */
+ public void setByteOrder(ByteOrder byteOrder) {
+ mByteOrder = byteOrder;
+ }
+
+ /**
* Prints out a parsed representation of the TLV-formatted byte array.
* Whenever possible bytes, shorts, and integer are printed out (for
* fields whose length is 1, 2, or 4 respectively).
@@ -486,7 +560,7 @@
public List<byte[]> toList() {
List<byte[]> list = new ArrayList<>();
for (TlvElement tlv : this) {
- list.add(Arrays.copyOfRange(tlv.refArray, tlv.offset, tlv.offset + tlv.length));
+ list.add(Arrays.copyOfRange(tlv.mRefArray, tlv.offset, tlv.offset + tlv.length));
}
return list;
@@ -516,7 +590,7 @@
if (mTypeSize == 1) {
type = mArray[mOffset];
} else if (mTypeSize == 2) {
- type = Memory.peekShort(mArray, mOffset, ByteOrder.BIG_ENDIAN);
+ type = Memory.peekShort(mArray, mOffset, mByteOrder);
}
mOffset += mTypeSize;
@@ -524,11 +598,12 @@
if (mLengthSize == 1) {
length = mArray[mOffset];
} else if (mLengthSize == 2) {
- length = Memory.peekShort(mArray, mOffset, ByteOrder.BIG_ENDIAN);
+ length = Memory.peekShort(mArray, mOffset, mByteOrder);
}
mOffset += mLengthSize;
TlvElement tlv = new TlvElement(type, length, mArray, mOffset);
+ tlv.byteOrder = mByteOrder;
mOffset += length;
return tlv;
}
@@ -543,7 +618,8 @@
/**
* Validates that a (T)LV array is constructed correctly. I.e. that its specified Length
- * fields correctly fill the specified length (and do not overshoot).
+ * fields correctly fill the specified length (and do not overshoot). Uses big-endian
+ * byte ordering.
*
* @param array The (T)LV array to verify.
* @param typeSize The size (in bytes) of the type field. Valid values are 0, 1, or 2.
@@ -551,6 +627,22 @@
* @return A boolean indicating whether the array is valid (true) or invalid (false).
*/
public static boolean isValid(@Nullable byte[] array, int typeSize, int lengthSize) {
+ return isValidEndian(array, typeSize, lengthSize, ByteOrder.BIG_ENDIAN);
+ }
+
+ /**
+ * Validates that a (T)LV array is constructed correctly. I.e. that its specified Length
+ * fields correctly fill the specified length (and do not overshoot).
+ *
+ * @param array The (T)LV array to verify.
+ * @param typeSize The size (in bytes) of the type field. Valid values are 0, 1, or 2.
+ * @param lengthSize The size (in bytes) of the length field. Valid values are 1 or 2.
+ * @param byteOrder The endianness of the byte array: {@link ByteOrder#BIG_ENDIAN} or
+ * {@link ByteOrder#LITTLE_ENDIAN}.
+ * @return A boolean indicating whether the array is valid (true) or invalid (false).
+ */
+ public static boolean isValidEndian(@Nullable byte[] array, int typeSize, int lengthSize,
+ ByteOrder byteOrder) {
if (typeSize < 0 || typeSize > 2) {
throw new IllegalArgumentException(
"Invalid arguments - typeSize must be 0, 1, or 2: typeSize=" + typeSize);
@@ -569,8 +661,7 @@
if (lengthSize == 1) {
nextTlvIndex += lengthSize + array[nextTlvIndex];
} else {
- nextTlvIndex += lengthSize + Memory.peekShort(array, nextTlvIndex,
- ByteOrder.BIG_ENDIAN);
+ nextTlvIndex += lengthSize + Memory.peekShort(array, nextTlvIndex, byteOrder);
}
}
diff --git a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
index 83affed..971aa8e 100644
--- a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
@@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.List;
+
/**
* Unit test harness for TlvBufferUtils class.
*/
@@ -69,6 +70,24 @@
}
/**
+ * Validate that re-using a TLV by any of the reallocation method resets it completely.
+ */
+ @Test
+ public void testTlvReuse() {
+ TlvBufferUtils.TlvConstructor tlv = new TlvBufferUtils.TlvConstructor(1, 1);
+
+ tlv.allocate(10);
+ tlv.putByte(0, (byte) 2);
+ tlv.putByte(1, (byte) 104);
+
+ collector.checkThat("initial", tlv.getArray(), equalTo(new byte[]{0, 1, 2, 1, 1, 104}));
+
+ tlv.allocate(8);
+ tlv.putByte(5, (byte) 7);
+ collector.checkThat("re-alloc", tlv.getArray(), equalTo(new byte[]{5, 1, 7}));
+ }
+
+ /**
* Verify that can build a valid TLV from a List of byte[].
*/
@Test
@@ -121,6 +140,23 @@
List<byte[]> data = new TlvBufferUtils.TlvIterable(0, 1, invalidTlv01).toList();
}
+ /**
+ * Validate the API which places raw bytes into the TLV (without a TL structure).
+ */
+ @Test
+ public void testRawPuts() {
+ TlvBufferUtils.TlvConstructor tlv = new TlvBufferUtils.TlvConstructor(1, 1);
+
+ tlv.allocate(10);
+ tlv.putByte(0, (byte) 2);
+ tlv.putRawByte((byte) 55);
+ tlv.putByte(1, (byte) 104);
+ tlv.putRawByteArray(new byte[]{66, 77});
+
+ collector.checkThat("data", tlv.getArray(),
+ equalTo(new byte[]{0, 1, 2, 55, 1, 1, 104, 66, 77}));
+ }
+
@Test
public void testTlvIterate() {
final String ascii = "ABC";
@@ -163,6 +199,7 @@
tlv02.putByte(0, (byte) 2);
tlv02.putString(0, ascii);
tlv02.putString(0, nonAscii);
+ tlv02.putByteArray(0, new byte[]{5, 4, 3, 2, 1});
TlvBufferUtils.TlvIterable tlv02It = new TlvBufferUtils.TlvIterable(0, 2, tlv02.getArray());
count = 0;
@@ -181,6 +218,11 @@
equalTo(nonAscii.getBytes().length));
collector.checkThat("tlv02-correct-iteration-DATA",
tlv.getString().equals(nonAscii), equalTo(true));
+ } else if (count == 3) {
+ collector.checkThat("tlv02-correct-iteration-mLength", tlv.length,
+ equalTo(5));
+ collector.checkThat("tlv02-correct-iteration-DATA", tlv.getRawData(),
+ equalTo(new byte[]{5, 4, 3, 2, 1}));
} else {
collector.checkThat("Invalid number of iterations in loop - tlv02", true,
equalTo(false));
@@ -188,7 +230,7 @@
++count;
}
collector.checkThat("Invalid number of iterations outside loop - tlv02", count,
- equalTo(3));
+ equalTo(4));
collector.checkThat("tlv22-valid",
TlvBufferUtils.isValid(tlv22.getArray(), 2, 2),