diff options
218 files changed, 4144 insertions, 3037 deletions
diff --git a/Android.mk b/Android.mk index 65d4d240fdcd..9c65948f4838 100644 --- a/Android.mk +++ b/Android.mk @@ -79,34 +79,6 @@ update-api: doc-comment-check-docs # ==== hiddenapi lists ======================================= ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true) -.KATI_RESTAT: $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS) -$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \ - PRIVATE_FLAGS_INPUTS := $(PRIVATE_FLAGS_INPUTS) $(SOONG_HIDDENAPI_FLAGS) -$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \ - frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py \ - frameworks/base/config/hiddenapi-greylist.txt \ - frameworks/base/config/hiddenapi-greylist-max-p.txt \ - frameworks/base/config/hiddenapi-greylist-max-o.txt \ - frameworks/base/config/hiddenapi-force-blacklist.txt \ - $(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS) \ - $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE) \ - $(SOONG_HIDDENAPI_FLAGS) - frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py \ - --csv $(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS) $(PRIVATE_FLAGS_INPUTS) \ - --greylist frameworks/base/config/hiddenapi-greylist.txt \ - --greylist-ignore-conflicts $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE) \ - --greylist-max-p frameworks/base/config/hiddenapi-greylist-max-p.txt \ - --greylist-max-o-ignore-conflicts \ - frameworks/base/config/hiddenapi-greylist-max-o.txt \ - --blacklist frameworks/base/config/hiddenapi-force-blacklist.txt \ - --output $@.tmp - $(call commit-change-for-toc,$@) - -$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA): \ - frameworks/base/tools/hiddenapi/merge_csv.py \ - $(PRIVATE_METADATA_INPUTS) - frameworks/base/tools/hiddenapi/merge_csv.py $(PRIVATE_METADATA_INPUTS) > $@ - $(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS)) $(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA)) endif # UNSAFE_DISABLE_HIDDENAPI_FLAGS diff --git a/api/current.txt b/api/current.txt index 8458ed33ad5d..d6f0955dbca9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -224,6 +224,11 @@ package android { public static final class R.attr { ctor public R.attr(); + field public static final int __removed1 = 16844185; // 0x1010599 + field public static final int __removed2 = 16844186; // 0x101059a + field public static final int __removed3 = 16844187; // 0x101059b + field public static final int __removed4 = 16844188; // 0x101059c + field public static final int __removed5 = 16844189; // 0x101059d field public static final int absListViewStyle = 16842858; // 0x101006a field public static final int accessibilityEventTypes = 16843648; // 0x1010380 field public static final int accessibilityFeedbackType = 16843650; // 0x1010382 @@ -484,10 +489,6 @@ package android { field public static final int dashGap = 16843175; // 0x10101a7 field public static final int dashWidth = 16843174; // 0x10101a6 field public static final int data = 16842798; // 0x101002e - field public static final int dataRetentionTime = 16844189; // 0x101059d - field public static final int dataSentOffDevice = 16844186; // 0x101059a - field public static final int dataSharedWithThirdParty = 16844187; // 0x101059b - field public static final int dataUsedForMonetization = 16844188; // 0x101059c field public static final int datePickerDialogTheme = 16843948; // 0x10104ac field public static final int datePickerMode = 16843955; // 0x10104b3 field public static final int datePickerStyle = 16843612; // 0x101035c @@ -1508,7 +1509,6 @@ package android { field @Deprecated public static final int unfocusedMonthDateColor = 16843588; // 0x1010344 field public static final int unselectedAlpha = 16843278; // 0x101020e field public static final int updatePeriodMillis = 16843344; // 0x1010250 - field public static final int usageInfoRequired = 16844185; // 0x1010599 field public static final int use32bitAbi = 16844053; // 0x1010515 field public static final int useAppZygote = 16844184; // 0x1010598 field public static final int useDefaultMargins = 16843641; // 0x1010379 @@ -10265,7 +10265,6 @@ package android.content { field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED"; field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED"; field public static final String ACTION_PASTE = "android.intent.action.PASTE"; - field public static final String ACTION_PERMISSION_USAGE_DETAILS = "android.intent.action.PERMISSION_USAGE_DETAILS"; field public static final String ACTION_PICK = "android.intent.action.PICK"; field public static final String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY"; field public static final String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED"; @@ -10391,7 +10390,6 @@ package android.content { field public static final String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE"; field public static final String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI"; field public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME"; - field public static final String EXTRA_PERMISSION_USAGE_PERMISSIONS = "android.intent.extra.PERMISSION_USAGE_PERMISSIONS"; field public static final String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER"; field public static final String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT"; field public static final String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY"; @@ -11356,8 +11354,8 @@ package android.content.pm { field public android.content.pm.ProviderInfo[] providers; field public android.content.pm.ActivityInfo[] receivers; field public android.content.pm.FeatureInfo[] reqFeatures; - field @Deprecated public String[] requestedPermissions; - field @Deprecated public int[] requestedPermissionsFlags; + field public String[] requestedPermissions; + field public int[] requestedPermissionsFlags; field public android.content.pm.ServiceInfo[] services; field public String sharedUserId; field public int sharedUserLabel; @@ -11365,7 +11363,6 @@ package android.content.pm { field public android.content.pm.SigningInfo signingInfo; field public String[] splitNames; field public int[] splitRevisionCodes; - field public android.content.pm.UsesPermissionInfo[] usesPermissions; field @Deprecated public int versionCode; field public String versionName; } @@ -11865,7 +11862,6 @@ package android.content.pm { field public String group; field public CharSequence nonLocalizedDescription; field @Deprecated public int protectionLevel; - field public boolean usageInfoRequired; } public final class ProviderInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable { @@ -12057,28 +12053,6 @@ package android.content.pm { field public static final android.os.Parcelable.Creator<android.content.pm.SigningInfo> CREATOR; } - public final class UsesPermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { - method public int describeContents(); - method public int getDataRetention(); - method public int getDataRetentionWeeks(); - method public int getDataSentOffDevice(); - method public int getDataSharedWithThirdParty(); - method public int getDataUsedForMonetization(); - method public int getFlags(); - method public String getPermission(); - field public static final android.os.Parcelable.Creator<android.content.pm.UsesPermissionInfo> CREATOR; - field public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 2; // 0x2 - field public static final int RETENTION_NOT_RETAINED = 1; // 0x1 - field public static final int RETENTION_SPECIFIED = 4; // 0x4 - field public static final int RETENTION_UNDEFINED = 0; // 0x0 - field public static final int RETENTION_UNLIMITED = 3; // 0x3 - field public static final int RETENTION_USER_SELECTED = 2; // 0x2 - field public static final int USAGE_NO = 3; // 0x3 - field public static final int USAGE_UNDEFINED = 0; // 0x0 - field public static final int USAGE_USER_TRIGGERED = 2; // 0x2 - field public static final int USAGE_YES = 1; // 0x1 - } - public final class VersionedPackage implements android.os.Parcelable { ctor public VersionedPackage(@NonNull String, int); ctor public VersionedPackage(@NonNull String, long); @@ -12356,8 +12330,10 @@ package android.content.res { public final class Resources.Theme { method public void applyStyle(int, boolean); method public void dump(int, String, String); + method public int[] getAttributeResolutionStack(@AttrRes int, @StyleRes int, @StyleRes int); method public int getChangingConfigurations(); method public android.graphics.drawable.Drawable getDrawable(@DrawableRes int) throws android.content.res.Resources.NotFoundException; + method @StyleRes public int getExplicitStyle(@Nullable android.util.AttributeSet); method public android.content.res.Resources getResources(); method @NonNull public android.content.res.TypedArray obtainStyledAttributes(@NonNull @StyleableRes int[]); method @NonNull public android.content.res.TypedArray obtainStyledAttributes(@StyleRes int, @NonNull @StyleableRes int[]) throws android.content.res.Resources.NotFoundException; @@ -14196,6 +14172,7 @@ package android.graphics { field public static final int DEPTH_POINT_CLOUD = 257; // 0x101 field public static final int FLEX_RGBA_8888 = 42; // 0x2a field public static final int FLEX_RGB_888 = 41; // 0x29 + field public static final int HEIC = 1212500294; // 0x48454946 field public static final int JPEG = 256; // 0x100 field public static final int NV16 = 16; // 0x10 field public static final int NV21 = 17; // 0x11 @@ -19446,9 +19423,9 @@ package android.icu.text { method public static android.icu.text.BreakIterator getSentenceInstance(java.util.Locale); method public static android.icu.text.BreakIterator getSentenceInstance(android.icu.util.ULocale); method public abstract java.text.CharacterIterator getText(); - method public static android.icu.text.BreakIterator getTitleInstance(); - method public static android.icu.text.BreakIterator getTitleInstance(java.util.Locale); - method public static android.icu.text.BreakIterator getTitleInstance(android.icu.util.ULocale); + method @Deprecated public static android.icu.text.BreakIterator getTitleInstance(); + method @Deprecated public static android.icu.text.BreakIterator getTitleInstance(java.util.Locale); + method @Deprecated public static android.icu.text.BreakIterator getTitleInstance(android.icu.util.ULocale); method public static android.icu.text.BreakIterator getWordInstance(); method public static android.icu.text.BreakIterator getWordInstance(java.util.Locale); method public static android.icu.text.BreakIterator getWordInstance(android.icu.util.ULocale); @@ -19465,7 +19442,7 @@ package android.icu.text { field public static final int KIND_CHARACTER = 0; // 0x0 field public static final int KIND_LINE = 2; // 0x2 field public static final int KIND_SENTENCE = 3; // 0x3 - field public static final int KIND_TITLE = 4; // 0x4 + field @Deprecated public static final int KIND_TITLE = 4; // 0x4 field public static final int KIND_WORD = 1; // 0x1 field public static final int WORD_IDEO = 400; // 0x190 field public static final int WORD_IDEO_LIMIT = 500; // 0x1f4 @@ -22643,6 +22620,7 @@ package android.location { method public int getCodeType(); method public int getConstellationType(); method public int getMultipathIndicator(); + method @NonNull public String getOtherCodeTypeName(); method public double getPseudorangeRateMetersPerSecond(); method public double getPseudorangeRateUncertaintyMetersPerSecond(); method public long getReceivedSvTimeNanos(); @@ -22668,10 +22646,11 @@ package android.location { field public static final int CODE_TYPE_A = 0; // 0x0 field public static final int CODE_TYPE_B = 1; // 0x1 field public static final int CODE_TYPE_C = 2; // 0x2 - field public static final int CODE_TYPE_CODELESS = 13; // 0xd field public static final int CODE_TYPE_I = 3; // 0x3 field public static final int CODE_TYPE_L = 4; // 0x4 field public static final int CODE_TYPE_M = 5; // 0x5 + field public static final int CODE_TYPE_N = 13; // 0xd + field public static final int CODE_TYPE_OTHER = 255; // 0xff field public static final int CODE_TYPE_P = 6; // 0x6 field public static final int CODE_TYPE_Q = 7; // 0x7 field public static final int CODE_TYPE_S = 8; // 0x8 @@ -50327,6 +50306,8 @@ package android.view { method @android.view.ViewDebug.ExportedProperty(category="drawing") public float getAlpha(); method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); + method @NonNull public java.util.List<java.lang.Integer> getAttributeResolutionStack(); + method @NonNull public java.util.Map<java.lang.Integer,java.lang.Integer> getAttributeSourceResourceMap(); method @android.view.ViewDebug.ExportedProperty @Nullable public String[] getAutofillHints(); method public final android.view.autofill.AutofillId getAutofillId(); method public int getAutofillType(); @@ -50357,6 +50338,7 @@ package android.view { method public void getDrawingRect(android.graphics.Rect); method public long getDrawingTime(); method @android.view.ViewDebug.ExportedProperty(category="drawing") public float getElevation(); + method @StyleRes public int getExplicitStyle(); method @android.view.ViewDebug.ExportedProperty public boolean getFilterTouchesWhenObscured(); method @android.view.ViewDebug.ExportedProperty public boolean getFitsSystemWindows(); method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.NOT_FOCUSABLE, to="NOT_FOCUSABLE"), @android.view.ViewDebug.IntToString(from=android.view.View.FOCUSABLE, to="FOCUSABLE"), @android.view.ViewDebug.IntToString(from=android.view.View.FOCUSABLE_AUTO, to="FOCUSABLE_AUTO")}, category="focus") public int getFocusable(); @@ -50651,6 +50633,7 @@ package android.view { method public static int resolveSizeAndState(int, int, int); method public boolean restoreDefaultFocus(); method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>); + method public final void saveAttributeDataForStyleable(@NonNull android.content.Context, @NonNull int[], @Nullable android.util.AttributeSet, @NonNull android.content.res.TypedArray, int, int); method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>); method public void scheduleDrawable(@NonNull android.graphics.drawable.Drawable, @NonNull Runnable, long); method public void scrollBy(int, int); diff --git a/api/removed.txt b/api/removed.txt index 9f4b0416246d..262ffec46de1 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -344,7 +344,7 @@ package android.os { public final class PowerManager { method public void goToSleep(long); method @Deprecated public void userActivity(long, boolean); - method public void wakeUp(long); + method @Deprecated public void wakeUp(long); } public class RecoverySystem { diff --git a/api/system-current.txt b/api/system-current.txt index 8ac5f534cab2..b7fc33950642 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3920,6 +3920,7 @@ package android.net { method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported(); method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.os.Bundle); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler); method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int); @@ -5002,10 +5003,11 @@ package android.os { method public boolean getEnableAdjustBrightness(); method public boolean getEnableDataSaver(); method public boolean getEnableFirewall(); + method public boolean getEnableNightMode(); method public boolean getEnableQuickDoze(); method public boolean getForceAllAppsStandby(); method public boolean getForceBackgroundCheck(); - method public int getGpsMode(); + method public int getLocationMode(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.os.BatterySaverPolicyConfig> CREATOR; } @@ -5027,10 +5029,11 @@ package android.os { method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableAdjustBrightness(boolean); method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableDataSaver(boolean); method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableFirewall(boolean); + method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableNightMode(boolean); method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableQuickDoze(boolean); method @NonNull public android.os.BatterySaverPolicyConfig.Builder setForceAllAppsStandby(boolean); method @NonNull public android.os.BatterySaverPolicyConfig.Builder setForceBackgroundCheck(boolean); - method @NonNull public android.os.BatterySaverPolicyConfig.Builder setGpsMode(int); + method @NonNull public android.os.BatterySaverPolicyConfig.Builder setLocationMode(int); } public class Binder implements android.os.IBinder { diff --git a/api/test-current.txt b/api/test-current.txt index 5b51d6e42a68..2c8d08c49fdb 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -767,6 +767,7 @@ package android.location { method public void setCodeType(int); method public void setConstellationType(int); method public void setMultipathIndicator(int); + method public void setOtherCodeTypeName(@NonNull String); method public void setPseudorangeRateMetersPerSecond(double); method public void setPseudorangeRateUncertaintyMetersPerSecond(double); method public void setReceivedSvTimeNanos(long); @@ -934,6 +935,7 @@ package android.net { } public class ConnectivityManager { + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.os.Bundle); field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; } @@ -2578,6 +2580,10 @@ package android.view { method public void setDisplayId(int); } + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface RemotableViewMethod { + method public abstract String asyncImpl() default ""; + } + @UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback { method public android.view.View getTooltipView(); method public static boolean isDefaultFocusHighlightEnabled(); @@ -2664,6 +2670,8 @@ package android.view.autofill { public final class AutofillId implements android.os.Parcelable { ctor public AutofillId(int); ctor public AutofillId(@NonNull android.view.autofill.AutofillId, int); + ctor public AutofillId(int, int); + ctor public AutofillId(@NonNull android.view.autofill.AutofillId, long, int); } public final class AutofillManager { @@ -2713,6 +2721,66 @@ package android.view.contentcapture { public final class ViewNode extends android.app.assist.AssistStructure.ViewNode { method @Nullable public android.view.autofill.AutofillId getParentAutofillId(); + method @Nullable public static android.view.contentcapture.ViewNode readFromParcel(@NonNull android.os.Parcel); + method public static void writeToParcel(@NonNull android.os.Parcel, @Nullable android.view.contentcapture.ViewNode, int); + } + + public static final class ViewNode.ViewStructureImpl extends android.view.ViewStructure { + ctor public ViewNode.ViewStructureImpl(@NonNull android.view.View); + ctor public ViewNode.ViewStructureImpl(@NonNull android.view.autofill.AutofillId, long, int); + method public int addChildCount(int); + method public void asyncCommit(); + method public android.view.ViewStructure asyncNewChild(int); + method public android.view.autofill.AutofillId getAutofillId(); + method public int getChildCount(); + method public android.os.Bundle getExtras(); + method public CharSequence getHint(); + method public android.view.contentcapture.ViewNode getNode(); + method public android.graphics.Rect getTempRect(); + method public CharSequence getText(); + method public int getTextSelectionEnd(); + method public int getTextSelectionStart(); + method public boolean hasExtras(); + method public android.view.ViewStructure newChild(int); + method public android.view.ViewStructure.HtmlInfo.Builder newHtmlInfoBuilder(String); + method public void setAccessibilityFocused(boolean); + method public void setActivated(boolean); + method public void setAlpha(float); + method public void setAssistBlocked(boolean); + method public void setAutofillHints(String[]); + method public void setAutofillId(android.view.autofill.AutofillId); + method public void setAutofillId(android.view.autofill.AutofillId, int); + method public void setAutofillOptions(CharSequence[]); + method public void setAutofillType(int); + method public void setAutofillValue(android.view.autofill.AutofillValue); + method public void setCheckable(boolean); + method public void setChecked(boolean); + method public void setChildCount(int); + method public void setClassName(String); + method public void setClickable(boolean); + method public void setContentDescription(CharSequence); + method public void setContextClickable(boolean); + method public void setDataIsSensitive(boolean); + method public void setDimens(int, int, int, int, int, int); + method public void setElevation(float); + method public void setEnabled(boolean); + method public void setFocusable(boolean); + method public void setFocused(boolean); + method public void setHint(CharSequence); + method public void setHtmlInfo(android.view.ViewStructure.HtmlInfo); + method public void setId(int, String, String, String); + method public void setInputType(int); + method public void setLocaleList(android.os.LocaleList); + method public void setLongClickable(boolean); + method public void setOpaque(boolean); + method public void setSelected(boolean); + method public void setText(CharSequence); + method public void setText(CharSequence, int, int); + method public void setTextLines(int[], int[]); + method public void setTextStyle(float, int, int, int); + method public void setTransformation(android.graphics.Matrix); + method public void setVisibility(int); + method public void setWebDomain(String); } } diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index 056add5c71b5..2fef407a8e3f 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -43,6 +43,7 @@ cc_library { "libidmap2/PrettyPrintVisitor.cpp", "libidmap2/RawPrintVisitor.cpp", "libidmap2/ResourceUtils.cpp", + "libidmap2/Result.cpp", "libidmap2/Xml.cpp", "libidmap2/ZipFile.cpp", ], @@ -93,6 +94,7 @@ cc_test { "tests/PrettyPrintVisitorTests.cpp", "tests/RawPrintVisitorTests.cpp", "tests/ResourceUtilsTests.cpp", + "tests/ResultTests.cpp", "tests/XmlTests.cpp", "tests/ZipFileTests.cpp", ], diff --git a/cmds/idmap2/include/idmap2/Result.h b/cmds/idmap2/include/idmap2/Result.h index 6189ea371ee1..d88dd5179610 100644 --- a/cmds/idmap2/include/idmap2/Result.h +++ b/cmds/idmap2/include/idmap2/Result.h @@ -18,6 +18,11 @@ #define IDMAP2_INCLUDE_IDMAP2_RESULT_H_ #include <optional> +#include <string> +#include <utility> +#include <variant> + +#include "android-base/logging.h" // CHECK namespace android::idmap2 { @@ -26,6 +31,125 @@ using Result = std::optional<T>; static constexpr std::nullopt_t kResultError = std::nullopt; +namespace v2 { + +using Unit = std::monostate; + +class Error { + public: + explicit Error(const Error& parent) = default; + + // NOLINTNEXTLINE(cert-dcl50-cpp) + explicit Error(const char* fmt, ...) __attribute__((__format__(printf, 2, 3))); + + // NOLINTNEXTLINE(cert-dcl50-cpp) + explicit Error(const Error& parent, const char* fmt, ...) + __attribute__((__format__(printf, 3, 4))); + + inline std::string GetMessage() const { + return msg_; + } + + private: + std::string msg_; +}; + +template <typename T> +class Result { + public: + Result(const T& value); // NOLINT(runtime/explicit) + Result(T&& value) noexcept; // NOLINT(runtime/explicit) + + Result(const Error& error); // NOLINT(runtime/explicit) + Result(Error&& error) noexcept; // NOLINT(runtime/explicit) + + Result(const Result& error) = default; + + Result& operator=(const Result& rhs) = default; + Result& operator=(Result&& rhs) noexcept = default; + + explicit operator bool() const; + + constexpr const T& operator*() const&; + T& operator*() &; + + constexpr const T* operator->() const&; + T* operator->() &; + + std::string GetErrorMessage() const; + Error GetError() const; + + private: + bool is_ok() const; + + std::variant<T, Error> data_; +}; + +template <typename T> +Result<T>::Result(const T& value) : data_(std::in_place_type<T>, value) { +} + +template <typename T> +Result<T>::Result(T&& value) noexcept : data_(std::in_place_type<T>, std::forward<T>(value)) { +} + +template <typename T> +Result<T>::Result(const Error& error) : data_(std::in_place_type<Error>, error) { +} + +template <typename T> +Result<T>::Result(Error&& error) noexcept + : data_(std::in_place_type<Error>, std::forward<Error>(error)) { +} + +template <typename T> +Result<T>::operator bool() const { + return is_ok(); +} + +template <typename T> +constexpr const T& Result<T>::operator*() const& { + CHECK(is_ok()) << "Result<T>::operator* called in ERROR state"; + return std::get<T>(data_); +} + +template <typename T> +T& Result<T>::operator*() & { + CHECK(is_ok()) << "Result<T>::operator* called in ERROR state"; + return std::get<T>(data_); +} + +template <typename T> +constexpr const T* Result<T>::operator->() const& { + CHECK(is_ok()) << "Result<T>::operator-> called in ERROR state"; + return &std::get<T>(data_); +} + +template <typename T> +T* Result<T>::operator->() & { + CHECK(is_ok()) << "Result<T>::operator-> called in ERROR state"; + return &std::get<T>(data_); +} + +template <typename T> +inline std::string Result<T>::GetErrorMessage() const { + CHECK(!is_ok()) << "Result<T>::GetErrorMessage called in OK state"; + return std::get<Error>(data_).GetMessage(); +} + +template <typename T> +inline Error Result<T>::GetError() const { + CHECK(!is_ok()) << "Result<T>::GetError called in OK state"; + return Error(std::get<Error>(data_)); +} + +template <typename T> +inline bool Result<T>::is_ok() const { + return std::holds_alternative<T>(data_); +} + +} // namespace v2 + } // namespace android::idmap2 #endif // IDMAP2_INCLUDE_IDMAP2_RESULT_H_ diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index fa5ac8ea11dc..b19d7a971cb8 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -117,6 +117,12 @@ const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) { return loaded_arsc.GetPackageById(id); } +Result<uint32_t> GetCrc(const ZipFile& zip) { + const Result<uint32_t> a = zip.Crc("resources.arsc"); + const Result<uint32_t> b = zip.Crc("AndroidManifest.xml"); + return a && b ? Result<uint32_t>(*a ^ *b) : kResultError; +} + } // namespace std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) { @@ -153,7 +159,7 @@ bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { return false; } - Result<uint32_t> target_crc = target_zip->Crc("resources.arsc"); + Result<uint32_t> target_crc = GetCrc(*target_zip); if (!target_crc) { out_error << "error: failed to get target crc" << std::endl; return false; @@ -173,7 +179,7 @@ bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { return false; } - Result<uint32_t> overlay_crc = overlay_zip->Crc("resources.arsc"); + Result<uint32_t> overlay_crc = GetCrc(*overlay_zip); if (!overlay_crc) { out_error << "error: failed to get overlay crc" << std::endl; return false; @@ -356,14 +362,14 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( header->magic_ = kIdmapMagic; header->version_ = kIdmapCurrentVersion; - Result<uint32_t> crc = target_zip->Crc("resources.arsc"); + Result<uint32_t> crc = GetCrc(*target_zip); if (!crc) { out_error << "error: failed to get zip crc for target" << std::endl; return nullptr; } header->target_crc_ = *crc; - crc = overlay_zip->Crc("resources.arsc"); + crc = GetCrc(*overlay_zip); if (!crc) { out_error << "error: failed to get zip crc for overlay" << std::endl; return nullptr; diff --git a/cmds/idmap2/libidmap2/Result.cpp b/cmds/idmap2/libidmap2/Result.cpp new file mode 100644 index 000000000000..a5c999916c72 --- /dev/null +++ b/cmds/idmap2/libidmap2/Result.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cstdarg> + +#include "android-base/stringprintf.h" + +#include "idmap2/Result.h" + +namespace android::idmap2 { + +v2::Error::Error(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + base::StringAppendV(&msg_, fmt, ap); + va_end(ap); +} + +v2::Error::Error(const Error& parent, const char* fmt, ...) : msg_(parent.msg_) { + msg_.append(" -> "); + + va_list ap; + va_start(ap, fmt); + base::StringAppendV(&msg_, fmt, ap); + va_end(ap); +} + +} // namespace android::idmap2 diff --git a/cmds/idmap2/static-checks.sh b/cmds/idmap2/static-checks.sh index ad9830b8a096..57407102843b 100755 --- a/cmds/idmap2/static-checks.sh +++ b/cmds/idmap2/static-checks.sh @@ -73,6 +73,7 @@ function _cpplint() 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: misc-non-private-member-variables-in-classes' \ + -e 'Unknown NOLINT error category: performance-unnecessary-copy-initialization' \ )" if [[ "$output" ]]; then echo "$output" diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 9e27ccd7cfbb..b40521f054af 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -191,8 +191,8 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U); - ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xab7cf70d); - ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xd470336b); + ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xdd53ca29); + ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xa71ccd77); ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path); ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path); ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path); diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index b1ca12557dcb..a5588c330d85 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -52,8 +52,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos); ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos); - ASSERT_NE(stream.str().find("00000008: ab7cf70d target crc\n"), std::string::npos); - ASSERT_NE(stream.str().find("0000000c: d470336b overlay crc\n"), std::string::npos); + ASSERT_NE(stream.str().find("00000008: dd53ca29 target crc\n"), std::string::npos); + ASSERT_NE(stream.str().find("0000000c: a71ccd77 overlay crc\n"), std::string::npos); ASSERT_NE(stream.str().find("0000021c: 00000000 0x7f010000 -> 0x7f010000 integer/int1\n"), std::string::npos); } diff --git a/cmds/idmap2/tests/ResultTests.cpp b/cmds/idmap2/tests/ResultTests.cpp new file mode 100644 index 000000000000..d82f0c475ea9 --- /dev/null +++ b/cmds/idmap2/tests/ResultTests.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <memory> +#include <type_traits> +#include <utility> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "idmap2/Result.h" + +namespace android::idmap2 { + +struct Container { + uint32_t value; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +// Tests: Error + +TEST(ResultTests, ErrorTraits) { + ASSERT_TRUE(std::is_move_constructible<v2::Error>::value); + ASSERT_TRUE(std::is_move_assignable<v2::Error>::value); + ASSERT_TRUE(std::is_copy_constructible<v2::Error>::value); + ASSERT_TRUE(std::is_copy_assignable<v2::Error>::value); +} + +TEST(ResultTests, ErrorCtorFormat) { + v2::Error e("%s=0x%08x", "resid", 0x7f010002); + ASSERT_EQ(e.GetMessage(), "resid=0x7f010002"); +} + +TEST(ResultTests, ErrorPropagateParent) { + v2::Error e1("foo"); + ASSERT_EQ(e1.GetMessage(), "foo"); + + v2::Error e2(e1, "bar"); + ASSERT_EQ(e2.GetMessage(), "foo -> bar"); + + v2::Error e3(e2); // NOLINT(performance-unnecessary-copy-initialization) + ASSERT_EQ(e3.GetMessage(), "foo -> bar"); + + v2::Error e4(e3, "%02d", 1); + ASSERT_EQ(e4.GetMessage(), "foo -> bar -> 01"); +} + +// Tests: Result<T> member functions + +// Result(const Result&) +TEST(ResultTests, CopyConstructor) { + v2::Result<uint32_t> r1(42U); + + v2::Result<uint32_t> r2(r1); + ASSERT_TRUE(r2); + ASSERT_EQ(*r2, 42U); + + v2::Result<uint32_t> r3 = r2; + ASSERT_TRUE(r3); + ASSERT_EQ(*r3, 42U); +} + +// Result(const T&) +TEST(ResultTests, Constructor) { + uint32_t v = 42U; + v2::Result<uint32_t> r1(v); + ASSERT_TRUE(r1); + ASSERT_EQ(*r1, 42U); + + v2::Error e("foo"); + v2::Result<uint32_t> r2(e); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +// Result(const T&&) +TEST(ResultTests, MoveConstructor) { + v2::Result<uint32_t> r1(42U); + ASSERT_TRUE(r1); + ASSERT_EQ(*r1, 42U); + + v2::Result<uint32_t> r2(v2::Error("foo")); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +// operator= +TEST(ResultTests, CopyAssignmentOperator) { + // note: 'Result<...> r2 = r1;' calls the copy ctor + v2::Result<uint32_t> r1(42U); + v2::Result<uint32_t> r2(0U); + r2 = r1; + ASSERT_TRUE(r2); + ASSERT_EQ(*r2, 42U); + + v2::Result<uint32_t> r3(v2::Error("foo")); + r2 = r3; + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +TEST(ResultTests, MoveAssignmentOperator) { + v2::Result<uint32_t> r(0U); + r = v2::Result<uint32_t>(42U); + ASSERT_TRUE(r); + ASSERT_EQ(*r, 42U); + + r = v2::Result<uint32_t>(v2::Error("foo")); + ASSERT_FALSE(r); + ASSERT_EQ(r.GetErrorMessage(), "foo"); +} + +// operator bool() +TEST(ResultTests, BoolOperator) { + v2::Result<uint32_t> r1(42U); + ASSERT_TRUE(r1); + ASSERT_EQ(*r1, 42U); + + v2::Result<uint32_t> r2(v2::Error("foo")); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +// operator* +TEST(ResultTests, IndirectionOperator) { + const v2::Result<uint32_t> r1(42U); + ASSERT_TRUE(r1); + ASSERT_EQ(*r1, 42U); + + const v2::Result<Container> r2(Container{42U}); + ASSERT_TRUE(r2); + const Container& c = *r2; + ASSERT_EQ(c.value, 42U); + + v2::Result<Container> r3(Container{42U}); + ASSERT_TRUE(r3); + ASSERT_EQ((*r3).value, 42U); + (*r3).value = 0U; + ASSERT_EQ((*r3).value, 0U); +} + +// operator-> +TEST(ResultTests, DereferenceOperator) { + const v2::Result<Container> r1(Container{42U}); + ASSERT_TRUE(r1); + ASSERT_EQ(r1->value, 42U); + + v2::Result<Container> r2(Container{42U}); + ASSERT_TRUE(r2); + ASSERT_EQ(r2->value, 42U); + r2->value = 0U; + ASSERT_EQ(r2->value, 0U); +} + +// Tests: intended use of Result<T> + +TEST(ResultTests, ResultTraits) { + ASSERT_TRUE(std::is_move_constructible<v2::Result<uint32_t>>::value); + ASSERT_TRUE(std::is_move_assignable<v2::Result<uint32_t>>::value); + ASSERT_TRUE(std::is_copy_constructible<v2::Result<uint32_t>>::value); + ASSERT_TRUE(std::is_copy_assignable<v2::Result<uint32_t>>::value); +} + +TEST(ResultTests, UnitTypeResult) { + v2::Result<v2::Unit> r(v2::Unit{}); + ASSERT_TRUE(r); +} + +struct RefCountData { + int ctor; // NOLINT(misc-non-private-member-variables-in-classes) + int copy_ctor; // NOLINT(misc-non-private-member-variables-in-classes) + int dtor; // NOLINT(misc-non-private-member-variables-in-classes) + int move; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +class RefCountContainer { + public: + explicit RefCountContainer(RefCountData& data) : data_(data) { + ++data_.ctor; + } + + RefCountContainer(RefCountContainer const&) = delete; + + RefCountContainer(RefCountContainer&& rhs) noexcept : data_(rhs.data_) { + ++data_.copy_ctor; + } + + RefCountContainer& operator=(RefCountContainer const&) = delete; + + RefCountContainer& operator=(RefCountContainer&& rhs) noexcept { + data_ = rhs.data_; + ++data_.move; + return *this; + } + + ~RefCountContainer() { + ++data_.dtor; + } + + private: + RefCountData& data_; +}; + +TEST(ResultTests, ReferenceCount) { + ASSERT_TRUE(std::is_move_constructible<RefCountContainer>::value); + ASSERT_TRUE(std::is_move_assignable<RefCountContainer>::value); + ASSERT_FALSE(std::is_copy_constructible<RefCountContainer>::value); + ASSERT_FALSE(std::is_copy_assignable<RefCountContainer>::value); + + RefCountData rc{0, 0, 0, 0}; + { v2::Result<RefCountContainer> r(RefCountContainer{rc}); } + ASSERT_EQ(rc.ctor, 1); + ASSERT_EQ(rc.copy_ctor, 1); + ASSERT_EQ(rc.move, 0); + ASSERT_EQ(rc.dtor, 2); +} + +v2::Result<Container> CreateContainer(bool succeed) { + if (!succeed) { + return v2::Error("foo"); + } + return Container{42U}; +} + +TEST(ResultTests, FunctionReturn) { + auto r1 = CreateContainer(true); + ASSERT_TRUE(r1); + ASSERT_EQ(r1->value, 42U); + + auto r2 = CreateContainer(false); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); + ASSERT_EQ(r2.GetError().GetMessage(), "foo"); +} + +v2::Result<Container> FailToCreateContainer() { + auto container = CreateContainer(false); + if (!container) { + return v2::Error(container.GetError(), "bar"); + } + return container; +} + +TEST(ResultTests, CascadeError) { + auto container = FailToCreateContainer(); + ASSERT_FALSE(container); + ASSERT_EQ(container.GetErrorMessage(), "foo -> bar"); +} + +struct NoCopyContainer { + uint32_t value; // NOLINT(misc-non-private-member-variables-in-classes) + DISALLOW_COPY_AND_ASSIGN(NoCopyContainer); +}; + +v2::Result<std::unique_ptr<NoCopyContainer>> CreateNoCopyContainer(bool succeed) { + if (!succeed) { + return v2::Error("foo"); + } + std::unique_ptr<NoCopyContainer> p(new NoCopyContainer{0U}); + p->value = 42U; + return std::move(p); +} + +TEST(ResultTests, UniquePtr) { + auto r1 = CreateNoCopyContainer(true); + ASSERT_TRUE(r1); + ASSERT_EQ((*r1)->value, 42U); + (*r1)->value = 0U; + ASSERT_EQ((*r1)->value, 0U); + + auto r2 = CreateNoCopyContainer(false); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +} // namespace android::idmap2 diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto index e33bd8c97a07..2a3eee2a7e18 100644 --- a/cmds/statsd/src/atom_field_options.proto +++ b/cmds/statsd/src/atom_field_options.proto @@ -82,4 +82,6 @@ extend google.protobuf.FieldOptions { optional bool is_uid = 50001 [default = false]; optional LogMode log_mode = 50002 [default = MODE_AUTOMATIC]; + + optional bool allow_from_any_uid = 50003 [default = false]; }
\ No newline at end of file diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index fc3aa91b9e0b..4f17d69f23f2 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -110,7 +110,7 @@ message Atom { PacketWakeupOccurred packet_wakeup_occurred = 44; WallClockTimeShifted wall_clock_time_shifted = 45; AnomalyDetected anomaly_detected = 46; - AppBreadcrumbReported app_breadcrumb_reported = 47; + AppBreadcrumbReported app_breadcrumb_reported = 47 [(allow_from_any_uid) = true]; AppStartOccurred app_start_occurred = 48; AppStartCanceled app_start_canceled = 49; AppStartFullyDrawn app_start_fully_drawn = 50; @@ -121,7 +121,7 @@ message Atom { AppStartMemoryStateCaptured app_start_memory_state_captured = 55; ShutdownSequenceReported shutdown_sequence_reported = 56; BootSequenceReported boot_sequence_reported = 57; - DaveyOccurred davey_occurred = 58; + DaveyOccurred davey_occurred = 58 [(allow_from_any_uid) = true]; OverlayStateChanged overlay_state_changed = 59; ForegroundServiceStateChanged foreground_service_state_changed = 60; CallStateChanged call_state_changed = 61; @@ -239,6 +239,7 @@ message Atom { PermissionGrantRequestResultReported permission_grant_request_result_reported = 170; BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171; DeviceIdentifierAccessDenied device_identifier_access_denied = 172; + BubbleDeveloperErrorReported bubble_developer_error_reported = 173; } // Pulled events will start at field 10000. @@ -5344,6 +5345,27 @@ message BubbleUIChanged { } /** + * Logs System UI bubbles developer errors. + * + * Logged from: + * frameworks/base/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java + */ +message BubbleDeveloperErrorReported { + + // The app package that is posting the bubble. + optional string package_name = 1; + + // Bubble developer error type enums. + enum Error { + UNKNOWN = 0; + ACTIVITY_INFO_MISSING = 1; + ACTIVITY_INFO_NOT_RESIZABLE = 2; + DOCUMENT_LAUNCH_NOT_ALWAYS = 3; + } + optional Error error = 2 [default = UNKNOWN]; +} + +/** * Logs that a constraint for a scheduled job has changed. * * Logged from: diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index a5bd5c6b6364..37d5ba0e6801 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -443,6 +443,11 @@ void StatsdStats::noteBadValueType(int metricId) { getAtomMetricStats(metricId).badValueType++; } +void StatsdStats::noteBucketDropped(int metricId) { + lock_guard<std::mutex> lock(mLock); + getAtomMetricStats(metricId).bucketDropped++; +} + void StatsdStats::noteConditionChangeInNextBucket(int metricId) { lock_guard<std::mutex> lock(mLock); getAtomMetricStats(metricId).conditionChangeInNextBucket++; diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h index cb17061c1ed1..20ea7e5df1fa 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.h +++ b/cmds/statsd/src/guardrail/StatsdStats.h @@ -360,6 +360,11 @@ public: void noteBadValueType(int atomId); /** + * Buckets were dropped due to reclaim memory. + */ + void noteBucketDropped(int metricId); + + /** * A condition change was too late, arrived in the wrong bucket and was skipped */ void noteConditionChangeInNextBucket(int atomId); @@ -414,6 +419,7 @@ public: long badValueType = 0; long conditionChangeInNextBucket = 0; long invalidatedBucket = 0; + long bucketDropped = 0; } AtomMetricStats; private: diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index 7cc57c12063c..350745b2c326 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -243,6 +243,7 @@ void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, void CountMetricProducer::dropDataLocked(const int64_t dropTimeNs) { flushIfNeededLocked(dropTimeNs); + StatsdStats::getInstance().noteBucketDropped(mMetricId); mPastBuckets.clear(); } diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index 69bafc354643..6c1c47bbc093 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -444,6 +444,7 @@ void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet, void DurationMetricProducer::dropDataLocked(const int64_t dropTimeNs) { flushIfNeededLocked(dropTimeNs); + StatsdStats::getInstance().noteBucketDropped(mMetricId); mPastBuckets.clear(); } diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp index c53c4ce5e0d6..7e695a69988f 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.cpp +++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp @@ -77,6 +77,7 @@ EventMetricProducer::~EventMetricProducer() { void EventMetricProducer::dropDataLocked(const int64_t dropTimeNs) { mProto->clear(); + StatsdStats::getInstance().noteBucketDropped(mMetricId); } void EventMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition, diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index c9b71659aa58..2609937924ac 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -510,6 +510,7 @@ void GaugeMetricProducer::updateCurrentSlicedBucketForAnomaly() { void GaugeMetricProducer::dropDataLocked(const int64_t dropTimeNs) { flushIfNeededLocked(dropTimeNs); + StatsdStats::getInstance().noteBucketDropped(mMetricId); mPastBuckets.clear(); } diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index ca681176c54a..6ed6ab500597 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -241,12 +241,22 @@ void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs, VLOG("=========================Metric Reports End=========================="); } -// Consume the stats log if it's interesting to this metric. -void MetricsManager::onLogEvent(const LogEvent& event) { - if (!mConfigValid) { - return; + +bool MetricsManager::checkLogCredentials(const LogEvent& event) { + if (android::util::AtomsInfo::kWhitelistedAtoms.find(event.GetTagId()) != + android::util::AtomsInfo::kWhitelistedAtoms.end()) + { + return true; } + std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex); + if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) { + VLOG("log source %d not on the whitelist", event.GetUid()); + return false; + } + return true; +} +bool MetricsManager::eventSanityCheck(const LogEvent& event) { if (event.GetTagId() == android::util::APP_BREADCRUMB_REPORTED) { // Check that app breadcrumb reported fields are valid. status_t err = NO_ERROR; @@ -256,23 +266,23 @@ void MetricsManager::onLogEvent(const LogEvent& event) { long appHookUid = event.GetLong(event.size()-2, &err); if (err != NO_ERROR ) { VLOG("APP_BREADCRUMB_REPORTED had error when parsing the uid"); - return; + return false; } int32_t loggerUid = event.GetUid(); if (loggerUid != appHookUid && loggerUid != AID_STATSD) { VLOG("APP_BREADCRUMB_REPORTED has invalid uid: claimed %ld but caller is %d", appHookUid, loggerUid); - return; + return false; } // The state must be from 0,3. This part of code must be manually updated. long appHookState = event.GetLong(event.size(), &err); if (err != NO_ERROR ) { VLOG("APP_BREADCRUMB_REPORTED had error when parsing the state field"); - return; + return false; } else if (appHookState < 0 || appHookState > 3) { VLOG("APP_BREADCRUMB_REPORTED does not have valid state %ld", appHookState); - return; + return false; } } else if (event.GetTagId() == android::util::DAVEY_OCCURRED) { // Daveys can be logged from any app since they are logged in libs/hwui/JankTracker.cpp. @@ -283,31 +293,42 @@ void MetricsManager::onLogEvent(const LogEvent& event) { long jankUid = event.GetLong(1, &err); if (err != NO_ERROR ) { VLOG("Davey occurred had error when parsing the uid"); - return; + return false; } int32_t loggerUid = event.GetUid(); if (loggerUid != jankUid && loggerUid != AID_STATSD) { VLOG("DAVEY_OCCURRED has invalid uid: claimed %ld but caller is %d", jankUid, loggerUid); - return; + return false; } long duration = event.GetLong(event.size(), &err); if (err != NO_ERROR ) { VLOG("Davey occurred had error when parsing the duration"); - return; + return false; } else if (duration > 100000) { VLOG("Davey duration is unreasonably long: %ld", duration); - return; - } - } else { - std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex); - if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) { - VLOG("log source %d not on the whitelist", event.GetUid()); - return; + return false; } } + return true; +} + +// Consume the stats log if it's interesting to this metric. +void MetricsManager::onLogEvent(const LogEvent& event) { + if (!mConfigValid) { + return; + } + + if (!checkLogCredentials(event)) { + return; + } + + if (!eventSanityCheck(event)) { + return; + } + int tagId = event.GetTagId(); int64_t eventTimeNs = event.GetElapsedTimestampNs(); diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 80982c37dc6a..fdc28ea7f219 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -49,6 +49,10 @@ public: // Return whether the configuration is valid. bool isConfigValid() const; + bool checkLogCredentials(const LogEvent& event); + + bool eventSanityCheck(const LogEvent& event); + void onLogEvent(const LogEvent& event); void onAnomalyAlarmFired( diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 9fb78e780870..1bd3ef20a578 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -175,6 +175,7 @@ void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition void ValueMetricProducer::dropDataLocked(const int64_t dropTimeNs) { flushIfNeededLocked(dropTimeNs); + StatsdStats::getInstance().noteBucketDropped(mMetricId); mPastBuckets.clear(); } @@ -434,6 +435,10 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven } } 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."); } diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index d9bec5d588be..0cfefa9e3eb4 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -61,6 +61,7 @@ public: if (!mSplitBucketForAppUpgrade) { return; } + flushIfNeededLocked(eventTimeNs - 1); if (mIsPulled && mCondition) { pullAndMatchEventsLocked(eventTimeNs - 1); } @@ -212,6 +213,7 @@ private: FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition); FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade); FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade); + FRIEND_TEST(ValueMetricProducerTest, TestPartialBucketCreated); FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse); FRIEND_TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled); FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition); @@ -238,6 +240,8 @@ private: FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed); FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed); FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed); + FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded); + FRIEND_TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange); }; } // namespace statsd diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index 5b9148283bdc..73aab4847e11 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -418,6 +418,7 @@ message StatsdStatsReport { optional int64 bad_value_type = 5; optional int64 condition_change_in_next_bucket = 6; optional int64 invalidated_bucket = 7; + optional int64 bucket_dropped = 8; } 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 3cb7563b206b..f76a9ad78396 100644 --- a/cmds/statsd/src/stats_log_util.cpp +++ b/cmds/statsd/src/stats_log_util.cpp @@ -79,6 +79,7 @@ const int FIELD_ID_SKIPPED_FORWARD_BUCKETS = 4; const int FIELD_ID_BAD_VALUE_TYPE = 5; const int FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET = 6; const int FIELD_ID_INVALIDATED_BUCKET = 7; +const int FIELD_ID_BUCKET_DROPPED = 8; namespace { @@ -497,6 +498,8 @@ void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricSt (long long)pair.second.conditionChangeInNextBucket); protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_INVALIDATED_BUCKET, (long long)pair.second.invalidatedBucket); + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_DROPPED, + (long long)pair.second.bucketDropped); protoOutput->end(token); } diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 64045520fb0b..91b98ecffa29 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -167,9 +167,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(11, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(8, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); @@ -184,11 +185,12 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(23, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(12, curInterval.value.long_value); EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); - EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); - EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); + EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); + EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); @@ -202,11 +204,80 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(36, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(13, curInterval.value.long_value); EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); - EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size()); - EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); + EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); + EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value); + EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second[2].values[0].long_value); +} + +TEST(ValueMetricProducerTest, TestPartialBucketCreated) { + 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, _)) + // Initialize bucket. + .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + data->clear(); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); + event->write(tagId); + event->write(1); + event->init(); + data->push_back(event); + return true; + })) + // Partial bucket. + .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + data->clear(); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10); + event->write(tagId); + event->write(5); + event->init(); + data->push_back(event); + return true; + })); + + ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, + logEventMatcherIndex, eventMatcherWizard, tagId, + bucketStartTimeNs, bucketStartTimeNs, pullerManager); + + // First bucket ends. + vector<shared_ptr<LogEvent>> allData; + allData.clear(); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10); + event->write(tagId); + event->write(2); + event->init(); + allData.push_back(event); + valueProducer.onDataPulled(allData, /** success */ true); + + // Partial buckets created in 2nd bucket. + valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1); + + // One full bucket and one partial bucket. + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + vector<ValueBucket> buckets = valueProducer.mPastBuckets.begin()->second; + EXPECT_EQ(2UL, buckets.size()); + // Full bucket (2 - 1) + EXPECT_EQ(1, buckets[0].values[0].long_value); + // Full bucket (5 - 3) + EXPECT_EQ(3, buckets[1].values[0].long_value); } /* @@ -264,9 +335,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(11, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(8, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); @@ -275,16 +347,15 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { event->init(); allData.push_back(event); valueProducer.onDataPulled(allData, /** succeed */ true); - // has one slice - EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); - curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; + // No new data seen, so data has been cleared. + EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(11, curInterval.base.long_value); - // no events caused flush of bucket - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(8, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); @@ -363,9 +434,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(10, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(10, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); @@ -378,11 +450,12 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(36, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(26, curInterval.value.long_value); EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); - EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); - EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); + EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size()); + EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); + EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value); } /* @@ -456,9 +529,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) { curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(36, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(26, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); } /* @@ -532,9 +606,10 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) { curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(110, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(10, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1); @@ -651,8 +726,8 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) { event->init(); allData.push_back(event); valueProducer.onDataPulled(allData, /** succeed */ true); - EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); - EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs); + EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs); EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value); } @@ -694,7 +769,7 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) { valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1); EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); - EXPECT_EQ(bucketStartTimeNs, valueProducer.mCurrentBucketStartTimeNs); + EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs); } TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) { @@ -1018,9 +1093,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) { // tartUpdated:false sum:12 EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(23, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); - EXPECT_EQ(12, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(false, curInterval.hasValue); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); // pull 3 come late. // The previous bucket gets closed with error. (Has start value 23, no ending) @@ -1681,7 +1756,7 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval1.hasBase); EXPECT_EQ(11, interval1.base.long_value); - EXPECT_EQ(true, interval1.hasValue); + EXPECT_EQ(false, interval1.hasValue); EXPECT_EQ(8, interval1.value.long_value); auto it = valueProducer.mCurrentSlicedBucket.begin(); @@ -1695,9 +1770,14 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); EXPECT_EQ(true, interval2.hasBase); EXPECT_EQ(4, interval2.base.long_value); - EXPECT_EQ(true, interval2.hasValue); + EXPECT_EQ(false, interval2.hasValue); EXPECT_EQ(4, interval2.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + + EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); + auto iterator = valueProducer.mPastBuckets.begin(); + EXPECT_EQ(8, iterator->second[0].values[0].long_value); + iterator++; + EXPECT_EQ(4, iterator->second[0].values[0].long_value); } /* @@ -1766,7 +1846,7 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval1.hasBase); EXPECT_EQ(11, interval1.base.long_value); - EXPECT_EQ(true, interval1.hasValue); + EXPECT_EQ(false, interval1.hasValue); EXPECT_EQ(8, interval1.value.long_value); auto it = valueProducer.mCurrentSlicedBucket.begin(); @@ -1780,9 +1860,9 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); EXPECT_EQ(true, interval2.hasBase); EXPECT_EQ(4, interval2.base.long_value); - EXPECT_EQ(true, interval2.hasValue); + EXPECT_EQ(false, interval2.hasValue); EXPECT_EQ(4, interval2.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); // next pull somehow did not happen, skip to end of bucket 3 allData.clear(); @@ -1793,11 +1873,11 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { allData.push_back(event1); valueProducer.onDataPulled(allData, /** succeed */ true); - EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); + EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval2.hasBase); - EXPECT_EQ(5, interval2.base.long_value); + EXPECT_EQ(4, interval2.base.long_value); EXPECT_EQ(false, interval2.hasValue); - EXPECT_EQ(false, interval1.hasBase); + EXPECT_EQ(true, interval1.hasBase); EXPECT_EQ(false, interval1.hasValue); EXPECT_EQ(true, valueProducer.mHasGlobalBase); EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); @@ -1817,13 +1897,13 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval2.hasBase); - EXPECT_EQ(13, interval2.base.long_value); - EXPECT_EQ(true, interval2.hasValue); - EXPECT_EQ(8, interval2.value.long_value); + EXPECT_EQ(5, interval2.base.long_value); + EXPECT_EQ(false, interval2.hasValue); + EXPECT_EQ(5, interval2.value.long_value); EXPECT_EQ(true, interval1.hasBase); - EXPECT_EQ(5, interval1.base.long_value); - EXPECT_EQ(true, interval1.hasValue); - EXPECT_EQ(5, interval1.value.long_value); + EXPECT_EQ(13, interval1.base.long_value); + EXPECT_EQ(false, interval1.hasValue); + EXPECT_EQ(8, interval1.value.long_value); EXPECT_EQ(true, valueProducer.mHasGlobalBase); EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); } @@ -1892,9 +1972,11 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval1.hasBase); EXPECT_EQ(11, interval1.base.long_value); - EXPECT_EQ(true, interval1.hasValue); + EXPECT_EQ(false, interval1.hasValue); EXPECT_EQ(8, interval1.value.long_value); - EXPECT_TRUE(interval1.seenNewData); + EXPECT_FALSE(interval1.seenNewData); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); auto it = valueProducer.mCurrentSlicedBucket.begin(); for (; it != valueProducer.mCurrentSlicedBucket.end(); it++) { @@ -1908,8 +1990,8 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { EXPECT_EQ(true, interval2.hasBase); EXPECT_EQ(4, interval2.base.long_value); EXPECT_EQ(false, interval2.hasValue); - EXPECT_TRUE(interval2.seenNewData); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_FALSE(interval2.seenNewData); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); // next pull somehow did not happen, skip to end of bucket 3 allData.clear(); @@ -1920,35 +2002,34 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { allData.push_back(event1); valueProducer.onDataPulled(allData, /** succeed */ true); - EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); - - EXPECT_EQ(false, interval1.hasBase); - EXPECT_EQ(false, interval1.hasValue); - EXPECT_EQ(8, interval1.value.long_value); - // on probation now - EXPECT_FALSE(interval1.seenNewData); - + // Only one interval left. One was trimmed. + EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); + interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0]; + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); EXPECT_EQ(true, interval2.hasBase); EXPECT_EQ(5, interval2.base.long_value); EXPECT_EQ(false, interval2.hasValue); - // back to good status - EXPECT_TRUE(interval2.seenNewData); + EXPECT_FALSE(interval2.seenNewData); EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); allData.clear(); event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1); event1->write(2); - event1->write(13); + event1->write(14); event1->init(); allData.push_back(event1); valueProducer.onDataPulled(allData, /** succeed */ true); - EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); + interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, interval2.hasBase); - EXPECT_EQ(13, interval2.base.long_value); - EXPECT_EQ(true, interval2.hasValue); - EXPECT_EQ(8, interval2.value.long_value); - EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(14, interval2.base.long_value); + EXPECT_EQ(false, interval2.hasValue); + EXPECT_FALSE(interval2.seenNewData); + EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); + auto iterator = valueProducer.mPastBuckets.begin(); + EXPECT_EQ(9, iterator->second[0].values[0].long_value); + iterator++; + EXPECT_EQ(8, iterator->second[0].values[0].long_value); } TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) { @@ -2110,7 +2191,7 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) { EXPECT_EQ(false, valueProducer.mHasGlobalBase); } -TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) { +TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) { ValueMetric metric; metric.set_id(metricId); metric.set_bucket(ONE_MINUTE); @@ -2133,7 +2214,7 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) { EXPECT_CALL(*pullerManager, Pull(tagId, _)) .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); event->write(tagId); event->write(120); event->init(); @@ -2145,35 +2226,91 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) { eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); - valueProducer.mCondition = true; - valueProducer.mHasGlobalBase = true; + valueProducer.mCondition = false; - vector<shared_ptr<LogEvent>> allData; - allData.clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); - event->write(1); - event->write(110); - event->init(); - allData.push_back(event); - valueProducer.onDataPulled(allData, /** succeed */ true); + // Max delay is set to 0 so pull will exceed max delay. + valueProducer.onConditionChanged(true, bucketStartTimeNs + 1); + EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size()); +} - // has one slice +TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) { + 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()); + + ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, + eventMatcherWizard, tagId, bucket2StartTimeNs, + bucket2StartTimeNs, pullerManager); + + valueProducer.mCondition = false; + + // Event should be skipped since it is from previous bucket. + // Pull should not be called. + valueProducer.onConditionChanged(true, bucketStartTimeNs); + EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size()); +} + +TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) { + 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, _)) + .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + data->clear(); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); + event->write(tagId); + event->write(100); + event->init(); + data->push_back(event); + return true; + })); + + ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, + eventMatcherWizard, tagId, bucketStartTimeNs, + bucketStartTimeNs, pullerManager); + + valueProducer.mCondition = false; + valueProducer.mHasGlobalBase = false; + + valueProducer.onConditionChanged(true, bucketStartTimeNs + 1); + valueProducer.mHasGlobalBase = true; EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); ValueMetricProducer::Interval& curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); - EXPECT_EQ(110, curInterval.base.long_value); + EXPECT_EQ(100, curInterval.base.long_value); EXPECT_EQ(false, curInterval.hasValue); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); EXPECT_EQ(true, valueProducer.mHasGlobalBase); - - valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1); - - // has one slice - EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); - EXPECT_EQ(false, curInterval.hasValue); - EXPECT_EQ(false, curInterval.hasBase); - EXPECT_EQ(false, valueProducer.mHasGlobalBase); } TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) { diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java index 920a52dad641..d29e68e5a187 100644 --- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java +++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java @@ -19,6 +19,7 @@ package com.android.commands.svc; import android.content.Context; import android.os.BatteryManager; import android.os.IPowerManager; +import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -71,7 +72,8 @@ public class PowerCommand extends Svc.Command { if (val != 0) { // if the request is not to set it to false, wake up the screen so that // it can stay on as requested - pm.wakeUp(SystemClock.uptimeMillis(), "PowerCommand", null); + pm.wakeUp(SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_UNKNOWN, "PowerCommand", null); } pm.setStayOnSetting(val); } diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index aad412f15fe2..a0d8a1232257 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -828,7 +828,6 @@ Landroid/os/IPowerManager;->isInteractive()Z Landroid/os/IPowerManager;->reboot(ZLjava/lang/String;Z)V Landroid/os/IPowerManager;->releaseWakeLock(Landroid/os/IBinder;I)V Landroid/os/IPowerManager;->userActivity(JII)V -Landroid/os/IPowerManager;->wakeUp(JLjava/lang/String;Ljava/lang/String;)V Landroid/os/IRecoverySystem$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IRecoverySystem; Landroid/os/IRemoteCallback$Stub;-><init>()V Landroid/os/IRemoteCallback;->sendResult(Landroid/os/Bundle;)V diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 21d66e567a81..cc419b8d837a 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -4565,16 +4565,25 @@ public final class ActivityThread extends ClientTransactionHandler { } private void onCoreSettingsChange() { - boolean debugViewAttributes = - mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; - if (debugViewAttributes != View.mDebugViewAttributes) { - View.mDebugViewAttributes = debugViewAttributes; - + if (updateDebugViewAttributeState()) { // request all activities to relaunch for the changes to take place relaunchAllActivities(); } } + private boolean updateDebugViewAttributeState() { + boolean previousState = View.sDebugViewAttributes; + + View.sDebugViewAttributesApplicationPackage = mCoreSettings.getString( + Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, ""); + String currentPackage = (mBoundApplication != null && mBoundApplication.appInfo != null) + ? mBoundApplication.appInfo.packageName : ""; + View.sDebugViewAttributes = + mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0 + || View.sDebugViewAttributesApplicationPackage.equals(currentPackage); + return previousState != View.sDebugViewAttributes; + } + private void relaunchAllActivities() { for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) { final Activity activity = entry.getValue().activity; @@ -5950,8 +5959,7 @@ public final class ActivityThread extends ClientTransactionHandler { // true : use 24 hour format. DateFormat.set24HourTimePref(is24Hr); - View.mDebugViewAttributes = - mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; + updateDebugViewAttributeState(); StrictMode.initThreadDefaults(data.appInfo); StrictMode.initVmDefaults(data.appInfo); diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index a3021f371e19..d781a96420c7 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -817,28 +817,6 @@ public class Intent implements Parcelable, Cloneable { = "android.intent.action.SHOW_APP_INFO"; /** - * Activity Action: Start an activity to show the app's detailed usage information for - * permission protected data. - * - * The Intent contains an extra {@link #EXTRA_PERMISSION_USAGE_PERMISSIONS} that is of - * type {@code String[]} and contains the specific permissions to show information for. - * - * Apps should handle this intent if they want to provide more information about permission - * usage to users beyond the information provided in the manifest. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_PERMISSION_USAGE_DETAILS = - "android.intent.action.PERMISSION_USAGE_DETAILS"; - - /** - * The name of the extra used to contain the permissions in - * {@link #ACTION_PERMISSION_USAGE_DETAILS}. - * @see #ACTION_PERMISSION_USAGE_DETAILS - */ - public static final String EXTRA_PERMISSION_USAGE_PERMISSIONS = - "android.intent.extra.PERMISSION_USAGE_PERMISSIONS"; - - /** * Represents a shortcut/live folder icon resource. * * @see Intent#ACTION_CREATE_SHORTCUT diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index 6d22277a5384..27a5b392855e 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -204,10 +204,7 @@ public class PackageInfo implements Parcelable { * {@link PackageManager#GET_PERMISSIONS} was set. This list includes * all permissions requested, even those that were not granted or known * by the system at install time. - * - * @deprecated Use {@link #usesPermissions} */ - @Deprecated public String[] requestedPermissions; /** @@ -217,23 +214,10 @@ public class PackageInfo implements Parcelable { * {@link PackageManager#GET_PERMISSIONS} was set. Each value matches * the corresponding entry in {@link #requestedPermissions}, and will have * the flag {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate. - * - * @deprecated Use {@link #usesPermissions} */ - @Deprecated public int[] requestedPermissionsFlags; /** - * Array of all {@link android.R.styleable#AndroidManifestUsesPermission - * <uses-permission>} tags included under <manifest>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_PERMISSIONS} was set. This list includes - * all permissions requested, even those that were not granted or known - * by the system at install time. - */ - public UsesPermissionInfo[] usesPermissions; - - /** * Flag for {@link #requestedPermissionsFlags}: the requested permission * is required for the application to run; the user can not optionally * disable it. Currently all permissions are required. @@ -480,7 +464,6 @@ public class PackageInfo implements Parcelable { dest.writeTypedArray(permissions, parcelableFlags); dest.writeStringArray(requestedPermissions); dest.writeIntArray(requestedPermissionsFlags); - dest.writeTypedArray(usesPermissions, parcelableFlags); dest.writeTypedArray(signatures, parcelableFlags); dest.writeTypedArray(configPreferences, parcelableFlags); dest.writeTypedArray(reqFeatures, parcelableFlags); @@ -545,7 +528,6 @@ public class PackageInfo implements Parcelable { permissions = source.createTypedArray(PermissionInfo.CREATOR); requestedPermissions = source.createStringArray(); requestedPermissionsFlags = source.createIntArray(); - usesPermissions = source.createTypedArray(UsesPermissionInfo.CREATOR); signatures = source.createTypedArray(Signature.CREATOR); configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR); reqFeatures = source.createTypedArray(FeatureInfo.CREATOR); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 81ed110d15ec..5020a94c3469 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -791,23 +791,18 @@ public class PackageParser { pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags); } } - N = p.usesPermissionInfos.size(); + N = p.requestedPermissions.size(); if (N > 0) { pi.requestedPermissions = new String[N]; pi.requestedPermissionsFlags = new int[N]; - pi.usesPermissions = new UsesPermissionInfo[N]; for (int i=0; i<N; i++) { - UsesPermissionInfo info = p.usesPermissionInfos.get(i); - final String perm = info.getPermission(); + final String perm = p.requestedPermissions.get(i); pi.requestedPermissions[i] = perm; - int permissionFlags = 0; // The notion of required permissions is deprecated but for compatibility. - permissionFlags |= PackageInfo.REQUESTED_PERMISSION_REQUIRED; + pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED; if (grantedPermissions != null && grantedPermissions.contains(perm)) { - permissionFlags |= PackageInfo.REQUESTED_PERMISSION_GRANTED; + pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED; } - pi.requestedPermissionsFlags[i] = permissionFlags; - pi.usesPermissions[i] = new UsesPermissionInfo(info, permissionFlags); } } } @@ -2175,12 +2170,12 @@ public class PackageParser { return null; } } else if (tagName.equals(TAG_USES_PERMISSION)) { - if (!parseUsesPermission(pkg, res, parser, outError)) { + if (!parseUsesPermission(pkg, res, parser)) { return null; } } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M) || tagName.equals(TAG_USES_PERMISSION_SDK_23)) { - if (!parseUsesPermission(pkg, res, parser, outError)) { + if (!parseUsesPermission(pkg, res, parser)) { return null; } } else if (tagName.equals(TAG_USES_CONFIGURATION)) { @@ -2498,7 +2493,7 @@ public class PackageParser { newPermsMsg.append(' '); } newPermsMsg.append(npi.name); - addRequestedPermission(pkg, npi.name); + pkg.requestedPermissions.add(npi.name); pkg.implicitPermissions.add(npi.name); } } @@ -2519,7 +2514,7 @@ public class PackageParser { for (int in = 0; in < newPerms.size(); in++) { final String perm = newPerms.get(in); if (!pkg.requestedPermissions.contains(perm)) { - addRequestedPermission(pkg, perm); + pkg.requestedPermissions.add(perm); pkg.implicitPermissions.add(perm); } } @@ -2599,13 +2594,13 @@ public class PackageParser { } } else { if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) { - addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_AUDIO); + pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO); } if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) { - addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_VIDEO); + pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO); } if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) { - addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_IMAGES); + pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES); } } @@ -2645,12 +2640,6 @@ public class PackageParser { } /** - * Helper method for adding a requested permission to a package outside of a uses-permission. - */ - private void addRequestedPermission(Package pkg, String permission) { - pkg.requestedPermissions.add(permission); - pkg.usesPermissionInfos.add(new UsesPermissionInfo(permission)); - } /** * Matches a given {@code targetCode} against a set of release codeNames. Target codes can @@ -2987,8 +2976,8 @@ public class PackageParser { return certSha256Digests; } - private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser, - String[] outError) throws XmlPullParserException, IOException { + private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser) + throws XmlPullParserException, IOException { TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestUsesPermission); @@ -3012,44 +3001,6 @@ public class PackageParser { final String requiredNotfeature = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0); - int dataSentOffDevice = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSentOffDevice, 0); - - int dataSharedWithThirdParty = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSharedWithThirdParty, 0); - - int dataUsedForMonetization = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataUsedForMonetization, 0); - - int retentionWeeks = -1; - int retention; - - String rawRetention = sa.getString( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime); - - if (rawRetention == null) { - retention = UsesPermissionInfo.RETENTION_UNDEFINED; - } else if ("notRetained".equals(rawRetention)) { - retention = UsesPermissionInfo.RETENTION_NOT_RETAINED; - } else if ("userSelected".equals(rawRetention)) { - retention = UsesPermissionInfo.RETENTION_USER_SELECTED; - } else if ("unlimited".equals(rawRetention)) { - retention = UsesPermissionInfo.RETENTION_UNLIMITED; - } else { - // A number of weeks was specified - retention = UsesPermissionInfo.RETENTION_SPECIFIED; - retentionWeeks = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime, - -1); - - if (retentionWeeks < 0) { - outError[0] = "Bad value provided for dataRetentionTime."; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - XmlUtils.skipCurrentTag(parser); - sa.recycle(); - return false; - } - } sa.recycle(); XmlUtils.skipCurrentTag(parser); @@ -3082,10 +3033,6 @@ public class PackageParser { + parser.getPositionDescription()); } - UsesPermissionInfo info = new UsesPermissionInfo(name, dataSentOffDevice, - dataSharedWithThirdParty, dataUsedForMonetization, retention, retentionWeeks); - pkg.usesPermissionInfos.add(info); - return true; } @@ -3420,10 +3367,6 @@ public class PackageParser { perm.info.flags = sa.getInt( com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0); - perm.info.usageInfoRequired = sa.getInt( - com.android.internal.R.styleable.AndroidManifestPermission_usageInfoRequired, 0) - != 0; - sa.recycle(); if (perm.info.protectionLevel == -1) { @@ -6625,9 +6568,6 @@ public class PackageParser { @UnsupportedAppUsage public final ArrayList<String> requestedPermissions = new ArrayList<String>(); - public final ArrayList<UsesPermissionInfo> usesPermissionInfos = - new ArrayList<>(); - /** Permissions requested but not in the manifest. */ public final ArrayList<String> implicitPermissions = new ArrayList<>(); @@ -7159,7 +7099,6 @@ public class PackageParser { dest.readStringList(requestedPermissions); internStringArrayList(requestedPermissions); - dest.readParcelableList(usesPermissionInfos, boot); dest.readStringList(implicitPermissions); internStringArrayList(implicitPermissions); protectedBroadcasts = dest.createStringArrayList(); @@ -7327,7 +7266,6 @@ public class PackageParser { dest.writeParcelableList(instrumentation, flags); dest.writeStringList(requestedPermissions); - dest.writeParcelableList(usesPermissionInfos, flags); dest.writeStringList(implicitPermissions); dest.writeStringList(protectedBroadcasts); diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index fb63e0dad9b6..e24523406ab8 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -20,7 +20,6 @@ import android.annotation.IntDef; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; -import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -368,12 +367,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { */ public CharSequence nonLocalizedDescription; - /** - * If {@code true} an application targeting {@link Build.VERSION_CODES#Q} <em>must</em> - * include permission data usage information in order to be able to be granted this permission. - */ - public boolean usageInfoRequired; - /** @hide */ public static int fixProtectionLevel(int level) { if (level == PROTECTION_SIGNATURE_OR_SYSTEM) { @@ -475,7 +468,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { descriptionRes = orig.descriptionRes; requestRes = orig.requestRes; nonLocalizedDescription = orig.nonLocalizedDescription; - usageInfoRequired = orig.usageInfoRequired; } /** @@ -540,7 +532,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { dest.writeInt(descriptionRes); dest.writeInt(requestRes); TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); - dest.writeInt(usageInfoRequired ? 1 : 0); } /** @hide */ @@ -581,6 +572,5 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { descriptionRes = source.readInt(); requestRes = source.readInt(); nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - usageInfoRequired = source.readInt() != 0; } } diff --git a/core/java/android/content/pm/UsesPermissionInfo.java b/core/java/android/content/pm/UsesPermissionInfo.java deleted file mode 100644 index d08548fa31a5..000000000000 --- a/core/java/android/content/pm/UsesPermissionInfo.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.pm; - -import android.annotation.IntDef; -import android.os.Parcel; -import android.os.Parcelable; - -import java.lang.annotation.RetentionPolicy; -/** - * Information you can retrive about a particular application requested permission. This - * corresponds to information collected from the AndroidManifest.xml's <uses-permission> - * tags. - */ -public final class UsesPermissionInfo extends PackageItemInfo implements Parcelable { - - /** - * Flag for {@link #getFlags()}: the requested permission is currently granted to the - * application. - */ - public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 1 << 1; - - /** @hide */ - @IntDef(flag = true, prefix = {"FLAG_"}, value = {FLAG_REQUESTED_PERMISSION_GRANTED}) - @java.lang.annotation.Retention(RetentionPolicy.SOURCE) - public @interface Flags {} - - /** An unset value for {@link #getDataSentOffDevice()}, - * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()} - */ - public static final int USAGE_UNDEFINED = 0; - - /** - * A yes value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()}, - * and {@link #getDataUsedForMonetization()} corresponding to the <code>yes</code> value of - * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty}, - * and {@link android.R.attr#dataUsedForMonetization} attributes. - */ - public static final int USAGE_YES = 1; - - /** - * A user triggered only value for {@link #getDataSentOffDevice()}, - * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()} - * corresponding to the <code>userTriggered</code> value of - * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty}, - * and {@link android.R.attr#dataUsedForMonetization} attributes. - */ - public static final int USAGE_USER_TRIGGERED = 2; - - /** - * A no value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()}, - * and {@link #getDataUsedForMonetization()} corresponding to the <code>no</code> value of - * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty}, - * and {@link android.R.attr#dataUsedForMonetization} attributes. - */ - public static final int USAGE_NO = 3; - - /** @hide */ - @IntDef(prefix = {"USAGE_"}, value = { - USAGE_UNDEFINED, - USAGE_YES, - USAGE_USER_TRIGGERED, - USAGE_NO}) - @java.lang.annotation.Retention(RetentionPolicy.SOURCE) - public @interface Usage {} - - /** - * An unset value for {@link #getDataRetention}. - */ - public static final int RETENTION_UNDEFINED = 0; - - /** - * A data not retained value for {@link #getDataRetention()} corresponding to the - * <code>notRetained</code> value of {@link android.R.attr#dataRetentionTime}. - */ - public static final int RETENTION_NOT_RETAINED = 1; - - /** - * A user selected value for {@link #getDataRetention()} corresponding to the - * <code>userSelected</code> value of {@link android.R.attr#dataRetentionTime}. - */ - public static final int RETENTION_USER_SELECTED = 2; - - /** - * An unlimited value for {@link #getDataRetention()} corresponding to the - * <code>unlimited</code> value of {@link android.R.attr#dataRetentionTime}. - */ - public static final int RETENTION_UNLIMITED = 3; - - /** - * A specified value for {@link #getDataRetention()} corresponding to providing the number of - * weeks data is retained in {@link android.R.attr#dataRetentionTime}. The number of weeks - * is available in {@link #getDataRetentionWeeks()}. - */ - public static final int RETENTION_SPECIFIED = 4; - - /** @hide */ - @IntDef(prefix = {"RETENTION_"}, value = { - RETENTION_UNDEFINED, - RETENTION_NOT_RETAINED, - RETENTION_USER_SELECTED, - RETENTION_UNLIMITED, - RETENTION_SPECIFIED}) - @java.lang.annotation.Retention(RetentionPolicy.SOURCE) - public @interface Retention {} - - private final String mPermission; - private final @Flags int mFlags; - private final @Usage int mDataSentOffDevice; - private final @Usage int mDataSharedWithThirdParty; - private final @Usage int mDataUsedForMonetization; - private final @Retention int mDataRetention; - private final int mDataRetentionWeeks; - - /** @hide */ - public UsesPermissionInfo(String permission) { - mPermission = permission; - mDataSentOffDevice = USAGE_UNDEFINED; - mDataSharedWithThirdParty = USAGE_UNDEFINED; - mDataUsedForMonetization = USAGE_UNDEFINED; - mDataRetention = RETENTION_UNDEFINED; - mDataRetentionWeeks = -1; - mFlags = 0; - } - - /** @hide */ - public UsesPermissionInfo(String permission, - @Usage int dataSentOffDevice, @Usage int dataSharedWithThirdParty, - @Usage int dataUsedForMonetization, @Retention int dataRetention, - int dataRetentionWeeks) { - mPermission = permission; - mDataSentOffDevice = dataSentOffDevice; - mDataSharedWithThirdParty = dataSharedWithThirdParty; - mDataUsedForMonetization = dataUsedForMonetization; - mDataRetention = dataRetention; - mDataRetentionWeeks = dataRetentionWeeks; - mFlags = 0; - } - - /** @hide */ - public UsesPermissionInfo(UsesPermissionInfo orig) { - this(orig, orig.mFlags); - } - - /** @hide */ - public UsesPermissionInfo(UsesPermissionInfo orig, int flags) { - super(orig); - mPermission = orig.mPermission; - mFlags = flags; - mDataSentOffDevice = orig.mDataSentOffDevice; - mDataSharedWithThirdParty = orig.mDataSharedWithThirdParty; - mDataUsedForMonetization = orig.mDataUsedForMonetization; - mDataRetention = orig.mDataRetention; - mDataRetentionWeeks = orig.mDataRetentionWeeks; - } - - /** - * The name of the requested permission. - */ - public String getPermission() { - return mPermission; - } - - public @Flags int getFlags() { - return mFlags; - } - - /** - * If the application sends the data guarded by this permission off the device. - * - * See {@link android.R.attr#dataSentOffDevice} - */ - public @Usage int getDataSentOffDevice() { - return mDataSentOffDevice; - } - - /** - * If the application or its services shares the data guarded by this permission with third - * parties. - * - * See {@link android.R.attr#dataSharedWithThirdParty} - */ - public @Usage int getDataSharedWithThirdParty() { - return mDataSharedWithThirdParty; - } - - /** - * If the application or its services use the data guarded by this permission for monetization - * purposes. - * - * See {@link android.R.attr#dataUsedForMonetization} - */ - public @Usage int getDataUsedForMonetization() { - return mDataUsedForMonetization; - } - - /** - * How long the application or its services store the data guarded by this permission. - * If set to {@link #RETENTION_SPECIFIED} {@link #getDataRetentionWeeks()} will contain the - * number of weeks the data is stored. - * - * See {@link android.R.attr#dataRetentionTime} - */ - public @Retention int getDataRetention() { - return mDataRetention; - } - - /** - * If {@link #getDataRetention()} is {@link #RETENTION_SPECIFIED} the number of weeks the - * application or its services store data guarded by this permission. - * - * @throws IllegalStateException if {@link #getDataRetention} is not - * {@link #RETENTION_SPECIFIED}. - */ - public int getDataRetentionWeeks() { - if (mDataRetention != RETENTION_SPECIFIED) { - throw new IllegalStateException("Data retention weeks not specified"); - } - return mDataRetentionWeeks; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeString(mPermission); - dest.writeInt(mFlags); - dest.writeInt(mDataSentOffDevice); - dest.writeInt(mDataSharedWithThirdParty); - dest.writeInt(mDataUsedForMonetization); - dest.writeInt(mDataRetention); - dest.writeInt(mDataRetentionWeeks); - } - - private UsesPermissionInfo(Parcel source) { - super(source); - mPermission = source.readString(); - mFlags = source.readInt(); - mDataSentOffDevice = source.readInt(); - mDataSharedWithThirdParty = source.readInt(); - mDataUsedForMonetization = source.readInt(); - mDataRetention = source.readInt(); - mDataRetentionWeeks = source.readInt(); - } - - public static final Creator<UsesPermissionInfo> CREATOR = - new Creator<UsesPermissionInfo>() { - @Override - public UsesPermissionInfo createFromParcel(Parcel source) { - return new UsesPermissionInfo(source); - } - @Override - public UsesPermissionInfo[] newArray(int size) { - return new UsesPermissionInfo[size]; - } - }; -} diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 9e0a9ba0dc7b..faf17e011b23 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -1051,6 +1051,14 @@ public final class AssetManager implements AutoCloseable { } } + int[] getAttributeResolutionStack(long themePtr, @AttrRes int defStyleAttr, + @StyleRes int defStyleRes, @StyleRes int xmlStyle) { + synchronized (this) { + return nativeAttributeResolutionStack( + mObject, themePtr, xmlStyle, defStyleAttr, defStyleRes); + } + } + @UnsupportedAppUsage boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues, @@ -1419,6 +1427,8 @@ public final class AssetManager implements AutoCloseable { private static native @Nullable String nativeGetLastResourceResolution(long ptr); // Style attribute retrieval native methods. + private static native int[] nativeAttributeResolutionStack(long ptr, long themePtr, + @StyleRes int xmlStyleRes, @AttrRes int defStyleAttr, @StyleRes int defStyleRes); private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs, long outValuesAddress, long outIndicesAddress); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 59db49e0d37e..a2ae994f7b0f 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1725,6 +1725,68 @@ public class Resources { public void rebase() { mThemeImpl.rebase(); } + + /** + * Returns the resource ID for the style specified using {@code style="..."} in the + * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not + * specified or otherwise not applicable. + * <p> + * Each {@link android.view.View} can have an explicit style specified in the layout file. + * This style is used first during the {@link android.view.View} attribute resolution, then + * if an attribute is not defined there the resource system looks at default style and theme + * as fallbacks. + * + * @param set The base set of attribute values. + * + * @return The resource ID for the style specified using {@code style="..."} in the + * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise + * if not specified or otherwise not applicable. + */ + @StyleRes + public int getExplicitStyle(@Nullable AttributeSet set) { + if (set == null) { + return ID_NULL; + } + int styleAttr = set.getStyleAttribute(); + if (styleAttr == ID_NULL) { + return ID_NULL; + } + String styleAttrType = getResources().getResourceTypeName(styleAttr); + if ("attr".equals(styleAttrType)) { + TypedValue explicitStyle = new TypedValue(); + boolean resolved = resolveAttribute(styleAttr, explicitStyle, true); + if (resolved) { + return explicitStyle.resourceId; + } + } else if ("style".equals(styleAttrType)) { + return styleAttr; + } + return ID_NULL; + } + + /** + * Returns the ordered list of resource ID that are considered when resolving attribute + * values when making an equivalent call to + * {@link #obtainStyledAttributes(AttributeSet, int[], int, int)} . The list will include + * a set of explicit styles ({@code explicitStyleRes} and it will include the default styles + * ({@code defStyleAttr} and {@code defStyleRes}). + * + * @param defStyleAttr An attribute in the current theme that contains a + * reference to a style resource that supplies + * defaults values for the TypedArray. Can be + * 0 to not look for defaults. + * @param defStyleRes A resource identifier of a style resource that + * supplies default values for the TypedArray, + * used only if defStyleAttr is 0 or can not be found + * in the theme. Can be 0 to not look for defaults. + * @param explicitStyleRes A resource identifier of an explicit style resource. + * @return ordered list of resource ID that are considered when resolving attribute values. + */ + public int[] getAttributeResolutionStack(@AttrRes int defStyleAttr, + @StyleRes int defStyleRes, @StyleRes int explicitStyleRes) { + return mThemeImpl.getAttributeResolutionStack( + defStyleAttr, defStyleRes, explicitStyleRes); + } } static class ThemeKey implements Cloneable { diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 98980799a365..da064c956fcc 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -1488,6 +1488,32 @@ public class ResourcesImpl { } } } + + /** + * Returns the ordered list of resource ID that are considered when resolving attribute + * values when making an equivalent call to + * {@link #obtainStyledAttributes(Resources.Theme, AttributeSet, int[], int, int)}. The list + * will include a set of explicit styles ({@code explicitStyleRes} and it will include the + * default styles ({@code defStyleAttr} and {@code defStyleRes}). + * + * @param defStyleAttr An attribute in the current theme that contains a + * reference to a style resource that supplies + * defaults values for the TypedArray. Can be + * 0 to not look for defaults. + * @param defStyleRes A resource identifier of a style resource that + * supplies default values for the TypedArray, + * used only if defStyleAttr is 0 or can not be found + * in the theme. Can be 0 to not look for defaults. + * @param explicitStyleRes A resource identifier of an explicit style resource. + * @return ordered list of resource ID that are considered when resolving attribute values. + */ + public int[] getAttributeResolutionStack(@AttrRes int defStyleAttr, + @StyleRes int defStyleRes, @StyleRes int explicitStyleRes) { + synchronized (mKey) { + return mAssets.getAttributeResolutionStack( + mTheme, defStyleAttr, defStyleRes, explicitStyleRes); + } + } } private static class LookupStack { diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 1881a0cd32e8..0e4ff78af1e0 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1159,9 +1159,10 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>Each output JPEG size in android.scaler.availableStreamConfigurations will have at least * one corresponding size that has the same aspect ratio in availableThumbnailSizes, * and vice versa.</li> - * <li>All non-<code>(0, 0)</code> sizes will have non-zero widths and heights. - * This key is available on all devices.</li> + * <li>All non-<code>(0, 0)</code> sizes will have non-zero widths and heights.</li> * </ul> + * <p>This list is also used as supported thumbnail sizes for HEIC image format capture.</p> + * <p>This key is available on all devices.</p> * * @see CaptureRequest#JPEG_THUMBNAIL_SIZE */ @@ -3838,6 +3839,74 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri public static final Key<int[]> DISTORTION_CORRECTION_AVAILABLE_MODES = new Key<int[]>("android.distortionCorrection.availableModes", int[].class); + /** + * <p>The available HEIC (ISO/IEC 23008-12) stream + * configurations that this camera device supports + * (i.e. format, width, height, output/input stream).</p> + * <p>The configurations are listed as <code>(format, width, height, input?)</code> tuples.</p> + * <p>If the camera device supports HEIC image format, it will support identical set of stream + * combinations involving HEIC image format, compared to the combinations involving JPEG + * image format as required by the device's hardware level and capabilities.</p> + * <p>All the static, control, and dynamic metadata tags related to JPEG apply to HEIC formats. + * Configuring JPEG and HEIC streams at the same time is not supported.</p> + * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> + * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + * @hide + */ + public static final Key<android.hardware.camera2.params.StreamConfiguration[]> HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS = + new Key<android.hardware.camera2.params.StreamConfiguration[]>("android.heic.availableHeicStreamConfigurations", android.hardware.camera2.params.StreamConfiguration[].class); + + /** + * <p>This lists the minimum frame duration for each + * format/size combination for HEIC output formats.</p> + * <p>This should correspond to the frame duration when only that + * stream is active, with all processing (typically in android.*.mode) + * set to either OFF or FAST.</p> + * <p>When multiple streams are used in a request, the minimum frame + * duration will be max(individual stream min durations).</p> + * <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} and + * android.scaler.availableStallDurations for more details about + * calculating the max frame rate.</p> + * <p><b>Units</b>: (format, width, height, ns) x n</p> + * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> + * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + * @see CaptureRequest#SENSOR_FRAME_DURATION + * @hide + */ + public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS = + new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.heic.availableHeicMinFrameDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class); + + /** + * <p>This lists the maximum stall duration for each + * output format/size combination for HEIC streams.</p> + * <p>A stall duration is how much extra time would get added + * to the normal minimum frame duration for a repeating request + * that has streams with non-zero stall.</p> + * <p>This functions similarly to + * android.scaler.availableStallDurations for HEIC + * streams.</p> + * <p>All HEIC output stream formats may have a nonzero stall + * duration.</p> + * <p><b>Units</b>: (format, width, height, ns) x n</p> + * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> + * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + * @hide + */ + public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> HEIC_AVAILABLE_HEIC_STALL_DURATIONS = + new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.heic.availableHeicStallDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class); + /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ * End generated code *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/ diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 9c213f2f27a5..20fc53fee2e6 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -356,12 +356,6 @@ public abstract class CameraDevice implements AutoCloseable { * </table><br> * </p> * - * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} - * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices - * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV} - * streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level - * and capabilities.</p> - * * <p>FULL-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL} * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices * support at least the following stream combinations in addition to those for @@ -435,6 +429,18 @@ public abstract class CameraDevice implements AutoCloseable { * </table><br> * </p> * + * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} + * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices + * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV} + * streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level + * and capabilities.</p> + * + * <p>Devices capable of outputting HEIC formats ({@link StreamConfigurationMap#getOutputFormats} + * contains {@link android.graphics.ImageFormat#HEIC}) will support substituting {@code JPEG} + * streams with {@code HEIC} in all guaranteed stream combinations for the device's hardware + * level and capabilities. Calling createCaptureSession with both JPEG and HEIC outputs is not + * supported.</p> + * * <p>Clients can access the above mandatory stream combination tables via * {@link android.hardware.camera2.params.MandatoryStreamCombination}.</p> * diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 3d3a916bae7a..525070103c2c 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -2126,6 +2126,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>Setting a location object in a request will include the GPS coordinates of the location * into any JPEG images captured based on the request. These coordinates can then be * viewed by anyone who receives the JPEG image.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p>This key is available on all devices.</p> */ @PublicKey @@ -2136,6 +2137,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>GPS coordinates to include in output JPEG * EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * (-180 - 180], [-90,90], [-inf, inf]</p> * <p>This key is available on all devices.</p> @@ -2147,6 +2149,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>32 characters describing GPS algorithm to * include in EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p>This key is available on all devices.</p> * @hide */ @@ -2156,6 +2159,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>Time GPS fix was made to include in * EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p><b>Units</b>: UTC in seconds since January 1, 1970</p> * <p>This key is available on all devices.</p> * @hide @@ -2195,6 +2199,10 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * </code></pre> * <p>For EXTERNAL cameras the sensor orientation will always be set to 0 and the facing will * also be set to EXTERNAL. The above code is not relevant in such case.</p> + * <p>This tag is also used to describe the orientation of the HEIC image capture, in which + * case the rotation is reflected by + * {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}, and not by + * rotating the image data itself.</p> * <p><b>Units</b>: Degrees in multiples of 90</p> * <p><b>Range of valid values:</b><br> * 0, 90, 180, 270</p> @@ -2209,7 +2217,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>Compression quality of the final JPEG * image.</p> - * <p>85-95 is typical usage range.</p> + * <p>85-95 is typical usage range. This tag is also used to describe the quality + * of the HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * 1-100; larger is higher quality</p> * <p>This key is available on all devices.</p> @@ -2221,6 +2230,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>Compression quality of JPEG * thumbnail.</p> + * <p>This tag is also used to describe the quality of the HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * 1-100; larger is higher quality</p> * <p>This key is available on all devices.</p> @@ -2253,6 +2263,10 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * orientation is requested. LEGACY device will always report unrotated thumbnail * size.</li> * </ul> + * <p>The tag is also used as thumbnail size for HEIC image format capture, in which case the + * the thumbnail rotation is reflected by + * {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}, and not by + * rotating the thumbnail data itself.</p> * <p><b>Range of valid values:</b><br> * {@link CameraCharacteristics#JPEG_AVAILABLE_THUMBNAIL_SIZES android.jpeg.availableThumbnailSizes}</p> * <p>This key is available on all devices.</p> diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 8982b40be29b..13ad092f6efd 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -2450,6 +2450,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>Setting a location object in a request will include the GPS coordinates of the location * into any JPEG images captured based on the request. These coordinates can then be * viewed by anyone who receives the JPEG image.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p>This key is available on all devices.</p> */ @PublicKey @@ -2460,6 +2461,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>GPS coordinates to include in output JPEG * EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * (-180 - 180], [-90,90], [-inf, inf]</p> * <p>This key is available on all devices.</p> @@ -2471,6 +2473,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>32 characters describing GPS algorithm to * include in EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p>This key is available on all devices.</p> * @hide */ @@ -2480,6 +2483,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>Time GPS fix was made to include in * EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p><b>Units</b>: UTC in seconds since January 1, 1970</p> * <p>This key is available on all devices.</p> * @hide @@ -2519,6 +2523,10 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </code></pre> * <p>For EXTERNAL cameras the sensor orientation will always be set to 0 and the facing will * also be set to EXTERNAL. The above code is not relevant in such case.</p> + * <p>This tag is also used to describe the orientation of the HEIC image capture, in which + * case the rotation is reflected by + * {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}, and not by + * rotating the image data itself.</p> * <p><b>Units</b>: Degrees in multiples of 90</p> * <p><b>Range of valid values:</b><br> * 0, 90, 180, 270</p> @@ -2533,7 +2541,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>Compression quality of the final JPEG * image.</p> - * <p>85-95 is typical usage range.</p> + * <p>85-95 is typical usage range. This tag is also used to describe the quality + * of the HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * 1-100; larger is higher quality</p> * <p>This key is available on all devices.</p> @@ -2545,6 +2554,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>Compression quality of JPEG * thumbnail.</p> + * <p>This tag is also used to describe the quality of the HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * 1-100; larger is higher quality</p> * <p>This key is available on all devices.</p> @@ -2577,6 +2587,10 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * orientation is requested. LEGACY device will always report unrotated thumbnail * size.</li> * </ul> + * <p>The tag is also used as thumbnail size for HEIC image format capture, in which case the + * the thumbnail rotation is reflected by + * {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}, and not by + * rotating the thumbnail data itself.</p> * <p><b>Range of valid values:</b><br> * {@link CameraCharacteristics#JPEG_AVAILABLE_THUMBNAIL_SIZES android.jpeg.availableThumbnailSizes}</p> * <p>This key is available on all devices.</p> diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 7877a4d51313..65026b6feb9f 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -1133,6 +1133,9 @@ public class CameraMetadataNative implements Parcelable { /*dynamicDepthConfigurations*/ null, /*dynamicDepthMinFrameDurations*/ null, /*dynamicDepthStallDurations*/ null, + /*heicconfiguration*/ null, + /*heicminduration*/ null, + /*heicstallduration*/ null, /*highspeedvideoconfigurations*/ null, /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]); break; @@ -1144,6 +1147,9 @@ public class CameraMetadataNative implements Parcelable { /*dynamicDepthConfigurations*/ null, /*dynamicDepthMinFrameDurations*/ null, /*dynamicDepthStallDurations*/ null, + /*heicconfiguration*/ null, + /*heicminduration*/ null, + /*heicstallduration*/ null, highSpeedVideoConfigurations, /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]); break; @@ -1155,6 +1161,9 @@ public class CameraMetadataNative implements Parcelable { /*dynamicDepthConfigurations*/ null, /*dynamicDepthMinFrameDurations*/ null, /*dynamicDepthStallDurations*/ null, + /*heicconfiguration*/ null, + /*heicminduration*/ null, + /*heicstallduration*/ null, /*highSpeedVideoConfigurations*/ null, inputOutputFormatsMap, listHighResolution, supportsPrivate[i]); break; @@ -1166,6 +1175,9 @@ public class CameraMetadataNative implements Parcelable { /*dynamicDepthConfigurations*/ null, /*dynamicDepthMinFrameDurations*/ null, /*dynamicDepthStallDurations*/ null, + /*heicconfiguration*/ null, + /*heicminduration*/ null, + /*heicstallduration*/ null, /*highSpeedVideoConfigurations*/ null, /*inputOutputFormatsMap*/ null, listHighResolution, supportsPrivate[i]); } @@ -1230,6 +1242,12 @@ public class CameraMetadataNative implements Parcelable { CameraCharacteristics.DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS); StreamConfigurationDuration[] dynamicDepthStallDurations = getBase( CameraCharacteristics.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS); + StreamConfiguration[] heicConfigurations = getBase( + CameraCharacteristics.HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS); + StreamConfigurationDuration[] heicMinFrameDurations = getBase( + CameraCharacteristics.HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS); + StreamConfigurationDuration[] heicStallDurations = getBase( + CameraCharacteristics.HEIC_AVAILABLE_HEIC_STALL_DURATIONS); HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase( CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS); ReprocessFormatsMap inputOutputFormatsMap = getBase( @@ -1239,7 +1257,9 @@ public class CameraMetadataNative implements Parcelable { configurations, minFrameDurations, stallDurations, depthConfigurations, depthMinFrameDurations, depthStallDurations, dynamicDepthConfigurations, dynamicDepthMinFrameDurations, - dynamicDepthStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap, + dynamicDepthStallDurations, heicConfigurations, + heicMinFrameDurations, heicStallDurations, + highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution); } diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java index a22e008a65fd..996f9978a612 100644 --- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java @@ -79,6 +79,22 @@ public final class StreamConfigurationMap { * @param configurations a non-{@code null} array of {@link StreamConfiguration} * @param minFrameDurations a non-{@code null} array of {@link StreamConfigurationDuration} * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration} + * @param depthConfigurations a non-{@code null} array of depth {@link StreamConfiguration} + * @param depthMinFrameDurations a non-{@code null} array of depth + * {@link StreamConfigurationDuration} + * @param depthStallDurations a non-{@code null} array of depth + * {@link StreamConfigurationDuration} + * @param dynamicDepthConfigurations a non-{@code null} array of dynamic depth + * {@link StreamConfiguration} + * @param dynamicDepthMinFrameDurations a non-{@code null} array of dynamic depth + * {@link StreamConfigurationDuration} + * @param dynamicDepthStallDurations a non-{@code null} array of dynamic depth + * {@link StreamConfigurationDuration} + * @param heicConfigurations a non-{@code null} array of heic {@link StreamConfiguration} + * @param heicMinFrameDurations a non-{@code null} array of heic + * {@link StreamConfigurationDuration} + * @param heicStallDurations a non-{@code null} array of heic + * {@link StreamConfigurationDuration} * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if * camera device does not support high speed video recording * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE @@ -98,14 +114,19 @@ public final class StreamConfigurationMap { StreamConfiguration[] dynamicDepthConfigurations, StreamConfigurationDuration[] dynamicDepthMinFrameDurations, StreamConfigurationDuration[] dynamicDepthStallDurations, + StreamConfiguration[] heicConfigurations, + StreamConfigurationDuration[] heicMinFrameDurations, + StreamConfigurationDuration[] heicStallDurations, HighSpeedVideoConfiguration[] highSpeedVideoConfigurations, ReprocessFormatsMap inputOutputFormatsMap, boolean listHighResolution) { this(configurations, minFrameDurations, stallDurations, depthConfigurations, depthMinFrameDurations, depthStallDurations, dynamicDepthConfigurations, dynamicDepthMinFrameDurations, - dynamicDepthStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap, - listHighResolution, /*enforceImplementationDefined*/ true); + dynamicDepthStallDurations, + heicConfigurations, heicMinFrameDurations, heicStallDurations, + highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution, + /*enforceImplementationDefined*/ true); } /** @@ -117,6 +138,22 @@ public final class StreamConfigurationMap { * @param configurations a non-{@code null} array of {@link StreamConfiguration} * @param minFrameDurations a non-{@code null} array of {@link StreamConfigurationDuration} * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration} + * @param depthConfigurations a non-{@code null} array of depth {@link StreamConfiguration} + * @param depthMinFrameDurations a non-{@code null} array of depth + * {@link StreamConfigurationDuration} + * @param depthStallDurations a non-{@code null} array of depth + * {@link StreamConfigurationDuration} + * @param dynamicDepthConfigurations a non-{@code null} array of dynamic depth + * {@link StreamConfiguration} + * @param dynamicDepthMinFrameDurations a non-{@code null} array of dynamic depth + * {@link StreamConfigurationDuration} + * @param dynamicDepthStallDurations a non-{@code null} array of dynamic depth + * {@link StreamConfigurationDuration} + * @param heicConfigurations a non-{@code null} array of heic {@link StreamConfiguration} + * @param heicMinFrameDurations a non-{@code null} array of heic + * {@link StreamConfigurationDuration} + * @param heicStallDurations a non-{@code null} array of heic + * {@link StreamConfigurationDuration} * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if * camera device does not support high speed video recording * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE @@ -138,14 +175,23 @@ public final class StreamConfigurationMap { StreamConfiguration[] dynamicDepthConfigurations, StreamConfigurationDuration[] dynamicDepthMinFrameDurations, StreamConfigurationDuration[] dynamicDepthStallDurations, + StreamConfiguration[] heicConfigurations, + StreamConfigurationDuration[] heicMinFrameDurations, + StreamConfigurationDuration[] heicStallDurations, HighSpeedVideoConfiguration[] highSpeedVideoConfigurations, ReprocessFormatsMap inputOutputFormatsMap, boolean listHighResolution, boolean enforceImplementationDefined) { + if (configurations == null && + depthConfigurations == null && + heicConfigurations == null) { + throw new NullPointerException("At least one of color/depth/heic configurations " + + "must not be null"); + } + if (configurations == null) { // If no color configurations exist, ensure depth ones do - checkArrayElementsNotNull(depthConfigurations, "depthConfigurations"); mConfigurations = new StreamConfiguration[0]; mMinFrameDurations = new StreamConfigurationDuration[0]; mStallDurations = new StreamConfigurationDuration[0]; @@ -183,6 +229,19 @@ public final class StreamConfigurationMap { "dynamicDepthStallDurations"); } + if (heicConfigurations == null) { + mHeicConfigurations = new StreamConfiguration[0]; + mHeicMinFrameDurations = new StreamConfigurationDuration[0]; + mHeicStallDurations = new StreamConfigurationDuration[0]; + } else { + mHeicConfigurations = checkArrayElementsNotNull(heicConfigurations, + "heicConfigurations"); + mHeicMinFrameDurations = checkArrayElementsNotNull(heicMinFrameDurations, + "heicMinFrameDurations"); + mHeicStallDurations = checkArrayElementsNotNull(heicStallDurations, + "heicStallDurations"); + } + if (highSpeedVideoConfigurations == null) { mHighSpeedVideoConfigurations = new HighSpeedVideoConfiguration[0]; } else { @@ -235,6 +294,17 @@ public final class StreamConfigurationMap { mDynamicDepthOutputFormats.get(config.getFormat()) + 1); } + // For each heic format, track how many sizes there are available to configure + for (StreamConfiguration config : mHeicConfigurations) { + if (!config.isOutput()) { + // Ignoring input depth configs + continue; + } + + mHeicOutputFormats.put(config.getFormat(), + mHeicOutputFormats.get(config.getFormat()) + 1); + } + if (configurations != null && enforceImplementationDefined && mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) { throw new AssertionError( @@ -302,7 +372,16 @@ public final class StreamConfigurationMap { if (mInputOutputFormatsMap == null) { return new int[0]; } - return mInputOutputFormatsMap.getOutputs(inputFormat); + + int[] outputs = mInputOutputFormatsMap.getOutputs(inputFormat); + if (mHeicOutputFormats.size() > 0) { + // All reprocessing formats map contain JPEG. + int[] outputsWithHeic = Arrays.copyOf(outputs, outputs.length+1); + outputsWithHeic[outputs.length] = ImageFormat.HEIC; + return outputsWithHeic; + } else { + return outputs; + } } /** @@ -366,6 +445,8 @@ public final class StreamConfigurationMap { return mDepthOutputFormats.indexOfKey(internalFormat) >= 0; } else if (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) { return mDynamicDepthOutputFormats.indexOfKey(internalFormat) >= 0; + } else if (dataspace == HAL_DATASPACE_HEIF) { + return mHeicOutputFormats.indexOfKey(internalFormat) >= 0; } else { return getFormatsMap(/*output*/true).indexOfKey(internalFormat) >= 0; } @@ -479,6 +560,7 @@ public final class StreamConfigurationMap { StreamConfiguration[] configs = surfaceDataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations : surfaceDataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations : + surfaceDataspace == HAL_DATASPACE_HEIF ? mHeicConfigurations : mConfigurations; for (StreamConfiguration config : configs) { if (config.getFormat() == surfaceFormat && config.isOutput()) { @@ -512,9 +594,10 @@ public final class StreamConfigurationMap { int dataspace = imageFormatToDataspace(format); StreamConfiguration[] configs = - dataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations : - dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations : - mConfigurations; + dataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations : + dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations : + dataspace == HAL_DATASPACE_HEIF ? mHeicConfigurations : + mConfigurations; for (StreamConfiguration config : configs) { if ((config.getFormat() == internalFormat) && config.isOutput() && config.getSize().equals(size)) { @@ -1033,6 +1116,9 @@ public final class StreamConfigurationMap { Arrays.equals(mDynamicDepthMinFrameDurations, other.mDynamicDepthMinFrameDurations) && Arrays.equals(mDynamicDepthStallDurations, other.mDynamicDepthStallDurations) && + Arrays.equals(mHeicConfigurations, other.mHeicConfigurations) && + Arrays.equals(mHeicMinFrameDurations, other.mHeicMinFrameDurations) && + Arrays.equals(mHeicStallDurations, other.mHeicStallDurations) && Arrays.equals(mHighSpeedVideoConfigurations, other.mHighSpeedVideoConfigurations); } @@ -1049,7 +1135,9 @@ public final class StreamConfigurationMap { mConfigurations, mMinFrameDurations, mStallDurations, mDepthConfigurations, mDepthMinFrameDurations, mDepthStallDurations, mDynamicDepthConfigurations, mDynamicDepthMinFrameDurations, - mDynamicDepthStallDurations, mHighSpeedVideoConfigurations); + mDynamicDepthStallDurations, mHeicConfigurations, + mHeicMinFrameDurations, mHeicStallDurations, + mHighSpeedVideoConfigurations); } // Check that the argument is supported by #getOutputFormats or #getInputFormats @@ -1068,6 +1156,10 @@ public final class StreamConfigurationMap { if (mDynamicDepthOutputFormats.indexOfKey(internalFormat) >= 0) { return format; } + } else if (internalDataspace == HAL_DATASPACE_HEIF) { + if (mHeicOutputFormats.indexOfKey(internalFormat) >= 0) { + return format; + } } else { if (mAllOutputFormats.indexOfKey(internalFormat) >= 0) { return format; @@ -1108,8 +1200,9 @@ public final class StreamConfigurationMap { case HAL_PIXEL_FORMAT_Y16: return format; case ImageFormat.JPEG: + case ImageFormat.HEIC: throw new IllegalArgumentException( - "ImageFormat.JPEG is an unknown internal format"); + "An unknown internal format: " + format); default: return checkArgumentFormat(format); } @@ -1267,6 +1360,8 @@ public final class StreamConfigurationMap { * <ul> * <li>ImageFormat.JPEG => HAL_PIXEL_FORMAT_BLOB * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_PIXEL_FORMAT_BLOB + * <li>ImageFormat.DEPTH_JPEG => HAL_PIXEL_FORMAT_BLOB + * <li>ImageFormat.HEIC => HAL_PIXEL_FORMAT_BLOB * <li>ImageFormat.DEPTH16 => HAL_PIXEL_FORMAT_Y16 * </ul> * </p> @@ -1292,6 +1387,7 @@ public final class StreamConfigurationMap { case ImageFormat.JPEG: case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: return HAL_PIXEL_FORMAT_BLOB; case ImageFormat.DEPTH16: return HAL_PIXEL_FORMAT_Y16; @@ -1312,6 +1408,7 @@ public final class StreamConfigurationMap { * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH * <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH * <li>ImageFormat.DEPTH_JPEG => HAL_DATASPACE_DYNAMIC_DEPTH + * <li>ImageFormat.HEIC => HAL_DATASPACE_HEIF * <li>others => HAL_DATASPACE_UNKNOWN * </ul> * </p> @@ -1343,6 +1440,8 @@ public final class StreamConfigurationMap { return HAL_DATASPACE_DEPTH; case ImageFormat.DEPTH_JPEG: return HAL_DATASPACE_DYNAMIC_DEPTH; + case ImageFormat.HEIC: + return HAL_DATASPACE_HEIF; default: return HAL_DATASPACE_UNKNOWN; } @@ -1394,14 +1493,17 @@ public final class StreamConfigurationMap { !output ? mInputFormats : dataspace == HAL_DATASPACE_DEPTH ? mDepthOutputFormats : dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthOutputFormats : + dataspace == HAL_DATASPACE_HEIF ? mHeicOutputFormats : highRes ? mHighResOutputFormats : mOutputFormats; int sizesCount = formatsMap.get(format); if ( ((!output || (dataspace == HAL_DATASPACE_DEPTH || - dataspace == HAL_DATASPACE_DYNAMIC_DEPTH)) && sizesCount == 0) || + dataspace == HAL_DATASPACE_DYNAMIC_DEPTH || + dataspace == HAL_DATASPACE_HEIF)) && sizesCount == 0) || (output && (dataspace != HAL_DATASPACE_DEPTH && - dataspace != HAL_DATASPACE_DYNAMIC_DEPTH) && + dataspace != HAL_DATASPACE_DYNAMIC_DEPTH && + dataspace != HAL_DATASPACE_HEIF) && mAllOutputFormats.get(format) == 0)) { // Only throw if this is really not supported at all throw new IllegalArgumentException("format not available"); @@ -1413,10 +1515,12 @@ public final class StreamConfigurationMap { StreamConfiguration[] configurations = (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthConfigurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicConfigurations : mConfigurations; StreamConfigurationDuration[] minFrameDurations = (dataspace == HAL_DATASPACE_DEPTH) ? mDepthMinFrameDurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthMinFrameDurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicMinFrameDurations : mMinFrameDurations; for (StreamConfiguration config : configurations) { @@ -1445,7 +1549,8 @@ public final class StreamConfigurationMap { } // Dynamic depth streams can have both fast and also high res modes. - if ((sizeIndex != sizesCount) && (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH)) { + if ((sizeIndex != sizesCount) && (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH || + dataspace == HAL_DATASPACE_HEIF)) { if (sizeIndex > sizesCount) { throw new AssertionError( @@ -1485,6 +1590,9 @@ public final class StreamConfigurationMap { // Only one publicly dynamic depth format is available. formats[i++] = ImageFormat.DEPTH_JPEG; } + if (mHeicOutputFormats.size() > 0) { + formats[i++] = ImageFormat.HEIC; + } } if (formats.length != i) { throw new AssertionError("Too few formats " + i + ", expected " + formats.length); @@ -1529,10 +1637,14 @@ public final class StreamConfigurationMap { case DURATION_MIN_FRAME: return (dataspace == HAL_DATASPACE_DEPTH) ? mDepthMinFrameDurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? - mDynamicDepthMinFrameDurations : mMinFrameDurations; + mDynamicDepthMinFrameDurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicMinFrameDurations : + mMinFrameDurations; + case DURATION_STALL: return (dataspace == HAL_DATASPACE_DEPTH) ? mDepthStallDurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthStallDurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicStallDurations : mStallDurations; default: throw new IllegalArgumentException("duration was invalid"); @@ -1546,6 +1658,7 @@ public final class StreamConfigurationMap { if (output) { size += mDepthOutputFormats.size(); size += mDynamicDepthOutputFormats.size(); + size += mHeicOutputFormats.size(); } return size; @@ -1569,6 +1682,7 @@ public final class StreamConfigurationMap { StreamConfiguration[] configurations = (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthConfigurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicConfigurations : mConfigurations; for (int i = 0; i < configurations.length; i++) { @@ -1767,6 +1881,8 @@ public final class StreamConfigurationMap { return "RAW_DEPTH"; case ImageFormat.PRIVATE: return "PRIVATE"; + case ImageFormat.HEIC: + return "HEIC"; default: return "UNKNOWN"; } @@ -1795,7 +1911,7 @@ public final class StreamConfigurationMap { private static final int HAL_DATASPACE_DEPTH = 0x1000; private static final int HAL_DATASPACE_DYNAMIC_DEPTH = 0x1002; - + private static final int HAL_DATASPACE_HEIF = 0x1003; private static final long DURATION_20FPS_NS = 50000000L; /** * @see #getDurations(int, int) @@ -1815,6 +1931,10 @@ public final class StreamConfigurationMap { private final StreamConfigurationDuration[] mDynamicDepthMinFrameDurations; private final StreamConfigurationDuration[] mDynamicDepthStallDurations; + private final StreamConfiguration[] mHeicConfigurations; + private final StreamConfigurationDuration[] mHeicMinFrameDurations; + private final StreamConfigurationDuration[] mHeicStallDurations; + private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations; private final ReprocessFormatsMap mInputOutputFormatsMap; @@ -1834,6 +1954,9 @@ public final class StreamConfigurationMap { private final SparseIntArray mDepthOutputFormats = new SparseIntArray(); /** internal format -> num dynamic depth output sizes mapping, for HAL_DATASPACE_DYNAMIC_DEPTH */ private final SparseIntArray mDynamicDepthOutputFormats = new SparseIntArray(); + /** internal format -> num heic output sizes mapping, for HAL_DATASPACE_HEIF */ + private final SparseIntArray mHeicOutputFormats = new SparseIntArray(); + /** High speed video Size -> FPS range count mapping*/ private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap = new HashMap<Size, Integer>(); diff --git a/core/java/android/hardware/display/NightDisplayListener.java b/core/java/android/hardware/display/NightDisplayListener.java new file mode 100644 index 000000000000..468f8332dc2b --- /dev/null +++ b/core/java/android/hardware/display/NightDisplayListener.java @@ -0,0 +1,153 @@ +/* + * 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.hardware.display; + +import android.annotation.NonNull; +import android.annotation.UserIdInt; +import android.app.ActivityManager; +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings.Secure; + +import java.time.LocalTime; + +/** + * @hide + */ +public class NightDisplayListener { + + private final Context mContext; + private final int mUserId; + private final ColorDisplayManager mManager; + + private ContentObserver mContentObserver; + private Callback mCallback; + + public NightDisplayListener(@NonNull Context context) { + this(context, ActivityManager.getCurrentUser()); + } + + public NightDisplayListener(@NonNull Context context, @UserIdInt int userId) { + mContext = context.getApplicationContext(); + mUserId = userId; + mManager = mContext.getSystemService(ColorDisplayManager.class); + } + + /** + * Register a callback to be invoked whenever the Night display settings are changed. + */ + public void setCallback(Callback callback) { + final Callback oldCallback = mCallback; + if (oldCallback != callback) { + mCallback = callback; + + if (mContentObserver == null) { + mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + onSettingChanged(uri); + } + }; + } + + if (callback == null) { + // Stop listening for changes now that there IS NOT a callback. + mContext.getContentResolver().unregisterContentObserver(mContentObserver); + } else if (oldCallback == null) { + // Start listening for changes now that there IS a callback. + final ContentResolver cr = mContext.getContentResolver(); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_ACTIVATED), + false /* notifyForDescendants */, mContentObserver, mUserId); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_AUTO_MODE), + false /* notifyForDescendants */, mContentObserver, mUserId); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_START_TIME), + false /* notifyForDescendants */, mContentObserver, mUserId); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME), + false /* notifyForDescendants */, mContentObserver, mUserId); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE), + false /* notifyForDescendants */, mContentObserver, mUserId); + } + } + } + + private void onSettingChanged(Uri uri) { + final String setting = uri == null ? null : uri.getLastPathSegment(); + if (setting == null || mCallback == null) { + return; + } + + switch (setting) { + case Secure.NIGHT_DISPLAY_ACTIVATED: + mCallback.onActivated(mManager.isNightDisplayActivated()); + break; + case Secure.NIGHT_DISPLAY_AUTO_MODE: + mCallback.onAutoModeChanged(mManager.getNightDisplayAutoMode()); + break; + case Secure.NIGHT_DISPLAY_CUSTOM_START_TIME: + mCallback.onCustomStartTimeChanged(mManager.getNightDisplayCustomStartTime()); + break; + case Secure.NIGHT_DISPLAY_CUSTOM_END_TIME: + mCallback.onCustomEndTimeChanged(mManager.getNightDisplayCustomEndTime()); + break; + case Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE: + mCallback.onColorTemperatureChanged(mManager.getNightDisplayColorTemperature()); + break; + } + } + + /** + * Callback invoked whenever the Night display settings are changed. + */ + public interface Callback { + /** + * Callback invoked when the activated state changes. + * + * @param activated {@code true} if Night display is activated + */ + default void onActivated(boolean activated) {} + /** + * Callback invoked when the auto mode changes. + * + * @param autoMode the auto mode to use + */ + default void onAutoModeChanged(int autoMode) {} + /** + * Callback invoked when the time to automatically activate Night display changes. + * + * @param startTime the local time to automatically activate Night display + */ + default void onCustomStartTimeChanged(LocalTime startTime) {} + /** + * Callback invoked when the time to automatically deactivate Night display changes. + * + * @param endTime the local time to automatically deactivate Night display + */ + default void onCustomEndTimeChanged(LocalTime endTime) {} + + /** + * Callback invoked when the color temperature changes. + * + * @param colorTemperature the color temperature to tint the screen + */ + default void onColorTemperatureChanged(int colorTemperature) {} + } +} diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 8a141e2bfe6f..2aca55aacf7a 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3923,6 +3923,25 @@ public class ConnectivityManager { } /** + * Requests that the system open the captive portal app with the specified extras. + * + * <p>This endpoint is exclusively for use by the NetworkStack and is protected by the + * corresponding permission. + * @param appExtras Extras to include in the app start intent. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + public void startCaptivePortalApp(Bundle appExtras) { + try { + mService.startCaptivePortalAppInternal(appExtras); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Determine whether the device is configured to avoid bad wifi. * @hide */ diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 3a405d35e9aa..872671fa5697 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -27,6 +27,7 @@ import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; import android.net.NetworkState; import android.net.ProxyInfo; +import android.os.Bundle; import android.os.IBinder; import android.os.Messenger; import android.os.ParcelFileDescriptor; @@ -167,6 +168,7 @@ interface IConnectivityManager void setAcceptUnvalidated(in Network network, boolean accept, boolean always); void setAvoidUnvalidated(in Network network); void startCaptivePortalApp(in Network network); + void startCaptivePortalAppInternal(in Bundle appExtras); boolean getAvoidBadWifi(); int getMultipathPreference(in Network Network); diff --git a/core/java/android/os/BatterySaverPolicyConfig.java b/core/java/android/os/BatterySaverPolicyConfig.java index b6e2b69bbe3c..a107a7a2cfb8 100644 --- a/core/java/android/os/BatterySaverPolicyConfig.java +++ b/core/java/android/os/BatterySaverPolicyConfig.java @@ -47,10 +47,11 @@ public final class BatterySaverPolicyConfig implements Parcelable { private final boolean mEnableAdjustBrightness; private final boolean mEnableDataSaver; private final boolean mEnableFirewall; + private final boolean mEnableNightMode; private final boolean mEnableQuickDoze; private final boolean mForceAllAppsStandby; private final boolean mForceBackgroundCheck; - private final int mGpsMode; + private final int mLocationMode; private BatterySaverPolicyConfig(Builder in) { mAdjustBrightnessFactor = Math.max(0, Math.min(in.mAdjustBrightnessFactor, 1f)); @@ -67,11 +68,12 @@ public final class BatterySaverPolicyConfig implements Parcelable { mEnableAdjustBrightness = in.mEnableAdjustBrightness; mEnableDataSaver = in.mEnableDataSaver; mEnableFirewall = in.mEnableFirewall; + mEnableNightMode = in.mEnableNightMode; mEnableQuickDoze = in.mEnableQuickDoze; mForceAllAppsStandby = in.mForceAllAppsStandby; mForceBackgroundCheck = in.mForceBackgroundCheck; - mGpsMode = Math.max(PowerManager.MIN_LOCATION_MODE, - Math.min(in.mGpsMode, PowerManager.MAX_LOCATION_MODE)); + mLocationMode = Math.max(PowerManager.MIN_LOCATION_MODE, + Math.min(in.mLocationMode, PowerManager.MAX_LOCATION_MODE)); } private BatterySaverPolicyConfig(Parcel in) { @@ -101,10 +103,11 @@ public final class BatterySaverPolicyConfig implements Parcelable { mEnableAdjustBrightness = in.readBoolean(); mEnableDataSaver = in.readBoolean(); mEnableFirewall = in.readBoolean(); + mEnableNightMode = in.readBoolean(); mEnableQuickDoze = in.readBoolean(); mForceAllAppsStandby = in.readBoolean(); mForceBackgroundCheck = in.readBoolean(); - mGpsMode = Math.max(PowerManager.MIN_LOCATION_MODE, + mLocationMode = Math.max(PowerManager.MIN_LOCATION_MODE, Math.min(in.readInt(), PowerManager.MAX_LOCATION_MODE)); } @@ -150,10 +153,11 @@ public final class BatterySaverPolicyConfig implements Parcelable { dest.writeBoolean(mEnableAdjustBrightness); dest.writeBoolean(mEnableDataSaver); dest.writeBoolean(mEnableFirewall); + dest.writeBoolean(mEnableNightMode); dest.writeBoolean(mEnableQuickDoze); dest.writeBoolean(mForceAllAppsStandby); dest.writeBoolean(mForceBackgroundCheck); - dest.writeInt(mGpsMode); + dest.writeInt(mLocationMode); } @Override @@ -168,11 +172,12 @@ public final class BatterySaverPolicyConfig implements Parcelable { + "animation_disabled=" + mDisableAnimation + "," + "aod_disabled=" + mDisableAod + "," + "datasaver_disabled=" + !mEnableDataSaver + "," + + "enable_night_mode=" + mEnableNightMode + "," + "firewall_disabled=" + !mEnableFirewall + "," + "force_all_apps_standby=" + mForceAllAppsStandby + "," + "force_background_check=" + mForceBackgroundCheck + "," + "fullbackup_deferred=" + mDeferFullBackup + "," - + "gps_mode=" + mGpsMode + "," + + "gps_mode=" + mLocationMode + "," + "keyvaluebackup_deferred=" + mDeferKeyValueBackup + "," + "launch_boost_disabled=" + mDisableLaunchBoost + "," + "optional_sensors_disabled=" + mDisableOptionalSensors + "," @@ -260,6 +265,11 @@ public final class BatterySaverPolicyConfig implements Parcelable { return mEnableFirewall; } + /** Whether or not to enable night mode while in Battery Saver. */ + public boolean getEnableNightMode() { + return mEnableNightMode; + } + /** Whether or not to enable Quick Doze while in Battery Saver. */ public boolean getEnableQuickDoze() { return mEnableQuickDoze; @@ -275,9 +285,9 @@ public final class BatterySaverPolicyConfig implements Parcelable { return mForceBackgroundCheck; } - /** The GPS mode while in Battery Saver. */ - public int getGpsMode() { - return mGpsMode; + /** The location mode while in Battery Saver. */ + public int getLocationMode() { + return mLocationMode; } /** Builder class for constructing {@link BatterySaverPolicyConfig} objects. */ @@ -297,10 +307,11 @@ public final class BatterySaverPolicyConfig implements Parcelable { private boolean mEnableAdjustBrightness = false; private boolean mEnableDataSaver = false; private boolean mEnableFirewall = false; + private boolean mEnableNightMode = false; private boolean mEnableQuickDoze = false; private boolean mForceAllAppsStandby = false; private boolean mForceBackgroundCheck = false; - private int mGpsMode = PowerManager.LOCATION_MODE_NO_CHANGE; + private int mLocationMode = PowerManager.LOCATION_MODE_NO_CHANGE; public Builder() { } @@ -424,6 +435,13 @@ public final class BatterySaverPolicyConfig implements Parcelable { return this; } + /** Set whether or not to enable night mode while in Battery Saver. */ + @NonNull + public Builder setEnableNightMode(boolean enableNightMode) { + mEnableNightMode = enableNightMode; + return this; + } + /** Set whether or not to enable Quick Doze while in Battery Saver. */ @NonNull public Builder setEnableQuickDoze(boolean enableQuickDoze) { @@ -445,10 +463,10 @@ public final class BatterySaverPolicyConfig implements Parcelable { return this; } - /** Set the GPS mode while in Battery Saver. */ + /** Set the location mode while in Battery Saver. */ @NonNull - public Builder setGpsMode(@PowerManager.LocationPowerSaveMode int gpsMode) { - mGpsMode = gpsMode; + public Builder setLocationMode(@PowerManager.LocationPowerSaveMode int locationMode) { + mLocationMode = locationMode; return this; } diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 093897a3e476..bdef57518ac9 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -42,7 +42,7 @@ interface IPowerManager boolean isWakeLockLevelSupported(int level); void userActivity(long time, int event, int flags); - void wakeUp(long time, String reason, String opPackageName); + void wakeUp(long time, int reason, String details, String opPackageName); void goToSleep(long time, int reason, int flags); void nap(long time); boolean isInteractive(); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index be673ad14848..2ecf9d1159f0 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -435,6 +435,106 @@ public final class PowerManager { public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0; /** + * @hide + */ + @IntDef(prefix = { "WAKE_REASON_" }, value = { + WAKE_REASON_UNKNOWN, + WAKE_REASON_POWER_BUTTON, + WAKE_REASON_APPLICATION, + WAKE_REASON_PLUGGED_IN, + WAKE_REASON_GESTURE, + WAKE_REASON_CAMERA_LAUNCH, + WAKE_REASON_WAKE_KEY, + WAKE_REASON_WAKE_MOTION, + WAKE_REASON_HDMI, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WakeReason{} + + /** + * Wake up reason code: Waking for an unknown reason. + * @hide + */ + public static final int WAKE_REASON_UNKNOWN = 0; + + /** + * Wake up reason code: Waking up due to power button press. + * @hide + */ + public static final int WAKE_REASON_POWER_BUTTON = 1; + + /** + * Wake up reason code: Waking up because an application requested it. + * @hide + */ + public static final int WAKE_REASON_APPLICATION = 2; + + /** + * Wake up reason code: Waking up due to being plugged in or docked on a wireless charger. + * @hide + */ + public static final int WAKE_REASON_PLUGGED_IN = 3; + + /** + * Wake up reason code: Waking up due to a user performed gesture (e.g. douple tapping on the + * screen). + * @hide + */ + public static final int WAKE_REASON_GESTURE = 4; + + /** + * Wake up reason code: Waking up due to the camera being launched. + * @hide + */ + public static final int WAKE_REASON_CAMERA_LAUNCH = 5; + + /** + * Wake up reason code: Waking up because a wake key other than power was pressed. + * @hide + */ + public static final int WAKE_REASON_WAKE_KEY = 6; + + /** + * Wake up reason code: Waking up because a wake motion was performed. + * + * For example, a trackball that was set to wake the device up was spun. + * @hide + */ + public static final int WAKE_REASON_WAKE_MOTION = 7; + + /** + * Wake up reason code: Waking due to HDMI. + * @hide + */ + public static final int WAKE_REASON_HDMI = 8; + + /** + * Wake up reason code: Waking due to the lid being opened. + * @hide + */ + public static final int WAKE_REASON_LID = 9; + + /** + * Convert the wake reason to a string for debugging purposes. + * @hide + */ + public static String wakeReasonToString(@WakeReason int wakeReason) { + switch (wakeReason) { + case WAKE_REASON_UNKNOWN: return "WAKE_REASON_UNKNOWN"; + case WAKE_REASON_POWER_BUTTON: return "WAKE_REASON_POWER_BUTTON"; + case WAKE_REASON_APPLICATION: return "WAKE_REASON_APPLICATION"; + case WAKE_REASON_PLUGGED_IN: return "WAKE_REASON_PLUGGED_IN"; + case WAKE_REASON_GESTURE: return "WAKE_REASON_GESTURE"; + case WAKE_REASON_CAMERA_LAUNCH: return "WAKE_REASON_CAMERA_LAUNCH"; + case WAKE_REASON_WAKE_KEY: return "WAKE_REASON_WAKE_KEY"; + case WAKE_REASON_WAKE_MOTION: return "WAKE_REASON_WAKE_MOTION"; + case WAKE_REASON_HDMI: return "WAKE_REASON_HDMI"; + case WAKE_REASON_LID: return "WAKE_REASON_LID"; + default: return Integer.toString(wakeReason); + } + } + + /** * The value to pass as the 'reason' argument to reboot() to reboot into * recovery mode for tasks other than applying system updates, such as * doing factory resets. @@ -975,22 +1075,68 @@ public final class PowerManager { * @see #userActivity * @see #goToSleep * + * @deprecated Use {@link #wakeUp(long, int, String)} instead. * @removed Requires signature permission. */ + @Deprecated public void wakeUp(long time) { - try { - mService.wakeUp(time, "wakeUp", mContext.getOpPackageName()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + wakeUp(time, WAKE_REASON_UNKNOWN, "wakeUp"); } /** + * Forces the device to wake up from sleep. + * <p> + * If the device is currently asleep, wakes it up, otherwise does nothing. + * This is what happens when the power key is pressed to turn on the screen. + * </p><p> + * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. + * </p> + * + * @param time The time when the request to wake up was issued, in the + * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly + * order the wake up request with other power management functions. It should be set + * to the timestamp of the input event that caused the request to wake up. + * + * @param details A free form string to explain the specific details behind the wake up for + * debugging purposes. + * + * @see #userActivity + * @see #goToSleep + * + * @deprecated Use {@link #wakeUp(long, int, String)} instead. + * @hide + */ + @Deprecated + public void wakeUp(long time, String details) { + wakeUp(time, WAKE_REASON_UNKNOWN, details); + } + + /** + * Forces the device to wake up from sleep. + * <p> + * If the device is currently asleep, wakes it up, otherwise does nothing. + * This is what happens when the power key is pressed to turn on the screen. + * </p><p> + * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. + * </p> + * + * @param time The time when the request to wake up was issued, in the + * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly + * order the wake up request with other power management functions. It should be set + * to the timestamp of the input event that caused the request to wake up. + * + * @param reason The reason for the wake up. + * + * @param details A free form string to explain the specific details behind the wake up for + * debugging purposes. + * + * @see #userActivity + * @see #goToSleep * @hide */ - public void wakeUp(long time, String reason) { + public void wakeUp(long time, @WakeReason int reason, String details) { try { - mService.wakeUp(time, reason, mContext.getOpPackageName()); + mService.wakeUp(time, reason, details, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a8976aa56241..e95d60465371 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9300,6 +9300,13 @@ public final class Settings { public static final String DEBUG_VIEW_ATTRIBUTES = "debug_view_attributes"; /** + * Which application package is allowed to save View attribute data. + * @hide + */ + public static final String DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE = + "debug_view_attributes_application_package"; + + /** * Whether assisted GPS should be enabled or not. * @hide */ @@ -14022,6 +14029,7 @@ public final class Settings { INSTANT_APP_SETTINGS.add(TRANSITION_ANIMATION_SCALE); INSTANT_APP_SETTINGS.add(ANIMATOR_DURATION_SCALE); INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES); + INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE); INSTANT_APP_SETTINGS.add(WTF_IS_FATAL); INSTANT_APP_SETTINGS.add(SEND_ACTION_APP_ERROR); INSTANT_APP_SETTINGS.add(ZEN_MODE); diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java index eeb340b67e68..efb8923a459f 100644 --- a/core/java/android/service/dreams/Sandman.java +++ b/core/java/android/service/dreams/Sandman.java @@ -91,8 +91,9 @@ public final class Sandman { // and the UI mode manager starting a dream. We want the system to already // be awake by the time this happens. Otherwise the dream may not start. PowerManager powerManager = - (PowerManager)context.getSystemService(Context.POWER_SERVICE); + context.getSystemService(PowerManager.class); powerManager.wakeUp(SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_PLUGGED_IN, "android.service.dreams:DREAM"); } else { Slog.i(TAG, "Activating dream by user request."); diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 949328fd3a99..915a18e59226 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -94,7 +94,8 @@ public class TextLine { private final DecorationInfo mDecorationInfo = new DecorationInfo(); private final ArrayList<DecorationInfo> mDecorations = new ArrayList<>(); - @UnsupportedAppUsage + /** Not allowed to access. If it's for memory leak workaround, it was already fixed M. */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static final TextLine[] sCached = new TextLine[3]; /** diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index 59e562fe8071..62ed901c5e06 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -40,6 +40,7 @@ import android.util.Slog; import android.view.View.AttachInfo; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeIdManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeProvider; @@ -154,13 +155,7 @@ public final class AccessibilityInteractionController { } private boolean isShown(View view) { - // The first two checks are made also made by isShown() which - // however traverses the tree up to the parent to catch that. - // Therefore, we do some fail fast check to minimize the up - // tree traversal. - return (view.mAttachInfo != null - && view.mAttachInfo.mWindowVisibility == View.VISIBLE - && view.isShown()); + return (view != null) && (view.getWindowVisibility() == View.VISIBLE && view.isShown()); } public void findAccessibilityNodeInfoByAccessibilityIdClientThread( @@ -340,13 +335,8 @@ public final class AccessibilityInteractionController { return; } mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; - View root = null; - if (accessibilityViewId == AccessibilityNodeInfo.ROOT_ITEM_ID) { - root = mViewRootImpl.mView; - } else { - root = findViewByAccessibilityId(accessibilityViewId); - } - if (root != null && isShown(root)) { + final View root = findViewByAccessibilityId(accessibilityViewId); + if (root != null) { mPrefetcher.prefetchAccessibilityNodeInfos( root, virtualDescendantId, flags, infos, arguments); } @@ -396,12 +386,7 @@ public final class AccessibilityInteractionController { return; } mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; - View root = null; - if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) { - root = findViewByAccessibilityId(accessibilityViewId); - } else { - root = mViewRootImpl.mView; - } + final View root = findViewByAccessibilityId(accessibilityViewId); if (root != null) { final int resolvedViewId = root.getContext().getResources() .getIdentifier(viewId, null, null); @@ -462,13 +447,8 @@ public final class AccessibilityInteractionController { return; } mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; - View root = null; - if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) { - root = findViewByAccessibilityId(accessibilityViewId); - } else { - root = mViewRootImpl.mView; - } - if (root != null && isShown(root)) { + final View root = findViewByAccessibilityId(accessibilityViewId); + if (root != null) { AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider(); if (provider != null) { infos = provider.findAccessibilityNodeInfosByText(text, @@ -550,13 +530,8 @@ public final class AccessibilityInteractionController { return; } mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; - View root = null; - if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) { - root = findViewByAccessibilityId(accessibilityViewId); - } else { - root = mViewRootImpl.mView; - } - if (root != null && isShown(root)) { + final View root = findViewByAccessibilityId(accessibilityViewId); + if (root != null) { switch (focusType) { case AccessibilityNodeInfo.FOCUS_ACCESSIBILITY: { View host = mViewRootImpl.mAccessibilityFocusedHost; @@ -583,7 +558,7 @@ public final class AccessibilityInteractionController { } break; case AccessibilityNodeInfo.FOCUS_INPUT: { View target = root.findFocus(); - if (target == null || !isShown(target)) { + if (!isShown(target)) { break; } AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider(); @@ -645,13 +620,8 @@ public final class AccessibilityInteractionController { return; } mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; - View root = null; - if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) { - root = findViewByAccessibilityId(accessibilityViewId); - } else { - root = mViewRootImpl.mView; - } - if (root != null && isShown(root)) { + final View root = findViewByAccessibilityId(accessibilityViewId); + if (root != null) { View nextView = root.focusSearch(direction); if (nextView != null) { next = nextView.createAccessibilityNodeInfo(); @@ -705,13 +675,8 @@ public final class AccessibilityInteractionController { return; } mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; - View target = null; - if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) { - target = findViewByAccessibilityId(accessibilityViewId); - } else { - target = mViewRootImpl.mView; - } - if (target != null && isShown(target)) { + final View target = findViewByAccessibilityId(accessibilityViewId); + if (target != null) { if (action == R.id.accessibilityActionClickOnClickableSpan) { // Handle this hidden action separately succeeded = handleClickableSpanActionUiThread( @@ -791,15 +756,13 @@ public final class AccessibilityInteractionController { } private View findViewByAccessibilityId(int accessibilityId) { - View root = mViewRootImpl.mView; - if (root == null) { - return null; - } - View foundView = root.findViewByAccessibilityId(accessibilityId); - if (foundView != null && !isShown(foundView)) { - return null; + if (accessibilityId == AccessibilityNodeInfo.ROOT_ITEM_ID) { + return mViewRootImpl.mView; + } else { + final View foundView = + AccessibilityNodeIdManager.getInstance().findView(accessibilityId); + return isShown(foundView) ? foundView : null; } - return foundView; } private void applyAppScaleAndMagnificationSpecIfNeeded(List<AccessibilityNodeInfo> infos, @@ -1171,7 +1134,7 @@ public final class AccessibilityInteractionController { } View child = children.get(i); if (child.getAccessibilityViewId() != current.getAccessibilityViewId() - && isShown(child)) { + && isShown(child)) { AccessibilityNodeInfo info = null; AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider(); diff --git a/core/java/android/view/RemotableViewMethod.java b/core/java/android/view/RemotableViewMethod.java index 03aed9a53925..5eff848e85aa 100644 --- a/core/java/android/view/RemotableViewMethod.java +++ b/core/java/android/view/RemotableViewMethod.java @@ -16,6 +16,8 @@ package android.view; +import android.annotation.TestApi; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -26,6 +28,7 @@ import java.lang.annotation.Target; * This annotation indicates that a method on a subclass of View * is alllowed to be used with the {@link android.widget.RemoteViews} mechanism. */ +@TestApi @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface RemotableViewMethod { diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index c0a4028c0301..8028715219cc 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -852,12 +852,11 @@ public final class SurfaceControl implements Parcelable { } /** - * Free all server-side state associated with this surface and - * release this object's reference. This method can only be - * called from the process that created the service. + * Release the local resources like {@link #release} but also + * remove the Surface from the screen. * @hide */ - public void destroy() { + public void remove() { if (mNativeObject != 0) { nativeDestroy(mNativeObject); mNativeObject = 0; @@ -2467,5 +2466,23 @@ public final class SurfaceControl implements Parcelable { nativeMergeTransaction(mNativeObject, other.mNativeObject); return this; } + + /** + * Equivalent to reparent with a null parent, in that it removes + * the SurfaceControl from the scene, but it also releases + * the local resources (by calling {@link SurfaceControl#release}) + * after this method returns, {@link SurfaceControl#isValid} will return + * false for the argument. + * + * @param sc The surface to remove and release. + * @return This transaction + * @hide + */ + @NonNull + public Transaction remove(@NonNull SurfaceControl sc) { + reparent(sc, null); + sc.release(); + return this; + } } } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index cd5207c50d1d..9f0800f11721 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -334,7 +334,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb updateSurface(); if (mSurfaceControl != null) { - mSurfaceControl.destroy(); + mSurfaceControl.remove(); } mSurfaceControl = null; @@ -502,11 +502,11 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb private void releaseSurfaces() { if (mSurfaceControl != null) { - mSurfaceControl.destroy(); + mSurfaceControl.remove(); mSurfaceControl = null; } if (mBackgroundControl != null) { - mBackgroundControl.destroy(); + mBackgroundControl.remove(); mBackgroundControl = null; } } @@ -816,7 +816,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb } if (mDeferredDestroySurfaceControl != null) { - mDeferredDestroySurfaceControl.destroy(); + mDeferredDestroySurfaceControl.remove(); mDeferredDestroySurfaceControl = null; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 04ffa33d0e22..c641552d8d72 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -35,6 +35,7 @@ import android.annotation.LayoutRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; +import android.annotation.StyleRes; import android.annotation.TestApi; import android.annotation.UiThread; import android.annotation.UnsupportedAppUsage; @@ -91,6 +92,7 @@ import android.util.LongSparseLongArray; import android.util.Pools.SynchronizedPool; import android.util.Property; import android.util.SparseArray; +import android.util.SparseIntArray; import android.util.StateSet; import android.util.SuperNotCalledException; import android.util.TypedValue; @@ -103,6 +105,7 @@ import android.view.WindowInsetsAnimationListener.InsetsAnimation; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEventSource; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeIdManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeProvider; @@ -820,7 +823,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @hide */ - public static boolean mDebugViewAttributes = false; + public static boolean sDebugViewAttributes = false; + + /** + * When set to this application package view will save its attribute data. + * + * @hide + */ + public static String sDebugViewAttributesApplicationPackage; /** * Used to mark a View that has no ID. @@ -5078,6 +5088,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @LayoutRes private int mSourceLayoutId = ID_NULL; + @Nullable + private SparseIntArray mAttributeSourceResId; + + @Nullable + private int[] mAttributeResolutionStack; + + @StyleRes + private int mExplicitStyle; + /** * Cached reference to the {@link ContentCaptureSession}, is reset on {@link #invalidate()}. */ @@ -5253,7 +5272,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); - if (mDebugViewAttributes) { + retrieveExplicitStyle(context.getTheme(), attrs); + saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a, + defStyleAttr, defStyleRes); + + if (sDebugViewAttributes) { saveAttributeData(attrs, a); } @@ -5915,6 +5938,84 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Returns the ordered list of resource ID that are considered when resolving attribute values + * for this {@link View}. The list will include layout resource ID if the View is inflated from + * XML. It will also include a set of explicit styles if specified in XML using + * {@code style="..."}. Finally, it will include the default styles resolved from the theme. + * + * <p> + * <b>Note:</b> this method will only return actual values if the view attribute debugging + * is enabled in Android developer options. + * + * @return ordered list of resource ID that are considered when resolving attribute values for + * this {@link View}. + */ + @NonNull + public List<Integer> getAttributeResolutionStack() { + ArrayList<Integer> stack = new ArrayList<>(); + if (!sDebugViewAttributes) { + return stack; + } + if (mSourceLayoutId != ID_NULL) { + stack.add(mSourceLayoutId); + } + for (int i = 0; i < mAttributeResolutionStack.length; i++) { + stack.add(mAttributeResolutionStack[i]); + } + return stack; + } + + /** + * Returns the mapping of attribute resource ID to source resource ID where the attribute value + * was set. Source resource ID can either be a layout resource ID, if the value was set in XML + * within the View tag, or a style resource ID, if the attribute was set in a style. The source + * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}. + * + * <p> + * <b>Note:</b> this method will only return actual values if the view attribute debugging + * is enabled in Android developer options. + * + * @return mapping of attribute resource ID to source resource ID where the attribute value + * was set. + */ + @NonNull + public Map<Integer, Integer> getAttributeSourceResourceMap() { + HashMap<Integer, Integer> map = new HashMap<>(); + if (!sDebugViewAttributes) { + return map; + } + for (int i = 0; i < mAttributeSourceResId.size(); i++) { + map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i)); + } + return map; + } + + /** + * Returns the resource ID for the style specified using {@code style="..."} in the + * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not + * specified or otherwise not applicable. + * <p> + * Each {@link View} can have an explicit style specified in the layout file. + * This style is used first during the {@link View} attribute resolution, then if an attribute + * is not defined there the resource system looks at default style and theme as fallbacks. + * + * <p> + * <b>Note:</b> this method will only return actual values if the view attribute debugging + * is enabled in Android developer options. + * + * @return The resource ID for the style specified using {@code style="..."} in the + * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise + * if not specified or otherwise not applicable. + */ + @StyleRes + public int getExplicitStyle() { + if (!sDebugViewAttributes) { + return ID_NULL; + } + return mExplicitStyle; + } + + /** * An implementation of OnClickListener that attempts to lazily load a * named click handling method from a parent or ancestor context. */ @@ -6000,6 +6101,46 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mAttributeMap; } + private void retrieveExplicitStyle(@NonNull Resources.Theme theme, + @Nullable AttributeSet attrs) { + if (!sDebugViewAttributes) { + return; + } + mExplicitStyle = theme.getExplicitStyle(attrs); + } + + /** + * Stores debugging information about attributes. This should be called in a constructor by + * every custom {@link View} that uses a custom styleable. + * @param context Context under which this view is created. + * @param styleable A reference to styleable array R.styleable.Foo + * @param attrs AttributeSet used to construct this view. + * @param t Resolved {@link TypedArray} returned by a call to + * {@link Resources#obtainAttributes(AttributeSet, int[])}. + * @param defStyleAttr Default style attribute passed into the view constructor. + * @param defStyleRes Default style resource passed into the view constructor. + */ + public final void saveAttributeDataForStyleable(@NonNull Context context, + @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t, + int defStyleAttr, int defStyleRes) { + if (!sDebugViewAttributes) { + return; + } + + mAttributeResolutionStack = context.getTheme().getAttributeResolutionStack( + defStyleAttr, defStyleRes, mExplicitStyle); + + if (mAttributeSourceResId == null) { + mAttributeSourceResId = new SparseIntArray(); + } + + final int indexCount = t.getIndexCount(); + for (int j = 0; j < indexCount; ++j) { + final int index = t.getIndex(j); + mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0)); + } + } + private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) { final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount(); final int indexCount = t.getIndexCount(); @@ -19041,6 +19182,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, jumpDrawablesToCurrentState(); + AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId()); resetSubtreeAccessibilityStateChanged(); // rebuild, since Outline not maintained while View is detached @@ -19433,6 +19575,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if ((mViewFlags & TOOLTIP) == TOOLTIP) { hideTooltip(); } + + AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId()); } private void cleanupDraw() { @@ -23947,24 +24091,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Finds a view by its unuque and stable accessibility id. - * - * @param accessibilityId The searched accessibility id. - * @return The found view. - */ - @UnsupportedAppUsage - final <T extends View> T findViewByAccessibilityId(int accessibilityId) { - if (accessibilityId < 0) { - return null; - } - T view = findViewByAccessibilityIdTraversal(accessibilityId); - if (view != null) { - return view.includeForAccessibility() ? view : null; - } - return null; - } - - /** * Performs the traversal to find a view by its unique and stable accessibility id. * * <strong>Note:</strong>This method does not stop at the root namespace diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 47528a05f5a2..156972f6ecbb 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -95,6 +95,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener; import android.view.accessibility.AccessibilityManager.HighTextContrastChangeListener; +import android.view.accessibility.AccessibilityNodeIdManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeProvider; @@ -1602,7 +1603,7 @@ public final class ViewRootImpl implements ViewParent, mSurfaceSession = null; if (mBoundsSurfaceControl != null) { - mBoundsSurfaceControl.destroy(); + mBoundsSurfaceControl.remove(); mBoundsSurface.release(); mBoundsSurfaceControl = null; } @@ -7954,17 +7955,14 @@ public final class ViewRootImpl implements ViewParent, // Intercept accessibility focus events fired by virtual nodes to keep // track of accessibility focus position in such nodes. final int eventType = event.getEventType(); + final View source = getSourceForAccessibilityEvent(event); switch (eventType) { case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: { - final long sourceNodeId = event.getSourceNodeId(); - final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId( - sourceNodeId); - View source = mView.findViewByAccessibilityId(accessibilityViewId); if (source != null) { AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider(); if (provider != null) { final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId( - sourceNodeId); + event.getSourceNodeId()); final AccessibilityNodeInfo node; node = provider.createAccessibilityNodeInfo(virtualNodeId); setAccessibilityFocus(source, node); @@ -7972,15 +7970,8 @@ public final class ViewRootImpl implements ViewParent, } } break; case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: { - final long sourceNodeId = event.getSourceNodeId(); - final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId( - sourceNodeId); - View source = mView.findViewByAccessibilityId(accessibilityViewId); - if (source != null) { - AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider(); - if (provider != null) { - setAccessibilityFocus(null, null); - } + if (source != null && source.getAccessibilityNodeProvider() != null) { + setAccessibilityFocus(null, null); } } break; @@ -7993,6 +7984,13 @@ public final class ViewRootImpl implements ViewParent, return true; } + private View getSourceForAccessibilityEvent(AccessibilityEvent event) { + final long sourceNodeId = event.getSourceNodeId(); + final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId( + sourceNodeId); + return AccessibilityNodeIdManager.getInstance().findView(accessibilityViewId); + } + /** * Updates the focused virtual view, when necessary, in response to a * content changed event. diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java index 16bafe2c4f11..35ed7bfa2ce6 100644 --- a/core/java/android/view/WindowManagerPolicyConstants.java +++ b/core/java/android/view/WindowManagerPolicyConstants.java @@ -16,6 +16,11 @@ package android.view; +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Constants for interfacing with WindowManagerService and WindowManagerPolicyInternal. * @hide @@ -89,6 +94,35 @@ public interface WindowManagerPolicyConstants { /** Screen turned off because of timeout */ int OFF_BECAUSE_OF_TIMEOUT = 3; + @IntDef(prefix = { "ON_BECAUSE_OF_" }, value = { + ON_BECAUSE_OF_USER, + ON_BECAUSE_OF_APPLICATION, + ON_BECAUSE_OF_UNKNOWN, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface OnReason{} + + /** Convert the on reason to a human readable format */ + static String onReasonToString(@OnReason int why) { + switch (why) { + case ON_BECAUSE_OF_USER: + return "ON_BECAUSE_OF_USER"; + case ON_BECAUSE_OF_APPLICATION: + return "ON_BECAUSE_OF_APPLICATION"; + case ON_BECAUSE_OF_UNKNOWN: + return "ON_BECAUSE_OF_UNKNOWN"; + default: + return Integer.toString(why); + } + } + + /** Screen turned on because of a user-initiated action. */ + int ON_BECAUSE_OF_USER = 1; + /** Screen turned on because of an application request or event */ + int ON_BECAUSE_OF_APPLICATION = 2; + /** Screen turned on for an unknown reason */ + int ON_BECAUSE_OF_UNKNOWN = 3; + int APPLICATION_LAYER = 2; int APPLICATION_MEDIA_SUBLAYER = -2; int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 6aafa348e3f5..06207a9290d7 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -36,6 +36,7 @@ import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.res.Resources; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -183,7 +184,7 @@ public final class AccessibilityManager { boolean mIsTouchExplorationEnabled; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768939) boolean mIsHighTextContrastEnabled; AccessibilityPolicy mAccessibilityPolicy; diff --git a/core/java/android/view/accessibility/AccessibilityNodeIdManager.java b/core/java/android/view/accessibility/AccessibilityNodeIdManager.java new file mode 100644 index 000000000000..1ac704774e7f --- /dev/null +++ b/core/java/android/view/accessibility/AccessibilityNodeIdManager.java @@ -0,0 +1,68 @@ +/* + * 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.accessibility; + +import android.util.SparseArray; +import android.view.View; + +/** @hide */ +public final class AccessibilityNodeIdManager { + private SparseArray<View> mIdsToViews = new SparseArray<>(); + private static AccessibilityNodeIdManager sIdManager; + + /** + * Gets singleton. + * @return The instance. + */ + public static synchronized AccessibilityNodeIdManager getInstance() { + if (sIdManager == null) { + sIdManager = new AccessibilityNodeIdManager(); + } + return sIdManager; + } + + private AccessibilityNodeIdManager() { + } + + /** + * Register view to be kept track of by the accessibility system. + * Must be paired with unregisterView, otherwise this will leak. + * @param view The view to be registered. + * @param id The accessibilityViewId of the view. + */ + public void registerViewWithId(View view, int id) { + mIdsToViews.append(id, view); + } + + /** + * Unregister view, accessibility won't keep track of this view after this call. + * @param id The id returned from registerView when the view as first associated. + */ + public void unregisterViewWithId(int id) { + mIdsToViews.remove(id); + } + + /** + * Accessibility uses this to find the view in the hierarchy. + * @param id The accessibility view id. + * @return The view. + */ + public View findView(int id) { + final View view = mIdsToViews.get(id); + return view != null && view.includeForAccessibility() ? view : null; + } +} diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java index f1c7b695ce05..5608bb372701 100644 --- a/core/java/android/view/autofill/AutofillId.java +++ b/core/java/android/view/autofill/AutofillId.java @@ -52,11 +52,13 @@ public final class AutofillId implements Parcelable { } /** @hide */ + @TestApi public AutofillId(int parentId, int virtualChildId) { this(FLAG_IS_VIRTUAL_INT, parentId, virtualChildId, NO_SESSION); } /** @hide */ + @TestApi public AutofillId(@NonNull AutofillId parent, long virtualChildId, int sessionId) { this(FLAG_IS_VIRTUAL_LONG | FLAG_HAS_SESSION, parent.mViewId, virtualChildId, sessionId); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 1c96b87394b6..83fc017373a6 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -346,9 +346,6 @@ public final class AutofillManager { @TestApi public static final int FLAG_SMART_SUGGESTION_SYSTEM = 0x1; - /** @hide */ // TODO(b/123233342): remove when not used anymore - public static final int FLAG_SMART_SUGGESTION_LEGACY = 0x2; - /** @hide */ @IntDef(flag = true, prefix = { "FLAG_SMART_SUGGESTION_" }, value = { FLAG_SMART_SUGGESTION_SYSTEM diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java index dfac35ddf58b..22254cd94059 100644 --- a/core/java/android/view/contentcapture/ContentCaptureEvent.java +++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java @@ -138,8 +138,11 @@ public final class ContentCaptureEvent implements Parcelable { /** * Adds an autofill id to the this event, merging the single id into a list if necessary. - * @hide */ + * + * @hide + */ public ContentCaptureEvent addAutofillId(@NonNull AutofillId id) { + Preconditions.checkNotNull(id); if (mIds == null) { mIds = new ArrayList<>(); if (mId == null) { diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java index eef841da3bc5..8d6245458d62 100644 --- a/core/java/android/view/contentcapture/ViewNode.java +++ b/core/java/android/view/contentcapture/ViewNode.java @@ -34,7 +34,6 @@ import android.view.ViewStructure.HtmlInfo.Builder; import android.view.autofill.AutofillId; import android.view.autofill.AutofillValue; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; //TODO(b/122484602): add javadocs / implement Parcelable / implement @@ -589,6 +588,7 @@ public final class ViewNode extends AssistStructure.ViewNode { } /** @hide */ + @TestApi public static void writeToParcel(@NonNull Parcel parcel, @Nullable ViewNode node, int flags) { if (node == null) { parcel.writeLong(0); @@ -598,18 +598,20 @@ public final class ViewNode extends AssistStructure.ViewNode { } /** @hide */ + @TestApi public static @Nullable ViewNode readFromParcel(@NonNull Parcel parcel) { final long nodeFlags = parcel.readLong(); - return nodeFlags == 0 ? new ViewNode() : new ViewNode(nodeFlags, parcel); + return nodeFlags == 0 ? null : new ViewNode(nodeFlags, parcel); } /** @hide */ - @VisibleForTesting // Must be public to be accessed from FrameworkCoreTests' apk. + @TestApi public static final class ViewStructureImpl extends ViewStructure { final ViewNode mNode = new ViewNode(); - @VisibleForTesting // Must be public to be accessed from FrameworkCoreTests' apk. + /** @hide */ + @TestApi public ViewStructureImpl(@NonNull View view) { mNode.mAutofillId = Preconditions.checkNotNull(view).getAutofillId(); final ViewParent parent = view.getParent(); @@ -618,13 +620,15 @@ public final class ViewNode extends AssistStructure.ViewNode { } } - @VisibleForTesting // Must be public to be accessed from FrameworkCoreTests' apk. + /** @hide */ + @TestApi public ViewStructureImpl(@NonNull AutofillId parentId, long virtualId, int sessionId) { mNode.mParentAutofillId = Preconditions.checkNotNull(parentId); mNode.mAutofillId = new AutofillId(parentId, virtualId, sessionId); } - @VisibleForTesting // Must be public to be accessed from FrameworkCoreTests' apk. + /** @hide */ + @TestApi public ViewNode getNode() { return mNode; } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index aee4b1f63812..8a097883dd5c 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -339,7 +339,11 @@ public final class InputMethodManager { // For scheduling work on the main thread. This also serves as our // global lock. - @UnsupportedAppUsage + // Remark on @UnsupportedAppUsage: there were context leaks on old versions + // of android (b/37043700), so developers used this field to perform manual clean up. + // Leaks were fixed, hacks were backported to AppCompatActivity, + // so an access to the field is closed. + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) final H mH; // Our generic input connection if the current target does not have its own. @@ -375,13 +379,15 @@ public final class InputMethodManager { * This is the view that should currently be served by an input method, * regardless of the state of setting that up. */ - @UnsupportedAppUsage + // See comment to mH field in regard to @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) View mServedView; /** * This is then next view that will be served by the input method, when * we get around to updating things. */ - @UnsupportedAppUsage + // See comment to mH field in regard to @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) View mNextServedView; /** * This is set when we are in the process of connecting, to determine diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index cc45f38b0ea3..542df4562908 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -442,8 +442,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te /** * Handles one frame of a fling + * + * To interrupt a fling early you should use smoothScrollBy(0,0) instead */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private FlingRunnable mFlingRunnable; /** @@ -1611,15 +1613,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te return false; } - /** @hide */ - @Override - public View findViewByAccessibilityIdTraversal(int accessibilityId) { - if (accessibilityId == getAccessibilityViewId()) { - return this; - } - return super.findViewByAccessibilityIdTraversal(accessibilityId); - } - /** * Indicates whether the children's drawing cache is used during a scroll. * By default, the drawing cache is enabled but this will consume more memory. @@ -4688,7 +4681,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mScroller = new OverScroller(getContext()); } - @UnsupportedAppUsage + // Use AbsListView#fling(int) instead + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) void start(int initialVelocity) { int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0; mLastFlingY = initialY; @@ -4766,7 +4760,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te postOnAnimation(this); } - @UnsupportedAppUsage + // To interrupt a fling early you should use smoothScrollBy(0,0) instead + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) void endFling() { mTouchMode = TOUCH_MODE_REST; diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index d5b1a3d69dfe..249f49956256 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -1013,7 +1013,7 @@ public final class Magnifier { } synchronized (mLock) { mRenderer.destroy(); - mSurfaceControl.destroy(); + mSurfaceControl.remove(); mSurfaceSession.kill(); mHandler.removeCallbacks(mMagnifierUpdater); if (mBitmap != null) { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 659b71f51588..d87600125a54 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -712,7 +712,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @UnsupportedAppUsage private ChangeWatcher mChangeWatcher; - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug = 123769451) private ArrayList<TextWatcher> mListeners; // display attributes @@ -1055,6 +1055,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int inputType = EditorInfo.TYPE_NULL; a = theme.obtainStyledAttributes( attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes); + saveAttributeDataForStyleable(context, com.android.internal.R.styleable.TextView, attrs, a, + defStyleAttr, defStyleRes); int firstBaselineToTopHeight = -1; int lastBaselineToBottomHeight = -1; int lineHeight = -1; diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 9ba56b8c0f4e..4ac7f5012613 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -334,9 +334,14 @@ class ZygoteConnection { } } - private class HiddenApiUsageLogger implements VMRuntime.HiddenApiUsageLogger { + private static class HiddenApiUsageLogger implements VMRuntime.HiddenApiUsageLogger { private final MetricsLogger mMetricsLogger = new MetricsLogger(); + private static HiddenApiUsageLogger sInstance = new HiddenApiUsageLogger(); + + public static HiddenApiUsageLogger getInstance() { + return HiddenApiUsageLogger.sInstance; + } public void hiddenApiUsed(String packageName, String signature, int accessMethod, boolean accessDenied) { @@ -370,7 +375,7 @@ class ZygoteConnection { private void handleHiddenApiAccessLogSampleRate(int samplingRate) { try { ZygoteInit.setHiddenApiAccessLogSampleRate(samplingRate); - ZygoteInit.setHiddenApiUsageLogger(new HiddenApiUsageLogger()); + ZygoteInit.setHiddenApiUsageLogger(HiddenApiUsageLogger.getInstance()); mSocketOutStream.writeInt(0); } catch (IOException ioe) { throw new IllegalStateException("Error writing to command socket", ioe); diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 4101c04162af..d493ddfaae13 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -1105,6 +1105,46 @@ static jobjectArray NativeGetSizeConfigurations(JNIEnv* env, jclass /*clazz*/, j return array; } +static jintArray NativeAttributeResolutionStack( + JNIEnv* env, jclass /*clazz*/, jlong ptr, + jlong theme_ptr, jint xml_style_res, + jint def_style_attr, jint def_style_resid) { + + ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + Theme* theme = reinterpret_cast<Theme*>(theme_ptr); + CHECK(theme->GetAssetManager() == &(*assetmanager)); + (void) assetmanager; + + // Load default style from attribute, if specified... + uint32_t def_style_flags = 0u; + if (def_style_attr != 0) { + Res_value value; + if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) { + if (value.dataType == Res_value::TYPE_REFERENCE) { + def_style_resid = value.data; + } + } + } + + auto style_stack = assetmanager->GetBagResIdStack(xml_style_res); + auto def_style_stack = assetmanager->GetBagResIdStack(def_style_resid); + + jintArray array = env->NewIntArray(style_stack.size() + def_style_stack.size()); + if (env->ExceptionCheck()) { + return nullptr; + } + + for (uint32_t i = 0; i < style_stack.size(); i++) { + jint attr_resid = style_stack[i]; + env->SetIntArrayRegion(array, i, 1, &attr_resid); + } + for (uint32_t i = 0; i < def_style_stack.size(); i++) { + jint attr_resid = def_style_stack[i]; + env->SetIntArrayRegion(array, style_stack.size() + i, 1, &attr_resid); + } + return array; +} + static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr, jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) { @@ -1456,6 +1496,7 @@ static const JNINativeMethod gAssetManagerMethods[] = { (void*)NativeGetSizeConfigurations}, // Style attribute related methods. + {"nativeAttributeResolutionStack", "(JJIII)[I", (void*)NativeAttributeResolutionStack}, {"nativeApplyStyle", "(JJIIJ[IJJ)V", (void*)NativeApplyStyle}, {"nativeResolveAttrs", "(JJII[I[I[I[I)Z", (void*)NativeResolveAttrs}, {"nativeRetrieveAttributes", "(JJ[I[I[I)Z", (void*)NativeRetrieveAttributes}, diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 67a56ae2b52d..464f24901eb1 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -58,6 +58,8 @@ namespace android { +using ui::Dataspace; + static const char* const OutOfResourcesException = "android/view/Surface$OutOfResourcesException"; @@ -132,6 +134,7 @@ int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) { case PublicFormat::JPEG: case PublicFormat::DEPTH_POINT_CLOUD: case PublicFormat::DEPTH_JPEG: + case PublicFormat::HEIC: return HAL_PIXEL_FORMAT_BLOB; case PublicFormat::DEPTH16: return HAL_PIXEL_FORMAT_Y16; @@ -146,32 +149,44 @@ int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) { android_dataspace android_view_Surface_mapPublicFormatToHalDataspace( PublicFormat f) { + Dataspace dataspace; switch(f) { case PublicFormat::JPEG: - return HAL_DATASPACE_V0_JFIF; + dataspace = Dataspace::V0_JFIF; + break; case PublicFormat::DEPTH_POINT_CLOUD: case PublicFormat::DEPTH16: case PublicFormat::RAW_DEPTH: - return HAL_DATASPACE_DEPTH; + dataspace = Dataspace::DEPTH; + break; case PublicFormat::RAW_SENSOR: case PublicFormat::RAW_PRIVATE: case PublicFormat::RAW10: case PublicFormat::RAW12: - return HAL_DATASPACE_ARBITRARY; + dataspace = Dataspace::ARBITRARY; + break; case PublicFormat::YUV_420_888: case PublicFormat::NV21: case PublicFormat::YV12: - return HAL_DATASPACE_V0_JFIF; + dataspace = Dataspace::V0_JFIF; + break; case PublicFormat::DEPTH_JPEG: - return static_cast<android_dataspace> (HAL_DATASPACE_DYNAMIC_DEPTH); + dataspace = Dataspace::DYNAMIC_DEPTH; + break; + case PublicFormat::HEIC: + dataspace = Dataspace::HEIF; + break; default: // Most formats map to UNKNOWN - return HAL_DATASPACE_UNKNOWN; + dataspace = Dataspace::UNKNOWN; + break; } + return static_cast<android_dataspace>(dataspace); } PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( int format, android_dataspace dataSpace) { + Dataspace ds = static_cast<Dataspace>(dataSpace); switch(format) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: @@ -187,8 +202,8 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( // Enums overlap in both name and value return static_cast<PublicFormat>(format); case HAL_PIXEL_FORMAT_RAW16: - switch (dataSpace) { - case HAL_DATASPACE_DEPTH: + switch (ds) { + case Dataspace::DEPTH: return PublicFormat::RAW_DEPTH; default: return PublicFormat::RAW_SENSOR; @@ -210,8 +225,8 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( return PublicFormat::PRIVATE; case HAL_PIXEL_FORMAT_Y16: // Dataspace-dependent - switch (dataSpace) { - case HAL_DATASPACE_DEPTH: + switch (ds) { + case Dataspace::DEPTH: return PublicFormat::DEPTH16; default: // Assume non-depth Y16 is just Y16. @@ -220,11 +235,13 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( break; case HAL_PIXEL_FORMAT_BLOB: // Dataspace-dependent - switch (dataSpace) { - case HAL_DATASPACE_DEPTH: + switch (ds) { + case Dataspace::DEPTH: return PublicFormat::DEPTH_POINT_CLOUD; - case HAL_DATASPACE_V0_JFIF: + case Dataspace::V0_JFIF: return PublicFormat::JPEG; + case Dataspace::HEIF: + return PublicFormat::HEIC; default: if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) { return PublicFormat::DEPTH_JPEG; diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 68be0054ae45..6b8d8b1bb91f 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -178,12 +178,13 @@ static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) { sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); + ctrl->release(); ctrl->decStrong((void *)nativeCreate); } static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) { sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); - ctrl->clear(); + ctrl->destroy(); ctrl->decStrong((void *)nativeCreate); } diff --git a/core/jni/include/android_runtime/android_view_Surface.h b/core/jni/include/android_runtime/android_view_Surface.h index 984e942207c1..3f7c00c9ff01 100644 --- a/core/jni/include/android_runtime/android_view_Surface.h +++ b/core/jni/include/android_runtime/android_view_Surface.h @@ -55,10 +55,11 @@ enum class PublicFormat { DEPTH_POINT_CLOUD = 0x101, RAW_DEPTH = 0x1002, // @hide YV12 = 0x32315659, - Y8 = 0x20203859, // @hide + Y8 = 0x20203859, Y16 = 0x20363159, // @hide DEPTH16 = 0x44363159, DEPTH_JPEG = 0x69656963, + HEIC = 0x48454946, }; /* Gets the underlying ANativeWindow for a Surface. */ diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index a160451ecfed..d5776534bb90 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -259,6 +259,8 @@ message GlobalSettingsProto { optional SettingProto app = 1; // Whether views are allowed to save their attribute data. optional SettingProto view_attributes = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Which application package is allowed to save view attribute data. + optional SettingProto view_attributes_application_package = 3 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Debug debug = 37; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 60b04cf6c77b..07dd26e4969b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -662,8 +662,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readContacts" android:description="@string/permdesc_readContacts" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to write the user's contacts data. <p>Protection level: dangerous @@ -694,8 +693,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCalendar" android:description="@string/permdesc_readCalendar" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to write the user's calendar data. <p>Protection level: dangerous @@ -736,8 +734,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveSms" android:description="@string/permdesc_receiveSms" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to read SMS messages. <p>Protection level: dangerous @@ -746,8 +743,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readSms" android:description="@string/permdesc_readSms" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to receive WAP push messages. <p>Protection level: dangerous @@ -756,8 +752,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveWapPush" android:description="@string/permdesc_receiveWapPush" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to monitor incoming MMS messages. <p>Protection level: dangerous @@ -766,8 +761,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveMms" android:description="@string/permdesc_receiveMms" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast messages and to register a content observer to get notifications when @@ -785,8 +779,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCellBroadcasts" android:description="@string/permdesc_readCellBroadcasts" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- ====================================================================== --> <!-- Permissions for accessing external storage --> @@ -867,8 +860,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_audioRead" android:description="@string/permdesc_audioRead" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Runtime permission controlling access to the user's shared visual media collection, including images and videos. --> @@ -884,16 +876,14 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_imagesRead" android:description="@string/permdesc_imagesRead" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to read the user's shared video collection. --> <permission android:name="android.permission.READ_MEDIA_VIDEO" android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_videoRead" android:description="@string/permdesc_videoRead" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to access any geographic locations persisted in the user's shared collection. --> @@ -901,8 +891,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_mediaLocation" android:description="@string/permdesc_mediaLocation" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- @hide @SystemApi @TestApi Allows an application to modify OBB files visible to other apps. --> @@ -934,8 +923,7 @@ android:label="@string/permlab_accessFineLocation" android:description="@string/permdesc_accessFineLocation" android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- Allows an app to access approximate location. Alternatively, you might want {@link #ACCESS_FINE_LOCATION}. @@ -946,8 +934,7 @@ android:label="@string/permlab_accessCoarseLocation" android:description="@string/permdesc_accessCoarseLocation" android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- Allows an app to access location in the background. If you are requesting this, you should also request {@link #ACCESS_FINE_LOCATION}. @@ -959,8 +946,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_accessBackgroundLocation" android:description="@string/permdesc_accessBackgroundLocation" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> <!-- Permissions for accessing the call log --> @@ -1001,8 +987,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCallLog" android:description="@string/permdesc_readCallLog" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to write (but not read) the user's call log data. @@ -1032,8 +1017,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_processOutgoingCalls" android:description="@string/permdesc_processOutgoingCalls" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- ====================================================================== --> <!-- Permissions for accessing the device telephony --> @@ -1065,8 +1049,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readPhoneState" android:description="@string/permdesc_readPhoneState" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities granted by {@link #READ_PHONE_STATE} but is exposed to instant applications. @@ -1075,8 +1058,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readPhoneNumbers" android:description="@string/permdesc_readPhoneNumbers" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call. @@ -1178,8 +1160,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_recordAudio" android:description="@string/permdesc_recordAudio" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> <!-- Permissions for activity recognition --> @@ -1202,8 +1183,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_activityRecognition" android:description="@string/permdesc_activityRecognition" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> <!-- Permissions for accessing the UCE Service --> @@ -1252,8 +1232,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_camera" android:description="@string/permdesc_camera" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> @@ -1277,8 +1256,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_bodySensors" android:description="@string/permdesc_bodySensors" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an app to use fingerprint hardware. <p>Protection level: normal @@ -1780,8 +1758,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:protectionLevel="dangerous" android:description="@string/permdesc_getAccounts" - android:label="@string/permlab_getAccounts" - android:usageInfoRequired="true" /> + android:label="@string/permlab_getAccounts" /> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> <!-- Allows applications to call into AccountAuthenticators. diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index fa3a549463f5..46e14b41960c 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2426,6 +2426,8 @@ </attr> <attr name="__removed3" /> + <attr name="__removed4" /> + <attr name="__removed5" /> <!-- Describes the content of a view so that a autofill service can fill in the appropriate data. Multiple hints can be combined in a comma separated list or an array of strings diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 881688bd00c0..53cae638db80 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1689,10 +1689,6 @@ <attr name="request" /> <attr name="protectionLevel" /> <attr name="permissionFlags" /> - <!-- If {@code true} applications that target Q <em>must</em> specify the permission usage - attributes in their {@code uses-permission} elements or the permission will not be - granted. --> - <attr name="usageInfoRequired" format="boolean" /> </declare-styleable> <!-- The <code>permission-group</code> tag declares a logical grouping of @@ -1792,81 +1788,6 @@ requested. If it does support the feature, it will be as if the manifest didn't request it at all. --> <attr name="requiredNotFeature" format="string" /> - - <!-- Specify if the app uploads data, or derived data, guarded by this permission. - - If the permission is defined with {@link android.R.attr#usageInfoRequired} - {@code true} this <em>must</em> be specified by apps that target Android Q or the - permission will not be granted, it will be as if the manifest didn't request it at all. - --> - <attr name="dataSentOffDevice"> - <!-- The application may send data, or derived data, guarded by this permission off of the - device. --> - <enum name="yes" value="1" /> - <!-- The application may send data, or derived data, guarded by this permission off of the - device, however it will only do so when explicitly triggered by a user action. --> - <enum name="userTriggered" value="2" /> - <!-- The application does not send data, or derived data, guarded by this permission off - of the device. --> - <enum name="no" value="3" /> - </attr> - - <!-- Specify if the application or its related off-device services provide data, - or derived data, guarded by this permission to third parties outside of the developer's - organization that do not qualify as data processors. - - If the permission is defined with {@link android.R.attr#usageInfoRequired} - {@code true} this <em>must</em> be specified by apps that target Android Q or the - permission will not be granted, it will be as if the manifest didn't request it at all. - --> - <attr name="dataSharedWithThirdParty"> - <!-- The application or its services may provide data, or derived data, guarded by this - permission to third party organizations. --> - <enum name="yes" value="1" /> - <!-- The application or its services may provide data, or derived data, guarded by this - permission to third party organizations, however it will only do so when explicitly - triggered by a user action. --> - <enum name="userTriggered" value="2" /> - <!-- The application or its services does not provide data, or derived data, guarded by - this permission to third party organizations. --> - <enum name="no" value="3" /> - </attr> - - <!-- Specify if the application or its related off-device services use data, - or derived data, guarded by this permission for monetization purposes. - - For example, if the data is sold to another party or used for targeting advertisements - this must be set to {@code yes}. - - If the permission is defined with {@link android.R.attr#usageInfoRequired} - {@code true} this <em>must</em> be specified by apps that target Android Q or the - permission will not be granted, it will be as if the manifest didn't request it at all. - --> - <attr name="dataUsedForMonetization"> - <!-- The application or its services may use data, or derived data, guarded by this - permission for monetization purposes. --> - <enum name="yes" value="1" /> - <!-- The application or its services may use data, or derived data, guarded by this - permission for monetization purposes, however it will only do so when explicity - triggered by a user action. --> - <enum name="userTriggered" value="2" /> - <!-- The application or its services does not use data, or derived data, guarded by - this permission for monetization purposes. --> - <enum name="no" value="3" /> - </attr> - - <!-- Specify how long the application or its related off-device services store - data, or derived data, guarded by this permission. - - This can be one of "notRetained", "userSelected", "unlimited", or a number - representing the number of weeks the data is retained. - - If the permission is defined with {@link android.R.attr#usageInfoRequired} - {@code true} this <em>must</em> be specified by apps that target Android Q or the - permission will not be granted, it will be as if the manifest didn't request it at all. - --> - <attr name="dataRetentionTime" format="string" /> - </declare-styleable> <!-- The <code>uses-configuration</code> tag specifies diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 76b589ca4009..ec53811a6983 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -963,7 +963,7 @@ <bool name="config_nightDisplayAvailable">@bool/config_setColorTransformAccelerated</bool> <!-- Default mode to control how Night display is automatically activated. - One of the following values (see ColorDisplayController.java): + One of the following values (see ColorDisplayManager.java): 0 - AUTO_MODE_DISABLED 1 - AUTO_MODE_CUSTOM_TIME 2 - AUTO_MODE_TWILIGHT @@ -1052,7 +1052,7 @@ </string-array> - <!-- Indicate available ColorDisplayController.COLOR_MODE_xxx. --> + <!-- Indicate available ColorDisplayManager.COLOR_MODE_xxx. --> <integer-array name="config_availableColorModes"> <!-- Example: <item>0</item> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index f84f1f1bdb4f..e6d478aadae0 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2925,11 +2925,11 @@ <public name="importantForContentCapture" /> <public name="supportsMultipleDisplays" /> <public name="useAppZygote" /> - <public name="usageInfoRequired" /> - <public name="dataSentOffDevice" /> - <public name="dataSharedWithThirdParty" /> - <public name="dataUsedForMonetization" /> - <public name="dataRetentionTime" /> + <public name="__removed1" /> + <public name="__removed2" /> + <public name="__removed3" /> + <public name="__removed4" /> + <public name="__removed5" /> <public name="selectionDividerHeight" /> <public name="foregroundServiceType" /> <public name="hasFragileUserData" /> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 2cb925aa9549..ec57f793f15f 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -210,6 +210,7 @@ public class SettingsBackupTest { Settings.Global.DATA_STALL_VALID_DNS_TIME_THRESHOLD, Settings.Global.DEBUG_APP, Settings.Global.DEBUG_VIEW_ATTRIBUTES, + Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, Settings.Global.DEFAULT_DNS_SERVER, Settings.Global.DEFAULT_INSTALL_LOCATION, Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA, diff --git a/core/tests/coretests/src/android/view/accessibility/FindViewByIdTest.java b/core/tests/coretests/src/android/view/accessibility/FindViewByIdTest.java new file mode 100644 index 000000000000..da6ecb45bd5c --- /dev/null +++ b/core/tests/coretests/src/android/view/accessibility/FindViewByIdTest.java @@ -0,0 +1,100 @@ +/* + * 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.accessibility; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import android.app.Activity; +import android.content.Context; +import android.view.View; +import android.widget.LinearLayout; + +import androidx.test.InstrumentationRegistry; +import androidx.test.annotation.UiThreadTest; +import androidx.test.filters.MediumTest; +import androidx.test.rule.ActivityTestRule; + +import org.junit.Rule; +import org.junit.Test; + +@MediumTest +public class FindViewByIdTest { + + @Rule + public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class); + + private Context getContext() { + return InstrumentationRegistry.getTargetContext(); + } + + private Activity getActivity() { + return mActivityRule.getActivity(); + } + + @UiThreadTest + @Test + public void testFindViewById() { + LinearLayout contentView = new LinearLayout(getContext()); + getActivity().setContentView(contentView); + View child1 = new View(getContext()); + View child2 = new View(getContext()); + child1.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + child2.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + + contentView.addView(child1); + contentView.addView(child2); + View result = AccessibilityNodeIdManager.getInstance().findView( + child2.getAccessibilityViewId()); + assertEquals(result, child2); + } + + @UiThreadTest + @Test + public void testFindViewByIdReturnNullIfRemovedFromHierarchy() { + LinearLayout contentView = new LinearLayout(getContext()); + getActivity().setContentView(contentView); + View child1 = new View(getContext()); + View child2 = new View(getContext()); + contentView.addView(child1); + contentView.addView(child2); + child1.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + child2.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + + contentView.removeView(child1); + View result = AccessibilityNodeIdManager.getInstance().findView( + child1.getAccessibilityViewId()); + assertNull(result); + } + + @UiThreadTest + @Test + public void testFindViewByIdReturnNullIfNotImportant() { + LinearLayout contentView = new LinearLayout(getContext()); + getActivity().setContentView(contentView); + View child1 = new View(getContext()); + View child2 = new View(getContext()); + child2.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + + contentView.addView(child1); + contentView.addView(child2); + + View result = AccessibilityNodeIdManager.getInstance().findView( + child1.getAccessibilityViewId()); + assertNull(result); + } +} diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java new file mode 100644 index 000000000000..f325d8943ea3 --- /dev/null +++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java @@ -0,0 +1,229 @@ +/* + * 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.contentcapture; + +import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED; +import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED; +import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED; + +import static com.google.common.truth.Truth.assertThat; + +import static org.testng.Assert.assertThrows; + +import android.os.Parcel; +import android.os.SystemClock; +import android.view.autofill.AutofillId; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.ArrayList; + +/** + * Unit test for {@link ContentCaptureEvent}. + * + * <p>To run it: + * {@code atest FrameworksCoreTests:android.view.contentcapture.ContentCaptureEventTest} + */ +@RunWith(JUnit4.class) +public class ContentCaptureEventTest { + + private static final long MY_EPOCH = SystemClock.uptimeMillis(); + + // Not using @Mock because it's final - no need to be fancy here.... + private final ContentCaptureContext mClientContext = new ContentCaptureContext.Builder() + .setAction("WHATEVER").build(); + + @Test + public void testSetAutofillId_null() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED); + + assertThrows(NullPointerException.class, () -> event.setAutofillId(null)); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).isNull(); + } + + @Test + public void testSetAutofillIds_null() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED); + + assertThrows(NullPointerException.class, () -> event.setAutofillIds(null)); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).isNull(); + } + + @Test + public void testAddAutofillId_null() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED); + + assertThrows(NullPointerException.class, () -> event.addAutofillId(null)); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).isNull(); + } + + @Test + public void testSetAutofillId() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED); + + final AutofillId id = new AutofillId(108); + event.setAutofillId(id); + assertThat(event.getId()).isEqualTo(id); + assertThat(event.getIds()).isNull(); + } + + @Test + public void testSetAutofillIds() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED); + + final AutofillId id = new AutofillId(108); + final ArrayList<AutofillId> ids = new ArrayList<>(1); + ids.add(id); + event.setAutofillIds(ids); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).containsExactly(id); + } + + @Test + public void testAddAutofillId() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED); + + final AutofillId id1 = new AutofillId(108); + event.addAutofillId(id1); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).containsExactly(id1); + + final AutofillId id2 = new AutofillId(666); + event.addAutofillId(id2); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).containsExactly(id1, id2).inOrder(); + } + + @Test + public void testAddAutofillId_afterSetId() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED); + + final AutofillId id1 = new AutofillId(108); + event.setAutofillId(id1); + assertThat(event.getId()).isEqualTo(id1); + assertThat(event.getIds()).isNull(); + + final AutofillId id2 = new AutofillId(666); + event.addAutofillId(id2); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).containsExactly(id1, id2).inOrder(); + } + + @Test + public void testAddAutofillId_afterSetIds() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED); + + final AutofillId id1 = new AutofillId(108); + final ArrayList<AutofillId> ids = new ArrayList<>(1); + ids.add(id1); + event.setAutofillIds(ids); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).containsExactly(id1); + + final AutofillId id2 = new AutofillId(666); + event.addAutofillId(id2); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).containsExactly(id1, id2).inOrder(); + } + + @Test + public void testSessionStarted_directly() { + final ContentCaptureEvent event = newEventForSessionStarted(); + assertSessionStartedEvent(event); + } + + @Test + public void testSessionStarted_throughParcel() { + final ContentCaptureEvent event = newEventForSessionStarted(); + final ContentCaptureEvent clone = cloneThroughParcel(event); + assertSessionStartedEvent(clone); + } + + private ContentCaptureEvent newEventForSessionStarted() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_SESSION_STARTED) + .setClientContext(mClientContext) + .setParentSessionId("108"); + assertThat(event).isNotNull(); + return event; + } + + private void assertSessionStartedEvent(ContentCaptureEvent event) { + assertThat(event.getType()).isEqualTo(TYPE_SESSION_STARTED); + assertThat(event.getEventTime()).isAtLeast(MY_EPOCH); + assertThat(event.getSessionId()).isEqualTo("42"); + assertThat(event.getParentSessionId()).isEqualTo("108"); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).isNull(); + assertThat(event.getText()).isNull(); + assertThat(event.getViewNode()).isNull(); + final ContentCaptureContext clientContext = event.getClientContext(); + assertThat(clientContext.getAction()).isEqualTo("WHATEVER"); + } + + @Test + public void testSessionFinished_directly() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_SESSION_FINISHED) + .setParentSessionId("108"); + assertThat(event).isNotNull(); + assertSessionFinishedEvent(event); + } + + @Test + public void testSessionFinished_throughParcel() { + final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_SESSION_FINISHED) + .setClientContext(mClientContext) // should not be writting to parcel + .setParentSessionId("108"); + assertThat(event).isNotNull(); + final ContentCaptureEvent clone = cloneThroughParcel(event); + assertSessionFinishedEvent(clone); + } + + private void assertSessionFinishedEvent(ContentCaptureEvent event) { + assertThat(event.getType()).isEqualTo(TYPE_SESSION_FINISHED); + assertThat(event.getEventTime()).isAtLeast(MY_EPOCH); + assertThat(event.getSessionId()).isEqualTo("42"); + assertThat(event.getParentSessionId()).isEqualTo("108"); + assertThat(event.getId()).isNull(); + assertThat(event.getIds()).isNull(); + assertThat(event.getText()).isNull(); + assertThat(event.getViewNode()).isNull(); + assertThat(event.getClientContext()).isNull(); + } + + private ContentCaptureEvent cloneThroughParcel(ContentCaptureEvent event) { + Parcel parcel = Parcel.obtain(); + + try { + // Write to parcel + parcel.setDataPosition(0); // Sanity / paranoid check + event.writeToParcel(parcel, 0); + + // Read from parcel + parcel.setDataPosition(0); + ContentCaptureEvent clone = ContentCaptureEvent.CREATOR.createFromParcel(parcel); + assertThat(clone).isNotNull(); + return clone; + } finally { + parcel.recycle(); + } + } + +} diff --git a/core/tests/coretests/src/android/view/contentcapture/UserDataRemovalRequestTest.java b/core/tests/coretests/src/android/view/contentcapture/UserDataRemovalRequestTest.java deleted file mode 100644 index bebb2a89f480..000000000000 --- a/core/tests/coretests/src/android/view/contentcapture/UserDataRemovalRequestTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.contentcapture; - -import static com.google.common.truth.Truth.assertThat; - -import static org.testng.Assert.assertThrows; - -import android.net.Uri; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -/** - * Unit test for {@link UserDataRemovalRequest}. - * - * <p>To run it: - * {@code atest FrameworksCoreTests:android.view.contentcapture.UserDataRemovalRequestTest} - */ -@RunWith(MockitoJUnitRunner.class) -public class UserDataRemovalRequestTest { - - @Mock - private final Uri mUri = Uri.parse("content://com.example/"); - - private UserDataRemovalRequest.Builder mBuilder = new UserDataRemovalRequest.Builder(); - - @Test - public void testBuilder_addUri_invalid() { - assertThrows(NullPointerException.class, () -> mBuilder.addUri(null, false)); - } - - @Test - public void testBuilder_addUri_valid() { - assertThat(mBuilder.addUri(mUri, false)).isNotNull(); - assertThat(mBuilder.addUri(Uri.parse("content://com.example2"), true)).isNotNull(); - } - - @Test - public void testBuilder_addUriAfterForEverything() { - assertThat(mBuilder.forEverything()).isNotNull(); - assertThrows(IllegalStateException.class, () -> mBuilder.addUri(mUri, false)); - } - - @Test - public void testBuilder_forEverythingAfterAddingUri() { - assertThat(mBuilder.addUri(mUri, false)).isNotNull(); - assertThrows(IllegalStateException.class, () -> mBuilder.forEverything()); - } - - @Test - public void testBuild_invalid() { - assertThrows(IllegalStateException.class, () -> mBuilder.build()); - } - - @Test - public void testBuild_valid() { - assertThat(new UserDataRemovalRequest.Builder().forEverything().build()) - .isNotNull(); - assertThat(new UserDataRemovalRequest.Builder().addUri(mUri, false).build()) - .isNotNull(); - } - - @Test - public void testNoMoreInteractionsAfterBuild() { - assertThat(mBuilder.forEverything().build()).isNotNull(); - - assertThrows(IllegalStateException.class, () -> mBuilder.addUri(mUri, false)); - assertThrows(IllegalStateException.class, () -> mBuilder.forEverything()); - assertThrows(IllegalStateException.class, () -> mBuilder.build()); - - } -} diff --git a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java index b84a098574c2..213cd405e903 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java @@ -18,29 +18,18 @@ package android.view.contentcapture; import static com.google.common.truth.Truth.assertThat; -import static org.testng.Assert.assertThrows; - import android.content.Context; import android.graphics.Matrix; -import android.os.Bundle; -import android.os.LocaleList; -import android.os.Parcel; +import android.support.test.InstrumentationRegistry; import android.view.View; import android.view.ViewStructure.HtmlInfo; -import android.view.autofill.AutofillId; -import android.view.autofill.AutofillValue; import android.view.contentcapture.ViewNode.ViewStructureImpl; -import android.widget.FrameLayout; - -import androidx.test.InstrumentationRegistry; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import java.util.Locale; - /** * Unit tests for {@link ViewNode}. * @@ -55,100 +44,6 @@ public class ViewNodeTest { private HtmlInfo mHtmlInfoMock; @Test - public void testAutofillIdMethods_orphanView() { - View view = new View(mContext); - AutofillId initialId = new AutofillId(42); - view.setAutofillId(initialId); - - ViewStructureImpl structure = new ViewStructureImpl(view); - ViewNode node = structure.getNode(); - - assertThat(node.getAutofillId()).isEqualTo(initialId); - assertThat(node.getParentAutofillId()).isNull(); - - AutofillId newId = new AutofillId(108); - structure.setAutofillId(newId); - assertThat(node.getAutofillId()).isEqualTo(newId); - assertThat(node.getParentAutofillId()).isNull(); - - structure.setAutofillId(new AutofillId(66), 6); - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6)); - assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66)); - } - - @Test - public void testAutofillIdMethods_parentedView() { - FrameLayout parent = new FrameLayout(mContext); - AutofillId initialParentId = new AutofillId(48); - parent.setAutofillId(initialParentId); - - View child = new View(mContext); - AutofillId initialChildId = new AutofillId(42); - child.setAutofillId(initialChildId); - - parent.addView(child); - - ViewStructureImpl structure = new ViewStructureImpl(child); - ViewNode node = structure.getNode(); - - assertThat(node.getAutofillId()).isEqualTo(initialChildId); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - AutofillId newChildId = new AutofillId(108); - structure.setAutofillId(newChildId); - assertThat(node.getAutofillId()).isEqualTo(newChildId); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - AutofillId newParentId = new AutofillId(15162342); - parent.setAutofillId(newParentId); - assertThat(node.getAutofillId()).isEqualTo(newChildId); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - structure.setAutofillId(new AutofillId(66), 6); - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6)); - assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66)); - } - - @Test - public void testAutofillIdMethods_explicitIdsConstructor() { - AutofillId initialParentId = new AutofillId(42); - ViewStructureImpl structure = new ViewStructureImpl(initialParentId, 108, 666); - ViewNode node = structure.getNode(); - - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(initialParentId, 108, 666)); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - AutofillId newChildId = new AutofillId(108); - structure.setAutofillId(newChildId); - assertThat(node.getAutofillId()).isEqualTo(newChildId); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - structure.setAutofillId(new AutofillId(66), 6); - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6)); - assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66)); - } - - @Test - public void testInvalidSetters() { - View view = new View(mContext); - AutofillId initialId = new AutofillId(42); - view.setAutofillId(initialId); - - ViewStructureImpl structure = new ViewStructureImpl(view); - ViewNode node = structure.getNode(); - assertThat(node.getAutofillId()).isEqualTo(initialId); // sanity check - - assertThrows(NullPointerException.class, () -> structure.setAutofillId(null)); - assertThat(node.getAutofillId()).isEqualTo(initialId); // invariant - - assertThrows(NullPointerException.class, () -> structure.setAutofillId(null, 666)); - assertThat(node.getAutofillId()).isEqualTo(initialId); // invariant - - assertThrows(NullPointerException.class, () -> structure.setTextIdEntry(null)); - assertThat(node.getTextIdEntry()).isNull(); - } - - @Test public void testUnsupportedProperties() { View view = new View(mContext); @@ -190,273 +85,4 @@ public class ViewNodeTest { structure.setTransformation(Matrix.IDENTITY_MATRIX); assertThat(node.getTransformation()).isNull(); } - - @Test - public void testValidProperties_directly() { - ViewStructureImpl structure = newSimpleStructure(); - assertSimpleStructure(structure); - assertSimpleNode(structure.getNode()); - } - - @Test - public void testValidProperties_throughParcel() { - ViewStructureImpl structure = newSimpleStructure(); - final ViewNode node = structure.getNode(); - assertSimpleNode(node); // sanity check - - final ViewNode clone = cloneThroughParcel(node); - assertSimpleNode(clone); - } - - @Test - public void testComplexText_directly() { - ViewStructureImpl structure = newStructureWithComplexText(); - assertStructureWithComplexText(structure); - assertNodeWithComplexText(structure.getNode()); - } - - @Test - public void testComplexText_throughParcel() { - ViewStructureImpl structure = newStructureWithComplexText(); - final ViewNode node = structure.getNode(); - assertNodeWithComplexText(node); // sanity check - - ViewNode clone = cloneThroughParcel(node); - assertNodeWithComplexText(clone); - } - - @Test - public void testVisibility() { - // Visibility is a special case becase it use flag masks, so we want to make sure it works - // fine - View view = new View(mContext); - ViewStructureImpl structure = new ViewStructureImpl(view); - ViewNode node = structure.getNode(); - - structure.setVisibility(View.VISIBLE); - assertThat(node.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE); - - structure.setVisibility(View.GONE); - assertThat(node.getVisibility()).isEqualTo(View.GONE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.GONE); - - structure.setVisibility(View.VISIBLE); - assertThat(node.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE); - - structure.setVisibility(View.INVISIBLE); - assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.INVISIBLE); - - structure.setVisibility(View.INVISIBLE | View.GONE); - assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE | View.GONE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.INVISIBLE | View.GONE); - - - final int invalidValue = Math.max(Math.max(View.VISIBLE, View.INVISIBLE), View.GONE) * 2; - structure.setVisibility(View.VISIBLE); - structure.setVisibility(invalidValue); // should be ignored - assertThat(node.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE); - - structure.setVisibility(View.GONE | invalidValue); - assertThat(node.getVisibility()).isEqualTo(View.GONE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.GONE); - } - - /** - * Creates a {@link ViewStructureImpl} that can be asserted through - * {@link #assertSimpleNode(ViewNode)}. - */ - private ViewStructureImpl newSimpleStructure() { - View view = new View(mContext); - view.setAutofillId(new AutofillId(42)); - - ViewStructureImpl structure = new ViewStructureImpl(view); - - // Basic properties - structure.setText("Text is set!"); - structure.setClassName("Classy!"); - structure.setContentDescription("Described I am!"); - structure.setVisibility(View.INVISIBLE); - - // Autofill properties - structure.setAutofillType(View.AUTOFILL_TYPE_TEXT); - structure.setAutofillHints(new String[] { "Auto", "Man" }); - structure.setAutofillOptions(new String[] { "Maybe" }); - structure.setAutofillValue(AutofillValue.forText("Malkovich")); - - // Extra text properties - structure.setMinTextEms(6); - structure.setMaxTextLength(66); - structure.setMaxTextEms(666); - structure.setInputType(42); - structure.setTextIdEntry("TEXT, Y U NO ENTRY?"); - structure.setLocaleList(new LocaleList(Locale.US, Locale.ENGLISH)); - - // Resource id - structure.setId(16, "package.name", "type.name", "entry.name"); - - // Dimensions - structure.setDimens(4, 8, 15, 16, 23, 42); - - // Boolean properties - structure.setAssistBlocked(true); - structure.setEnabled(true); - structure.setClickable(true); - structure.setLongClickable(true); - structure.setContextClickable(true); - structure.setFocusable(true); - structure.setFocused(true); - structure.setAccessibilityFocused(true); - structure.setChecked(true); - structure.setActivated(true); - structure.setOpaque(true); - - // Bundle - assertThat(structure.hasExtras()).isFalse(); - final Bundle bundle = structure.getExtras(); - assertThat(bundle).isNotNull(); - bundle.putString("Marlon", "Bundle"); - assertThat(structure.hasExtras()).isTrue(); - return structure; - } - - /** - * Asserts the properties of a {@link ViewNode} that was created by - * {@link #newSimpleStructure()}. - */ - private void assertSimpleNode(ViewNode node) { - - // Basic properties - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(42)); - assertThat(node.getParentAutofillId()).isNull(); - assertThat(node.getText()).isEqualTo("Text is set!"); - assertThat(node.getClassName()).isEqualTo("Classy!"); - assertThat(node.getContentDescription().toString()).isEqualTo("Described I am!"); - assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE); - - // Autofill properties - assertThat(node.getAutofillType()).isEqualTo(View.AUTOFILL_TYPE_TEXT); - assertThat(node.getAutofillHints()).asList().containsExactly("Auto", "Man").inOrder(); - assertThat(node.getAutofillOptions()).asList().containsExactly("Maybe").inOrder(); - assertThat(node.getAutofillValue().getTextValue()).isEqualTo("Malkovich"); - - // Extra text properties - assertThat(node.getMinTextEms()).isEqualTo(6); - assertThat(node.getMaxTextLength()).isEqualTo(66); - assertThat(node.getMaxTextEms()).isEqualTo(666); - assertThat(node.getInputType()).isEqualTo(42); - assertThat(node.getTextIdEntry()).isEqualTo("TEXT, Y U NO ENTRY?"); - assertThat(node.getLocaleList()).isEqualTo(new LocaleList(Locale.US, Locale.ENGLISH)); - - // Resource id - assertThat(node.getId()).isEqualTo(16); - assertThat(node.getIdPackage()).isEqualTo("package.name"); - assertThat(node.getIdType()).isEqualTo("type.name"); - assertThat(node.getIdEntry()).isEqualTo("entry.name"); - - // Dimensions - assertThat(node.getLeft()).isEqualTo(4); - assertThat(node.getTop()).isEqualTo(8); - assertThat(node.getScrollX()).isEqualTo(15); - assertThat(node.getScrollY()).isEqualTo(16); - assertThat(node.getWidth()).isEqualTo(23); - assertThat(node.getHeight()).isEqualTo(42); - - // Boolean properties - assertThat(node.isAssistBlocked()).isTrue(); - assertThat(node.isEnabled()).isTrue(); - assertThat(node.isClickable()).isTrue(); - assertThat(node.isLongClickable()).isTrue(); - assertThat(node.isContextClickable()).isTrue(); - assertThat(node.isFocusable()).isTrue(); - assertThat(node.isFocused()).isTrue(); - assertThat(node.isAccessibilityFocused()).isTrue(); - assertThat(node.isChecked()).isTrue(); - assertThat(node.isActivated()).isTrue(); - assertThat(node.isOpaque()).isTrue(); - - // Bundle - final Bundle bundle = node.getExtras(); - assertThat(bundle).isNotNull(); - assertThat(bundle.size()).isEqualTo(1); - assertThat(bundle.getString("Marlon")).isEqualTo("Bundle"); - } - - /** - * Asserts the properties of a {@link ViewStructureImpl} that was created by - * {@link #newSimpleStructure()}. - */ - private void assertSimpleStructure(ViewStructureImpl structure) { - assertThat(structure.getAutofillId()).isEqualTo(new AutofillId(42)); - assertThat(structure.getText()).isEqualTo("Text is set!"); - - // Bundle - final Bundle bundle = structure.getExtras(); - assertThat(bundle.size()).isEqualTo(1); - assertThat(bundle.getString("Marlon")).isEqualTo("Bundle"); - } - - /** - * Creates a {@link ViewStructureImpl} with "complex" text properties (such as selection); it - * can be asserted through {@link #assertNodeWithComplexText(ViewNode)}. - */ - private ViewStructureImpl newStructureWithComplexText() { - View view = new View(mContext); - ViewStructureImpl structure = new ViewStructureImpl(view); - structure.setText("IGNORE ME!"); - structure.setText("Now we're talking!", 4, 8); - structure.setHint("Soylent Green is SPOILER ALERT"); - structure.setTextStyle(15.0f, 16, 23, 42); - structure.setTextLines(new int[] {4, 8, 15} , new int[] {16, 23, 42}); - return structure; - } - - /** - * Asserts the properties of a {@link ViewNode} that was created by - * {@link #newStructureWithComplexText()}. - */ - private void assertNodeWithComplexText(ViewNode node) { - assertThat(node.getText()).isEqualTo("Now we're talking!"); - assertThat(node.getTextSelectionStart()).isEqualTo(4); - assertThat(node.getTextSelectionEnd()).isEqualTo(8); - assertThat(node.getHint()).isEqualTo("Soylent Green is SPOILER ALERT"); - assertThat(node.getTextSize()).isWithin(1.0e-10f).of(15.0f); - assertThat(node.getTextColor()).isEqualTo(16); - assertThat(node.getTextBackgroundColor()).isEqualTo(23); - assertThat(node.getTextStyle()).isEqualTo(42); - assertThat(node.getTextLineCharOffsets()).asList().containsExactly(4, 8, 15).inOrder(); - assertThat(node.getTextLineBaselines()).asList().containsExactly(16, 23, 42).inOrder(); - } - - /** - * Asserts the properties of a {@link ViewStructureImpl} that was created by - * {@link #newStructureWithComplexText()}. - */ - private void assertStructureWithComplexText(ViewStructureImpl structure) { - assertThat(structure.getText()).isEqualTo("Now we're talking!"); - assertThat(structure.getTextSelectionStart()).isEqualTo(4); - assertThat(structure.getTextSelectionEnd()).isEqualTo(8); - assertThat(structure.getHint()).isEqualTo("Soylent Green is SPOILER ALERT"); - } - - private ViewNode cloneThroughParcel(ViewNode node) { - Parcel parcel = Parcel.obtain(); - - try { - // Write to parcel - parcel.setDataPosition(0); // Sanity / paranoid check - ViewNode.writeToParcel(parcel, node, 0); - - // Read from parcel - parcel.setDataPosition(0); - ViewNode clone = ViewNode.readFromParcel(parcel); - assertThat(clone).isNotNull(); - return clone; - } finally { - parcel.recycle(); - } - } } diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 0f35918232b4..6770ae19ce3d 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -104,16 +104,6 @@ applications that come with the platform <permission name="android.permission.WRITE_SECURE_SETTINGS"/> </privapp-permissions> - <privapp-permissions package="com.android.omadm.service"> - <permission name="android.permission.CHANGE_CONFIGURATION"/> - <permission name="android.permission.CONNECTIVITY_INTERNAL"/> - <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/> - <permission name="android.permission.MODIFY_PHONE_STATE"/> - <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> - <permission name="android.permission.WRITE_APN_SETTINGS"/> - <permission name="android.permission.WRITE_SECURE_SETTINGS"/> - </privapp-permissions> - <privapp-permissions package="com.android.packageinstaller"> <permission name="android.permission.DELETE_PACKAGES"/> <permission name="android.permission.INSTALL_PACKAGES"/> diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java index 0787d8518fa5..62647741dcfa 100644 --- a/graphics/java/android/graphics/ImageFormat.java +++ b/graphics/java/android/graphics/ImageFormat.java @@ -716,6 +716,14 @@ public class ImageFormat { public static final int PRIVATE = 0x22; /** + * Compressed HEIC format. + * + * <p>This format defines the HEIC brand of High Efficiency Image File + * Format as described in ISO/IEC 23008-12.</p> + */ + public static final int HEIC = 0x48454946; + + /** * Use this function to retrieve the number of bits per pixel of an * ImageFormat. * @@ -796,6 +804,7 @@ public class ImageFormat { case RAW_DEPTH: case Y8: case DEPTH_JPEG: + case HEIC: return true; } diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index bb04ff3cc9ff..7c9529b8ff71 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -134,7 +134,7 @@ public class Typeface { /** * @deprecated Use {@link android.graphics.fonts.FontFamily} instead. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug = 123768928) @Deprecated static final Map<String, android.graphics.FontFamily[]> sSystemFallbackMap = Collections.emptyMap(); @@ -1003,7 +1003,7 @@ public class Typeface { * @deprecated */ @Deprecated - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug = 123768928) private static Typeface createFromFamilies(android.graphics.FontFamily[] families) { long[] ptrArray = new long[families.length]; for (int i = 0; i < families.length; i++) { @@ -1054,7 +1054,7 @@ public class Typeface { * * @deprecated Use {@link android.graphics.fonts.FontFamily} instead. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug = 123768928) @Deprecated private static Typeface createFromFamiliesWithDefault(android.graphics.FontFamily[] families, String fallbackName, int weight, int italic) { diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 20303eba6667..81afd937d85e 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -704,9 +704,29 @@ ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_valu return cookie; } +const std::vector<uint32_t> AssetManager2::GetBagResIdStack(uint32_t resid) { + auto cached_iter = cached_bag_resid_stacks_.find(resid); + if (cached_iter != cached_bag_resid_stacks_.end()) { + return cached_iter->second; + } else { + auto found_resids = std::vector<uint32_t>(); + GetBag(resid, found_resids); + // Cache style stacks if they are not already cached. + cached_bag_resid_stacks_[resid] = found_resids; + return found_resids; + } +} + const ResolvedBag* AssetManager2::GetBag(uint32_t resid) { auto found_resids = std::vector<uint32_t>(); - return GetBag(resid, found_resids); + auto bag = GetBag(resid, found_resids); + + // Cache style stacks if they are not already cached. + auto cached_iter = cached_bag_resid_stacks_.find(resid); + if (cached_iter == cached_bag_resid_stacks_.end()) { + cached_bag_resid_stacks_[resid] = found_resids; + } + return bag; } const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>& child_resids) { diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index f29769b834d1..d862182d8960 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -237,6 +237,8 @@ class AssetManager2 { // resource has been resolved yet. std::string GetLastResourceResolution() const; + const std::vector<uint32_t> GetBagResIdStack(uint32_t resid); + // Retrieves the best matching bag/map resource with ID `resid`. // This method will resolve all parent references for this bag and merge keys with the child. // To iterate over the keys, use the following idiom: @@ -355,6 +357,10 @@ class AssetManager2 { // which involves some calculation. std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_; + // Cached set of bag resid stacks for each bag. These are cached because they might be requested + // a number of times for each view during View inspection. + std::unordered_map<uint32_t, std::vector<uint32_t>> cached_bag_resid_stacks_; + // Whether or not to save resource resolution steps bool resource_resolution_logging_enabled_ = false; diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java index 602cc3e6d0fd..59eff6401deb 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -17,6 +17,7 @@ package android.location; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -49,6 +50,7 @@ public final class GnssMeasurement implements Parcelable { private double mSnrInDb; private double mAutomaticGainControlLevelInDb; private int mCodeType; + private String mOtherCodeTypeName; // The following enumerations must be in sync with the values declared in gps.h @@ -209,8 +211,8 @@ public final class GnssMeasurement implements Parcelable { */ @IntDef(prefix = { "CODE_TYPE_" }, value = { CODE_TYPE_UNKNOWN, CODE_TYPE_A, CODE_TYPE_B, CODE_TYPE_C, CODE_TYPE_I, CODE_TYPE_L, - CODE_TYPE_M, CODE_TYPE_P, CODE_TYPE_Q, CODE_TYPE_S, CODE_TYPE_W, CODE_TYPE_X, - CODE_TYPE_Y, CODE_TYPE_Z, CODE_TYPE_CODELESS + CODE_TYPE_M, CODE_TYPE_N, CODE_TYPE_P, CODE_TYPE_Q, CODE_TYPE_S, CODE_TYPE_W, + CODE_TYPE_X, CODE_TYPE_Y, CODE_TYPE_Z, CODE_TYPE_OTHER }) @Retention(RetentionPolicy.SOURCE) public @interface CodeType {} @@ -299,7 +301,16 @@ public final class GnssMeasurement implements Parcelable { /** * The GNSS Measurement's code type is one of the following: GPS L1 codeless, GPS L2 codeless. */ - public static final int CODE_TYPE_CODELESS = 13; + public static final int CODE_TYPE_N = 13; + + /** + * Other code type that does not belong to any of the above code types. + * + * This code type is used in the case that the code type being tracked in this measurement, as + * classified by RINEX standards, does not fit into one of the existing enumerated values. When + * this code type is set, the field otherCodeTypeName must specify the new code type. + */ + public static final int CODE_TYPE_OTHER = 255; /** * All the 'Accumulated Delta Range' flags. @@ -349,6 +360,7 @@ public final class GnssMeasurement implements Parcelable { mSnrInDb = measurement.mSnrInDb; mAutomaticGainControlLevelInDb = measurement.mAutomaticGainControlLevelInDb; mCodeType = measurement.mCodeType; + mOtherCodeTypeName = measurement.mOtherCodeTypeName; } /** @@ -1175,8 +1187,8 @@ public final class GnssMeasurement implements Parcelable { /** * Gets the GNSS measurement's code type. * - * <p>Similar to the Attribute field described in Rinex 3.03, e.g., in Tables 4-10, and Table - * A2 at the Rinex 3.03 Update 1 Document. + * <p>Similar to the Attribute field described in RINEX 3.03, e.g., in Tables 4-10, and Table + * A2 at the RINEX 3.03 Update 1 Document. */ @CodeType public int getCodeType() { @@ -1206,6 +1218,29 @@ public final class GnssMeasurement implements Parcelable { } /** + * Gets the GNSS measurement's code type name when the code type is {@link #CODE_TYPE_OTHER}. + * + * <p>This is used to specify the observation descriptor defined in GNSS Observation Data File + * Header Section Description in the RINEX standard (Version 3.XX), in cases where the code type + * does not align with an existing Android enumerated value. For example, if a code type "G" is + * added, this string shall be set to "G". + */ + @NonNull + public String getOtherCodeTypeName() { + return mOtherCodeTypeName; + } + + /** + * Sets the GNSS measurement's code type name when the code type is {@link #CODE_TYPE_OTHER}. + * + * @hide + */ + @TestApi + public void setOtherCodeTypeName(@NonNull String otherCodeTypeName) { + mOtherCodeTypeName = otherCodeTypeName; + } + + /** * Gets a string representation of the 'code type'. * * <p>For internal and logging use only. @@ -1226,6 +1261,8 @@ public final class GnssMeasurement implements Parcelable { return "CODE_TYPE_L"; case CODE_TYPE_M: return "CODE_TYPE_M"; + case CODE_TYPE_N: + return "CODE_TYPE_N"; case CODE_TYPE_P: return "CODE_TYPE_P"; case CODE_TYPE_Q: @@ -1240,8 +1277,8 @@ public final class GnssMeasurement implements Parcelable { return "CODE_TYPE_Y"; case CODE_TYPE_Z: return "CODE_TYPE_Z"; - case CODE_TYPE_CODELESS: - return "CODE_TYPE_CODELESS"; + case CODE_TYPE_OTHER: + return "CODE_TYPE_OTHER"; default: return "<Invalid: " + mCodeType + ">"; } @@ -1273,6 +1310,7 @@ public final class GnssMeasurement implements Parcelable { gnssMeasurement.mSnrInDb = parcel.readDouble(); gnssMeasurement.mAutomaticGainControlLevelInDb = parcel.readDouble(); gnssMeasurement.mCodeType = parcel.readInt(); + gnssMeasurement.mOtherCodeTypeName = parcel.readString(); return gnssMeasurement; } @@ -1306,6 +1344,7 @@ public final class GnssMeasurement implements Parcelable { parcel.writeDouble(mSnrInDb); parcel.writeDouble(mAutomaticGainControlLevelInDb); parcel.writeInt(mCodeType); + parcel.writeString(mOtherCodeTypeName); } @Override @@ -1384,6 +1423,9 @@ public final class GnssMeasurement implements Parcelable { format, "CodeType", hasCodeType() ? getCodeTypeString() : null)); + builder.append(String.format( + format, + "OtherCodeTypeName", mOtherCodeTypeName)); return builder.toString(); } @@ -1409,6 +1451,7 @@ public final class GnssMeasurement implements Parcelable { resetSnrInDb(); resetAutomaticGainControlLevel(); resetCodeType(); + setOtherCodeTypeName(""); } private void setFlag(int flag) { diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java index 26b9b8cf85a7..70a343f4de01 100644 --- a/media/java/android/media/Image.java +++ b/media/java/android/media/Image.java @@ -155,6 +155,13 @@ public abstract class Image implements AutoCloseable { * UnSupportedOperationException being thrown. * </td> * </tr> + * <tr> + * <td>{@link android.graphics.ImageFormat#HEIC HEIC}</td> + * <td>1</td> + * <td>Compressed data, so row and pixel strides are 0. To uncompress, use + * {@link android.graphics.BitmapFactory#decodeByteArray BitmapFactory#decodeByteArray}. + * </td> + * </tr> * </table> * * @see android.graphics.ImageFormat diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index 60ef1d93191a..6116429ae561 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -821,6 +821,7 @@ public class ImageReader implements AutoCloseable { case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.RAW_PRIVATE: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: width = ImageReader.this.getWidth(); break; default: @@ -838,6 +839,7 @@ public class ImageReader implements AutoCloseable { case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.RAW_PRIVATE: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: height = ImageReader.this.getHeight(); break; default: diff --git a/media/java/android/media/ImageUtils.java b/media/java/android/media/ImageUtils.java index b77a884d3412..d8a0bb334c53 100644 --- a/media/java/android/media/ImageUtils.java +++ b/media/java/android/media/ImageUtils.java @@ -36,8 +36,8 @@ class ImageUtils { * {@link android.graphics.PixelFormat PixelFormat} are supported by * ImageReader. When reading RGB data from a surface, the formats defined in * {@link android.graphics.PixelFormat PixelFormat} can be used; when - * reading YUV, JPEG or raw sensor data (for example, from the camera or video - * decoder), formats from {@link android.graphics.ImageFormat ImageFormat} + * reading YUV, JPEG, HEIC or raw sensor data (for example, from the camera + * or video decoder), formats from {@link android.graphics.ImageFormat ImageFormat} * are used. */ public static int getNumPlanesForFormat(int format) { @@ -64,6 +64,7 @@ class ImageUtils { case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.RAW_DEPTH: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: return 1; case ImageFormat.PRIVATE: return 0; @@ -194,6 +195,7 @@ class ImageUtils { case ImageFormat.JPEG: case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: estimatedBytePerPixel = 0.3; break; case ImageFormat.Y8: @@ -262,6 +264,7 @@ class ImageUtils { case ImageFormat.RAW10: case ImageFormat.RAW12: case ImageFormat.RAW_DEPTH: + case ImageFormat.HEIC: return new Size(image.getWidth(), image.getHeight()); case ImageFormat.PRIVATE: return new Size(0, 0); diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index 1c6210e0c060..761b62588e5a 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -353,11 +353,6 @@ public class AudioMix { // no route flags set, use default as described in Builder.setRouteFlags(int) mRouteFlags = ROUTE_FLAG_LOOP_BACK; } - // can't do loop back AND render at same time in this implementation - if (mRouteFlags == (ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK)) { - throw new IllegalArgumentException("Unsupported route behavior combination 0x" + - Integer.toHexString(mRouteFlags)); - } if (mFormat == null) { // FIXME Can we eliminate this? Will AudioMix work with an unspecified sample rate? int rate = AudioSystem.getPrimaryOutputSamplingRate(); @@ -377,11 +372,11 @@ public class AudioMix { throw new IllegalArgumentException("Unsupported device on non-playback mix"); } } else { - if ((mRouteFlags & ROUTE_FLAG_RENDER) == ROUTE_FLAG_RENDER) { + if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_RENDER) { throw new IllegalArgumentException( "Can't have flag ROUTE_FLAG_RENDER without an audio device"); } - if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_LOOP_BACK) { + if ((mRouteFlags & ROUTE_FLAG_LOOP_BACK) == ROUTE_FLAG_LOOP_BACK) { if (mRule.getTargetMixType() == MIX_TYPE_PLAYERS) { mDeviceSystemType = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; } else if (mRule.getTargetMixType() == MIX_TYPE_RECORDERS) { diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 406f9dd94bb4..f07f1e8fb62b 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -153,8 +153,12 @@ JMediaCodec::JMediaCodec( if (nameIsType) { mCodec = MediaCodec::CreateByType(mLooper, name, encoder, &mInitStatus); + if (mCodec == nullptr || mCodec->getName(&mNameAtCreation) != OK) { + mNameAtCreation = "(null)"; + } } else { mCodec = MediaCodec::CreateByComponentName(mLooper, name, &mInitStatus); + mNameAtCreation = name; } CHECK((mCodec != NULL) != (mInitStatus != OK)); } @@ -699,9 +703,8 @@ status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const return err; } - // TODO: get alias ScopedLocalRef<jstring> nameObject(env, - env->NewStringUTF(codecInfo->getCodecName())); + env->NewStringUTF(mNameAtCreation.c_str())); ScopedLocalRef<jstring> canonicalNameObject(env, env->NewStringUTF(codecInfo->getCodecName())); diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index 0a53f1a0e268..de08550fa3db 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -155,6 +155,7 @@ private: sp<ALooper> mLooper; sp<MediaCodec> mCodec; + AString mNameAtCreation; sp<AMessage> mCallbackNotification; sp<AMessage> mOnFrameRenderedNotification; diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp index cf1494296756..6b8f7457eab9 100644 --- a/media/jni/android_media_MediaCodecList.cpp +++ b/media/jni/android_media_MediaCodecList.cpp @@ -24,6 +24,10 @@ #include <media/IMediaCodecList.h> #include <media/MediaCodecInfo.h> +#include <utils/Vector.h> + +#include <vector> + #include "android_runtime/AndroidRuntime.h" #include "jni.h" #include <nativehelper/JNIHelp.h> @@ -31,25 +35,91 @@ using namespace android; -static sp<IMediaCodecList> getCodecList(JNIEnv *env) { - sp<IMediaCodecList> mcl = MediaCodecList::getInstance(); - if (mcl == NULL) { - // This should never happen unless something is really wrong - jniThrowException( - env, "java/lang/RuntimeException", "cannot get MediaCodecList"); +/** + * This object unwraps codec aliases into individual codec infos as the Java interface handles + * aliases in this way. + */ +class JavaMediaCodecListWrapper { +public: + struct Info { + sp<MediaCodecInfo> info; + AString alias; + }; + + const Info getCodecInfo(size_t index) const { + if (index < mInfoList.size()) { + return mInfoList[index]; + } + // return + return Info { nullptr /* info */, "(none)" /* alias */ }; + } + + size_t countCodecs() const { + return mInfoList.size(); } - return mcl; + + sp<IMediaCodecList> getCodecList() const { + return mCodecList; + } + + size_t findCodecByName(AString name) const { + auto it = mInfoIndex.find(name); + return it == mInfoIndex.end() ? -ENOENT : it->second; + } + + JavaMediaCodecListWrapper(sp<IMediaCodecList> mcl) + : mCodecList(mcl) { + size_t numCodecs = mcl->countCodecs(); + for (size_t ix = 0; ix < numCodecs; ++ix) { + sp<MediaCodecInfo> info = mcl->getCodecInfo(ix); + Vector<AString> namesAndAliases; + info->getAliases(&namesAndAliases); + namesAndAliases.insertAt(0); + namesAndAliases.editItemAt(0) = info->getCodecName(); + for (const AString &nameOrAlias : namesAndAliases) { + if (mInfoIndex.count(nameOrAlias) > 0) { + // skip duplicate names or aliases + continue; + } + mInfoIndex.emplace(nameOrAlias, mInfoList.size()); + mInfoList.emplace_back(Info { info, nameOrAlias }); + } + } + } + +private: + sp<IMediaCodecList> mCodecList; + std::vector<Info> mInfoList; + std::map<AString, size_t> mInfoIndex; +}; + +static std::mutex sMutex; +static std::unique_ptr<JavaMediaCodecListWrapper> sListWrapper; + +static const JavaMediaCodecListWrapper *getCodecList(JNIEnv *env) { + std::lock_guard<std::mutex> lock(sMutex); + if (sListWrapper == nullptr) { + sp<IMediaCodecList> mcl = MediaCodecList::getInstance(); + if (mcl == NULL) { + // This should never happen unless something is really wrong + jniThrowException( + env, "java/lang/RuntimeException", "cannot get MediaCodecList"); + } + + sListWrapper.reset(new JavaMediaCodecListWrapper(mcl)); + } + return sListWrapper.get(); } -static sp<MediaCodecInfo> getCodecInfo(JNIEnv *env, jint index) { - sp<IMediaCodecList> mcl = getCodecList(env); - if (mcl == NULL) { +static JavaMediaCodecListWrapper::Info getCodecInfo(JNIEnv *env, jint index) { + const JavaMediaCodecListWrapper *mcl = getCodecList(env); + if (mcl == nullptr) { // Runtime exception already pending. - return NULL; + return JavaMediaCodecListWrapper::Info { nullptr /* info */, "(none)" /* alias */ }; } - sp<MediaCodecInfo> info = mcl->getCodecInfo(index); - if (info == NULL) { + JavaMediaCodecListWrapper::Info info = mcl->getCodecInfo(index); + if (info.info == NULL) { jniThrowException(env, "java/lang/IllegalArgumentException", NULL); } @@ -58,36 +128,36 @@ static sp<MediaCodecInfo> getCodecInfo(JNIEnv *env, jint index) { static jint android_media_MediaCodecList_getCodecCount( JNIEnv *env, jobject /* thiz */) { - sp<IMediaCodecList> mcl = getCodecList(env); + const JavaMediaCodecListWrapper *mcl = getCodecList(env); if (mcl == NULL) { // Runtime exception already pending. return 0; } + return mcl->countCodecs(); } static jstring android_media_MediaCodecList_getCodecName( JNIEnv *env, jobject /* thiz */, jint index) { - sp<MediaCodecInfo> info = getCodecInfo(env, index); - if (info == NULL) { + JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index); + if (info.info == NULL) { // Runtime exception already pending. return NULL; } - // TODO: support aliases - const char *name = info->getCodecName(); + const char *name = info.alias.c_str(); return env->NewStringUTF(name); } static jstring android_media_MediaCodecList_getCanonicalName( JNIEnv *env, jobject /* thiz */, jint index) { - sp<MediaCodecInfo> info = getCodecInfo(env, index); - if (info == NULL) { + JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index); + if (info.info == NULL) { // Runtime exception already pending. return NULL; } - const char *name = info->getCodecName(); + const char *name = info.info->getCodecName(); return env->NewStringUTF(name); } @@ -104,7 +174,7 @@ static jint android_media_MediaCodecList_findCodecByName( return -ENOENT; } - sp<IMediaCodecList> mcl = getCodecList(env); + const JavaMediaCodecListWrapper *mcl = getCodecList(env); if (mcl == NULL) { // Runtime exception already pending. env->ReleaseStringUTFChars(name, nameStr); @@ -118,25 +188,25 @@ static jint android_media_MediaCodecList_findCodecByName( static jboolean android_media_MediaCodecList_getAttributes( JNIEnv *env, jobject /* thiz */, jint index) { - sp<MediaCodecInfo> info = getCodecInfo(env, index); - if (info == NULL) { + JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index); + if (info.info == NULL) { // Runtime exception already pending. return 0; } - return info->getAttributes(); + return info.info->getAttributes(); } static jarray android_media_MediaCodecList_getSupportedTypes( JNIEnv *env, jobject /* thiz */, jint index) { - sp<MediaCodecInfo> info = getCodecInfo(env, index); - if (info == NULL) { + JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index); + if (info.info == NULL) { // Runtime exception already pending. return NULL; } Vector<AString> types; - info->getSupportedMediaTypes(&types); + info.info->getSupportedMediaTypes(&types); jclass clazz = env->FindClass("java/lang/String"); CHECK(clazz != NULL); @@ -160,8 +230,8 @@ static jobject android_media_MediaCodecList_getCodecCapabilities( return NULL; } - sp<MediaCodecInfo> info = getCodecInfo(env, index); - if (info == NULL) { + JavaMediaCodecListWrapper::Info info = getCodecInfo(env, index); + if (info.info == NULL) { // Runtime exception already pending. return NULL; } @@ -181,7 +251,7 @@ static jobject android_media_MediaCodecList_getCodecCapabilities( // TODO query default-format also from codec/codec list const sp<MediaCodecInfo::Capabilities> &capabilities = - info->getCapabilitiesFor(typeStr); + info.info->getCapabilitiesFor(typeStr); env->ReleaseStringUTFChars(type, typeStr); typeStr = NULL; if (capabilities == NULL) { @@ -192,7 +262,7 @@ static jobject android_media_MediaCodecList_getCodecCapabilities( capabilities->getSupportedColorFormats(&colorFormats); capabilities->getSupportedProfileLevels(&profileLevels); sp<AMessage> details = capabilities->getDetails(); - bool isEncoder = info->isEncoder(); + bool isEncoder = info.info->isEncoder(); jobject defaultFormatObj = NULL; if (ConvertMessageToMap(env, defaultFormat, &defaultFormatObj)) { @@ -267,13 +337,13 @@ static jobject android_media_MediaCodecList_getCodecCapabilities( } static jobject android_media_MediaCodecList_getGlobalSettings(JNIEnv *env, jobject /* thiz */) { - sp<IMediaCodecList> mcl = getCodecList(env); + const JavaMediaCodecListWrapper *mcl = getCodecList(env); if (mcl == NULL) { // Runtime exception already pending. return NULL; } - const sp<AMessage> settings = mcl->getGlobalSettings(); + const sp<AMessage> settings = mcl->getCodecList()->getGlobalSettings(); if (settings == NULL) { jniThrowException(env, "java/lang/RuntimeException", "cannot get global settings"); return NULL; diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp index 458d8471dafd..01baadb2f024 100644 --- a/media/jni/android_media_Utils.cpp +++ b/media/jni/android_media_Utils.cpp @@ -29,6 +29,9 @@ #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) +// Must be in sync with the value in HeicCompositeStream.cpp +#define CAMERA3_HEIC_BLOB_ID 0x00FE + namespace android { AssetStream::AssetStream(SkStream* stream) @@ -609,34 +612,35 @@ bool isPossiblyYUV(PixelFormat format) { } } -uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride) { +uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) { ALOGV("%s", __FUNCTION__); LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!"); uint32_t size = 0; uint32_t width = buffer->width; - uint8_t* jpegBuffer = buffer->data; + uint8_t* blobBuffer = buffer->data; if (usingRGBAOverride) { width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4; } - // First check for JPEG transport header at the end of the buffer - uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob)); + // First check for BLOB transport header at the end of the buffer + uint8_t* header = blobBuffer + (width - sizeof(struct camera3_jpeg_blob)); struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header); - if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) { + if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID || + blob->jpeg_blob_id == CAMERA3_HEIC_BLOB_ID) { size = blob->jpeg_size; - ALOGV("%s: Jpeg size = %d", __FUNCTION__, size); + ALOGV("%s: Jpeg/Heic size = %d", __FUNCTION__, size); } // failed to find size, default to whole buffer if (size == 0) { /* - * This is a problem because not including the JPEG header - * means that in certain rare situations a regular JPEG blob + * This is a problem because not including the JPEG/BLOB header + * means that in certain rare situations a regular JPEG/HEIC blob * will be mis-identified as having a header, in which case * we will get a garbage size value. */ - ALOGW("%s: No JPEG header detected, defaulting to size=width=%d", + ALOGW("%s: No JPEG/HEIC header detected, defaulting to size=width=%d", __FUNCTION__, width); size = width; } @@ -760,7 +764,7 @@ status_t getLockedImageInfo(LockedImage* buffer, int idx, pData = buffer->data; - dataSize = Image_getJpegSize(buffer, usingRGBAOverride); + dataSize = Image_getBlobSize(buffer, usingRGBAOverride); pStride = 0; rStride = 0; break; diff --git a/media/jni/android_media_Utils.h b/media/jni/android_media_Utils.h index 821c6b25c333..19c1b88f78e8 100644 --- a/media/jni/android_media_Utils.h +++ b/media/jni/android_media_Utils.h @@ -119,7 +119,7 @@ bool usingRGBAToJpegOverride(int32_t imageFormat, int32_t containerFormat); int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat); -uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride); +uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride); bool isFormatOpaque(int format); diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java index dbffa6d6bcf2..0d6d080b6dc2 100644 --- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java +++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java @@ -61,6 +61,7 @@ import android.net.util.SharedLog; import android.net.util.Stopwatch; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.os.Bundle; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; @@ -674,11 +675,11 @@ public class NetworkMonitor extends StateMachine { public boolean processMessage(Message message) { switch (message.what) { case CMD_LAUNCH_CAPTIVE_PORTAL_APP: - final Intent intent = new Intent( - ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN); + final Bundle appExtras = new Bundle(); // OneAddressPerFamilyNetwork is not parcelable across processes. - intent.putExtra(ConnectivityManager.EXTRA_NETWORK, new Network(mNetwork)); - intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL, + appExtras.putParcelable( + ConnectivityManager.EXTRA_NETWORK, new Network(mNetwork)); + appExtras.putParcelable(ConnectivityManager.EXTRA_CAPTIVE_PORTAL, new CaptivePortal(new ICaptivePortal.Stub() { @Override public void appResponse(int response) { @@ -700,16 +701,14 @@ public class NetworkMonitor extends StateMachine { } })); final CaptivePortalProbeResult probeRes = mLastPortalProbeResult; - intent.putExtra(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl); + appExtras.putString(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl); if (probeRes.probeSpec != null) { final String encodedSpec = probeRes.probeSpec.getEncodedSpec(); - intent.putExtra(EXTRA_CAPTIVE_PORTAL_PROBE_SPEC, encodedSpec); + appExtras.putString(EXTRA_CAPTIVE_PORTAL_PROBE_SPEC, encodedSpec); } - intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT, + appExtras.putString(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT, mCaptivePortalUserAgent); - intent.setFlags( - Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); - mContext.startActivityAsUser(intent, UserHandle.CURRENT); + mCm.startCaptivePortalApp(appExtras); return HANDLED; default: return NOT_HANDLED; diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml index 478ee54b40e5..cd6abb267e44 100644 --- a/packages/PrintSpooler/AndroidManifest.xml +++ b/packages/PrintSpooler/AndroidManifest.xml @@ -37,16 +37,8 @@ <uses-permission android:name="android.permission.READ_PRINT_SERVICES" /> <uses-permission android:name="android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" - android:dataSentOffDevice="no" - android:dataSharedWithThirdParty="no" - android:dataUsedForMonetization="no" - android:dataRetentionTime="unlimited"/> - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" - android:dataSentOffDevice="no" - android:dataSharedWithThirdParty="no" - android:dataUsedForMonetization="no" - android:dataRetentionTime="unlimited"/> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowClearUserData="true" diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index fad93cbf83da..6152b8cbd562 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -457,6 +457,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.DEBUG_VIEW_ATTRIBUTES, GlobalSettingsProto.Debug.VIEW_ATTRIBUTES); + dumpSetting(s, p, + Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, + GlobalSettingsProto.Debug.VIEW_ATTRIBUTES_APPLICATION_PACKAGE); p.end(debugToken); final long defaultToken = p.start(GlobalSettingsProto.DEFAULT); diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 866b46f732d8..3778a9c1cf83 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -22,11 +22,6 @@ android:sharedUserId="android.uid.systemui" coreApp="true"> - <!-- Using OpenGL ES 2.0 --> - <uses-feature - android:glEsVersion="0x00020000" - android:required="true" /> - <!-- SysUI must be the one to define this permission; its name is referenced by the core OS. --> <permission android:name="android.permission.systemui.IDENTITY" diff --git a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl deleted file mode 100644 index 11d73a93ad04..000000000000 --- a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl +++ /dev/null @@ -1,33 +0,0 @@ -precision mediump float; - -uniform sampler2D uTexture; -uniform float uCenterReveal; -uniform float uReveal; -uniform float uAod2Opacity; -uniform int uAodMode; -varying vec2 vTextureCoordinates; - -vec3 luminosity(vec3 color) { - float lum = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; - return vec3(lum); -} - -vec4 transform(vec3 diffuse) { - // TODO: Add well comments here, tracking on b/123615467. - vec3 lum = luminosity(diffuse); - diffuse = mix(diffuse, lum, smoothstep(0., uCenterReveal, uReveal)); - float val = mix(uReveal, uCenterReveal, step(uCenterReveal, uReveal)); - diffuse = smoothstep(val, 1.0, diffuse); - diffuse *= uAod2Opacity * (1. - smoothstep(uCenterReveal, 1., uReveal)); - return vec4(diffuse.r, diffuse.g, diffuse.b, 1.); -} - -void main() { - vec4 fragColor = texture2D(uTexture, vTextureCoordinates); - // TODO: Remove the branch logic here, tracking on b/123615467. - if (uAodMode != 0) { - gl_FragColor = transform(fragColor.rgb); - } else { - gl_FragColor = fragColor; - } -}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl deleted file mode 100644 index 4393e2bb0ebf..000000000000 --- a/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl +++ /dev/null @@ -1,8 +0,0 @@ -attribute vec4 aPosition; -attribute vec2 aTextureCoordinates; -varying vec2 vTextureCoordinates; - -void main() { - vTextureCoordinates = aTextureCoordinates; - gl_Position = aPosition; -}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index fece94e69a3d..c3f61eee4930 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -18,6 +18,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; import android.hardware.SensorPrivacyManager; +import android.hardware.display.NightDisplayListener; import android.os.Handler; import android.os.Looper; import android.util.ArrayMap; @@ -25,7 +26,6 @@ import android.util.DisplayMetrics; import android.view.IWindowManager; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.ColorDisplayController; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.Preconditions; @@ -206,7 +206,7 @@ public class Dependency extends SystemUI { @Inject Lazy<UserInfoController> mUserInfoController; @Inject Lazy<KeyguardMonitor> mKeyguardMonitor; @Inject Lazy<BatteryController> mBatteryController; - @Inject Lazy<ColorDisplayController> mColorDisplayController; + @Inject Lazy<NightDisplayListener> mNightDisplayListener; @Inject Lazy<ManagedProfileController> mManagedProfileController; @Inject Lazy<NextAlarmController> mNextAlarmController; @Inject Lazy<DataSaverController> mDataSaverController; @@ -330,7 +330,7 @@ public class Dependency extends SystemUI { mProviders.put(BatteryController.class, mBatteryController::get); - mProviders.put(ColorDisplayController.class, mColorDisplayController::get); + mProviders.put(NightDisplayListener.class, mNightDisplayListener::get); mProviders.put(ManagedProfileController.class, mManagedProfileController::get); diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java index 88e32cbeaa29..a517d7ce8e0e 100644 --- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java @@ -24,6 +24,7 @@ import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; import android.annotation.Nullable; import android.content.Context; import android.hardware.SensorPrivacyManager; +import android.hardware.display.NightDisplayListener; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -34,7 +35,6 @@ import android.util.DisplayMetrics; import android.view.IWindowManager; import android.view.WindowManagerGlobal; -import com.android.internal.app.ColorDisplayController; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.settingslib.bluetooth.LocalBluetoothManager; @@ -152,8 +152,8 @@ public class DependencyProvider { @Singleton @Provides - public ColorDisplayController provideColorDisplayController(Context context) { - return new ColorDisplayController(context); + public NightDisplayListener provideNightDisplayListener(Context context) { + return new NightDisplayListener(context); } @Singleton diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 50409421a68b..2aecc24e83c0 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -19,11 +19,8 @@ package com.android.systemui; import static android.view.Display.DEFAULT_DISPLAY; import android.app.WallpaperManager; -import android.content.BroadcastReceiver; import android.content.ComponentCallbacks2; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.RecordingCanvas; @@ -31,9 +28,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region.Op; import android.hardware.display.DisplayManager; -import android.opengl.GLSurfaceView; import android.os.AsyncTask; -import android.os.Build; import android.os.Handler; import android.os.Trace; import android.service.wallpaper.WallpaperService; @@ -44,7 +39,6 @@ import android.view.Surface; import android.view.SurfaceHolder; import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.glwallpaper.ImageWallpaperRenderer; import java.io.FileDescriptor; import java.io.IOException; @@ -57,17 +51,12 @@ import java.io.PrintWriter; public class ImageWallpaper extends WallpaperService { private static final String TAG = "ImageWallpaper"; private static final String GL_LOG_TAG = "ImageWallpaperGL"; - // TODO: Testing purpose, need to remove later, b/123616712. - private static final String SENSOR_EVENT_AWAKE = "systemui.test.event.awake"; - // TODO: Testing purpose, need to remove later, b/123616712. - private static final String SENSOR_EVENT_SLEEP = "systemui.test.event.sleep"; private static final boolean DEBUG = false; private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu"; private static final long DELAY_FORGET_WALLPAPER = 5000; private WallpaperManager mWallpaperManager; private DrawableEngine mEngine; - private GLEngine mGlEngine; @Override public void onCreate() { @@ -84,112 +73,10 @@ public class ImageWallpaper extends WallpaperService { @Override public Engine onCreateEngine() { - mGlEngine = new GLEngine(this); - return mGlEngine; + mEngine = new DrawableEngine(); + return mEngine; } - class GLEngine extends Engine { - private GLWallpaperSurfaceView mWallpaperSurfaceView; - - GLEngine(Context context) { - mWallpaperSurfaceView = new GLWallpaperSurfaceView(context); - mWallpaperSurfaceView.setRenderer( - new ImageWallpaperRenderer(context, mWallpaperSurfaceView)); - mWallpaperSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - setOffsetNotificationsEnabled(true); - } - - @Override - public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) { - if (mWallpaperSurfaceView != null) { - mWallpaperSurfaceView.notifyAmbientModeChanged(inAmbientMode); - } - } - - @Override - public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, - float yOffsetStep, int xPixelOffset, int yPixelOffset) { - if (mWallpaperSurfaceView != null) { - mWallpaperSurfaceView.notifyOffsetsChanged(xOffset, yOffset); - } - } - - private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView { - private SensorEventListener mEventListener; - private WallpaperStatusListener mWallpaperChangedListener; - - // TODO: Testing purpose, need to remove later, b/123616712. - /** - * For testing only: adb shell am broadcast -a <INTENT> - */ - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent == null) { - return; - } - switch (intent.getAction()) { - case SENSOR_EVENT_AWAKE: - notifySensorEvents(true); - break; - case SENSOR_EVENT_SLEEP: - notifySensorEvents(false); - break; - } - } - }; - - GLWallpaperSurfaceView(Context context) { - super(context); - setEGLContextClientVersion(2); - // TODO: Testing purpose, need to remove later, b/123616712. - if (Build.IS_DEBUGGABLE) { - IntentFilter filter = new IntentFilter(); - filter.addAction(SENSOR_EVENT_AWAKE); - filter.addAction(SENSOR_EVENT_SLEEP); - registerReceiver(mReceiver, filter); - } - } - - @Override - public SurfaceHolder getHolder() { - return getSurfaceHolder(); - } - - @Override - public void setRenderer(Renderer renderer) { - super.setRenderer(renderer); - mEventListener = (SensorEventListener) renderer; - mWallpaperChangedListener = (WallpaperStatusListener) renderer; - } - - private void notifySensorEvents(boolean reach) { - if (mEventListener != null) { - mEventListener.onSensorEvent(reach); - } - } - - private void notifyAmbientModeChanged(boolean inAmbient) { - if (mWallpaperChangedListener != null) { - mWallpaperChangedListener.onAmbientModeChanged(inAmbient); - } - } - - private void notifyOffsetsChanged(float xOffset, float yOffset) { - if (mWallpaperChangedListener != null) { - mWallpaperChangedListener.onOffsetsChanged( - xOffset, yOffset, getHolder().getSurfaceFrame()); - } - } - - @Override - public void render() { - requestRender(); - } - } - } - - // TODO: Remove this engine, tracking on b/123617158. class DrawableEngine extends Engine { private final Runnable mUnloadWallpaperCallback = () -> { unloadWallpaper(false /* forgetSize */); @@ -677,46 +564,4 @@ public class ImageWallpaper extends WallpaperService { } } } - - /** - * A listener to trace sensor event. - */ - public interface SensorEventListener { - - /** - * Called back while sensor event comes. - * @param reach The status of sensor. - */ - void onSensorEvent(boolean reach); - } - - /** - * A listener to trace status of image wallpaper. - */ - public interface WallpaperStatusListener { - - /** - * Called back while ambient mode changes. - * @param inAmbientMode true if is in ambient mode, false otherwise. - */ - void onAmbientModeChanged(boolean inAmbientMode); - - /** - * Called back while wallpaper offsets. - * @param xOffset The offset portion along x. - * @param yOffset The offset portion along y. - */ - void onOffsetsChanged(float xOffset, float yOffset, Rect frame); - } - - /** - * An abstraction for view of GLRenderer. - */ - public interface ImageGLView { - - /** - * Ask the view to render. - */ - void render(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index d6a46a9e3458..6877f5ed6b26 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -16,6 +16,10 @@ package com.android.systemui.bubbles; +import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS; +import static android.util.StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING; +import static android.util.StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE; +import static android.util.StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; @@ -26,17 +30,16 @@ import static com.android.systemui.statusbar.notification.NotificationAlertingMa import android.annotation.Nullable; import android.app.INotificationManager; import android.app.Notification; -import android.app.NotificationChannel; import android.app.PendingIntent; import android.content.Context; 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.LayoutInflater; import android.view.ViewGroup; import android.view.WindowManager; @@ -427,11 +430,15 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe @Nullable private PendingIntent getValidBubbleIntent(NotificationEntry notif) { Notification notification = notif.notification.getNotification(); + String packageName = notif.notification.getPackageName(); Notification.BubbleMetadata data = notif.getBubbleMetadata(); - if (data != null && canLaunchInActivityView(data.getIntent())) { + if (data != null && canLaunchInActivityView(data.getIntent(), + true /* enable logging for bubbles */, packageName)) { return data.getIntent(); - } else if (shouldUseContentIntent(mContext) - && canLaunchInActivityView(notification.contentIntent)) { + } + if (shouldUseContentIntent(mContext) + && canLaunchInActivityView(notification.contentIntent, + false /* disable logging for notifications */, packageName)) { Log.d(TAG, "[addBubble " + notif.key + "]: No appOverlayIntent, using contentIntent."); return notification.contentIntent; @@ -442,16 +449,41 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe /** * Whether an intent is properly configured to display in an {@link android.app.ActivityView}. + * + * @param intent the pending intent of the bubble. + * @param enableLogging whether bubble developer error should be logged. + * @param packageName the notification package name for this bubble. + * @return */ - private boolean canLaunchInActivityView(PendingIntent intent) { + private boolean canLaunchInActivityView(PendingIntent intent, boolean enableLogging, + String packageName) { if (intent == null) { return false; } ActivityInfo info = intent.getIntent().resolveActivityInfo(mContext.getPackageManager(), 0); - return info != null - && ActivityInfo.isResizeableMode(info.resizeMode) - && (info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) != 0; + if (info == null) { + if (enableLogging) { + StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName, + BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING); + } + return false; + } + if (!ActivityInfo.isResizeableMode(info.resizeMode)) { + if (enableLogging) { + StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName, + BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE); + } + return false; + } + if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) { + if (enableLogging) { + StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName, + BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS); + } + return false; + } + return (info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) != 0; } /** diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java index 4557b4de4901..d06feedfd9aa 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java @@ -110,7 +110,8 @@ public class DozeService extends DreamService @Override public void requestWakeUp() { PowerManager pm = getSystemService(PowerManager.class); - pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:NODOZE"); + pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, + "com.android.systemui:NODOZE"); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java deleted file mode 100644 index d03b00bcfc85..000000000000 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.glwallpaper; - -import static android.opengl.GLES20.GL_FRAGMENT_SHADER; -import static android.opengl.GLES20.GL_VERTEX_SHADER; -import static android.opengl.GLES20.glAttachShader; -import static android.opengl.GLES20.glCompileShader; -import static android.opengl.GLES20.glCreateProgram; -import static android.opengl.GLES20.glCreateShader; -import static android.opengl.GLES20.glGetAttribLocation; -import static android.opengl.GLES20.glGetUniformLocation; -import static android.opengl.GLES20.glLinkProgram; -import static android.opengl.GLES20.glShaderSource; -import static android.opengl.GLES20.glUseProgram; - -import android.content.Context; -import android.content.res.Resources; -import android.util.Log; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * This class takes charge of linking shader codes and then return a handle for OpenGL ES program. - */ -class ImageGLProgram { - private static final String TAG = ImageGLProgram.class.getSimpleName(); - - private Context mContext; - private int mProgramHandle; - - ImageGLProgram(Context context) { - mContext = context.getApplicationContext(); - } - - private int loadShaderProgram(int vertexId, int fragmentId) { - final String vertexSrc = getShaderResource(vertexId); - final String fragmentSrc = getShaderResource(fragmentId); - final int vertexHandle = getShaderHandle(GL_VERTEX_SHADER, vertexSrc); - final int fragmentHandle = getShaderHandle(GL_FRAGMENT_SHADER, fragmentSrc); - return getProgramHandle(vertexHandle, fragmentHandle); - } - - private String getShaderResource(int shaderId) { - Resources res = mContext.getResources(); - StringBuilder code = new StringBuilder(); - - try (BufferedReader reader = new BufferedReader( - new InputStreamReader(res.openRawResource(shaderId)))) { - String nextLine; - while ((nextLine = reader.readLine()) != null) { - code.append(nextLine).append("\n"); - } - } catch (IOException | Resources.NotFoundException ex) { - Log.d(TAG, "Can not read the shader source", ex); - code = null; - } - - return code == null ? "" : code.toString(); - } - - private int getShaderHandle(int type, String src) { - final int shader = glCreateShader(type); - if (shader == 0) { - Log.d(TAG, "Create shader failed, type=" + type); - return 0; - } - glShaderSource(shader, src); - glCompileShader(shader); - return shader; - } - - private int getProgramHandle(int vertexHandle, int fragmentHandle) { - final int program = glCreateProgram(); - if (program == 0) { - Log.d(TAG, "Can not create OpenGL ES program"); - return 0; - } - - glAttachShader(program, vertexHandle); - glAttachShader(program, fragmentHandle); - glLinkProgram(program); - return program; - } - - boolean useGLProgram(int vertexResId, int fragmentResId) { - mProgramHandle = loadShaderProgram(vertexResId, fragmentResId); - glUseProgram(mProgramHandle); - return true; - } - - int getAttributeHandle(String name) { - return glGetAttribLocation(mProgramHandle, name); - } - - int getUniformHandle(String name) { - return glGetUniformLocation(mProgramHandle, name); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java deleted file mode 100644 index 4e07872c9456..000000000000 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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.glwallpaper; - -import static android.opengl.GLES20.GL_FLOAT; -import static android.opengl.GLES20.GL_LINEAR; -import static android.opengl.GLES20.GL_TEXTURE0; -import static android.opengl.GLES20.GL_TEXTURE_2D; -import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER; -import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER; -import static android.opengl.GLES20.GL_TRIANGLES; -import static android.opengl.GLES20.glActiveTexture; -import static android.opengl.GLES20.glBindTexture; -import static android.opengl.GLES20.glDrawArrays; -import static android.opengl.GLES20.glEnableVertexAttribArray; -import static android.opengl.GLES20.glGenTextures; -import static android.opengl.GLES20.glTexParameteri; -import static android.opengl.GLES20.glUniform1i; -import static android.opengl.GLES20.glVertexAttribPointer; - -import android.graphics.Bitmap; -import android.opengl.GLUtils; -import android.util.Log; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; - -/** - * This class takes charge of the geometry data like vertices and texture coordinates. - * It delivers these data to opengl runtime and triggers draw calls if necessary. - */ -class ImageGLWallpaper { - private static final String TAG = ImageGLWallpaper.class.getSimpleName(); - - static final String A_POSITION = "aPosition"; - static final String A_TEXTURE_COORDINATES = "aTextureCoordinates"; - static final String U_CENTER_REVEAL = "uCenterReveal"; - static final String U_REVEAL = "uReveal"; - static final String U_AOD2OPACITY = "uAod2Opacity"; - static final String U_TEXTURE = "uTexture"; - static final String U_AOD_MODE = "uAodMode"; - - private static final int HANDLE_UNDEFINED = -1; - private static final int POSITION_COMPONENT_COUNT = 2; - private static final int TEXTURE_COMPONENT_COUNT = 2; - private static final int BYTES_PER_FLOAT = 4; - - // Vertices to define the square with 2 triangles. - private static final float[] VERTICES = { - -1.0f, -1.0f, - +1.0f, -1.0f, - +1.0f, +1.0f, - +1.0f, +1.0f, - -1.0f, +1.0f, - -1.0f, -1.0f - }; - - // Texture coordinates that maps to vertices. - private static final float[] TEXTURES = { - 0f, 1f, - 1f, 1f, - 1f, 0f, - 1f, 0f, - 0f, 0f, - 0f, 1f - }; - - private final FloatBuffer mVertexBuffer; - private final FloatBuffer mTextureBuffer; - private final ImageGLProgram mProgram; - - private int mAttrPosition; - private int mAttrTextureCoordinates; - private int mUniAod2Opacity; - private int mUniAodMode; - private int mUniCenterReveal; - private int mUniReveal; - private int mUniTexture; - private int mTextureId; - - ImageGLWallpaper(ImageGLProgram program) { - mProgram = program; - - // Create an float array in opengles runtime (native) and put vertex data. - mVertexBuffer = ByteBuffer.allocateDirect(VERTICES.length * BYTES_PER_FLOAT) - .order(ByteOrder.nativeOrder()) - .asFloatBuffer(); - mVertexBuffer.put(VERTICES); - mVertexBuffer.position(0); - - // Create an float array in opengles runtime (native) and put texture data. - mTextureBuffer = ByteBuffer.allocateDirect(TEXTURES.length * BYTES_PER_FLOAT) - .order(ByteOrder.nativeOrder()) - .asFloatBuffer(); - mTextureBuffer.put(TEXTURES); - mTextureBuffer.position(0); - } - - void setup() { - setupAttributes(); - setupUniforms(); - } - - private void setupAttributes() { - mAttrPosition = mProgram.getAttributeHandle(A_POSITION); - mVertexBuffer.position(0); - glVertexAttribPointer(mAttrPosition, POSITION_COMPONENT_COUNT, GL_FLOAT, - false, 0, mVertexBuffer); - glEnableVertexAttribArray(mAttrPosition); - - mAttrTextureCoordinates = mProgram.getAttributeHandle(A_TEXTURE_COORDINATES); - mTextureBuffer.position(0); - glVertexAttribPointer(mAttrTextureCoordinates, TEXTURE_COMPONENT_COUNT, GL_FLOAT, - false, 0, mTextureBuffer); - glEnableVertexAttribArray(mAttrTextureCoordinates); - } - - private void setupUniforms() { - mUniAod2Opacity = mProgram.getUniformHandle(U_AOD2OPACITY); - mUniAodMode = mProgram.getUniformHandle(U_AOD_MODE); - mUniCenterReveal = mProgram.getUniformHandle(U_CENTER_REVEAL); - mUniReveal = mProgram.getUniformHandle(U_REVEAL); - mUniTexture = mProgram.getUniformHandle(U_TEXTURE); - } - - int getHandle(String name) { - switch (name) { - case A_POSITION: - return mAttrPosition; - case A_TEXTURE_COORDINATES: - return mAttrTextureCoordinates; - case U_AOD2OPACITY: - return mUniAod2Opacity; - case U_AOD_MODE: - return mUniAodMode; - case U_CENTER_REVEAL: - return mUniCenterReveal; - case U_REVEAL: - return mUniReveal; - case U_TEXTURE: - return mUniTexture; - default: - return HANDLE_UNDEFINED; - } - } - - void draw() { - glDrawArrays(GL_TRIANGLES, 0, VERTICES.length / 2); - } - - void setupTexture(Bitmap bitmap) { - final int[] tids = new int[1]; - - if (bitmap == null) { - Log.w(TAG, "setupTexture: invalid bitmap"); - return; - } - - // Generate one texture object and store the id in tids[0]. - glGenTextures(1, tids, 0); - if (tids[0] == 0) { - Log.w(TAG, "setupTexture: glGenTextures() failed"); - return; - } - - // Bind a named texture to a texturing target. - glBindTexture(GL_TEXTURE_2D, tids[0]); - // Load the bitmap data and copy it over into the texture object that is currently bound. - GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0); - // Use bilinear texture filtering when minification. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // Use bilinear texture filtering when magnification. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - mTextureId = tids[0]; - } - - void useTexture() { - // Set the active texture unit to texture unit 0. - glActiveTexture(GL_TEXTURE0); - // Bind the texture to this unit. - glBindTexture(GL_TEXTURE_2D, mTextureId); - // Let the texture sampler in fragment shader to read form this texture unit. - glUniform1i(mUniTexture, 0); - } - - void adjustTextureCoordinates(Bitmap bitmap, int surfaceWidth, int surfaceHeight, - float xOffset, float yOffset) { - if (bitmap == null) { - Log.d(TAG, "adjustTextureCoordinates: invalid bitmap"); - return; - } - - float ratioW = 1f; - float ratioH = 1f; - int bitmapWidth = bitmap.getWidth(); - int bitmapHeight = bitmap.getHeight(); - - boolean adjustWidth = bitmapWidth > surfaceWidth; - if (adjustWidth) { - ratioW = (float) surfaceWidth / bitmapWidth; - float referenceX = xOffset + ratioW > 1f ? 1f - ratioW : xOffset; - for (int i = 0; i < TEXTURES.length; i += 2) { - if (i == 2 || i == 4 || i == 6) { - TEXTURES[i] = Math.min(1f, referenceX + ratioW); - } else { - TEXTURES[i] = referenceX; - } - } - } - - boolean adjustHeight = bitmapHeight > surfaceHeight; - if (adjustHeight) { - ratioH = (float) surfaceHeight / bitmapHeight; - float referenceY = yOffset + ratioH > 1f ? 1f - ratioH : yOffset; - for (int i = 1; i < TEXTURES.length; i += 2) { - if (i == 1 || i == 3 || i == 11) { - TEXTURES[i] = Math.min(1f, referenceY + ratioH); - } else { - TEXTURES[i] = referenceY; - } - } - } - - if (adjustWidth || adjustHeight) { - mTextureBuffer.put(TEXTURES); - mTextureBuffer.position(0); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java deleted file mode 100644 index 477e7d7ebf72..000000000000 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.glwallpaper; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.os.AsyncTask; -import android.os.Handler; -import android.os.Handler.Callback; -import android.os.Message; -import android.util.Log; - -/** - * A helper class that computes histogram and percentile 85 from a bitmap. - * Percentile 85 will be computed each time the user picks a new image wallpaper. - */ -class ImageProcessHelper { - private static final String TAG = ImageProcessHelper.class.getSimpleName(); - private static final float DEFAULT_PER85 = 0.8f; - private static final int MSG_UPDATE_PER85 = 1; - - /** - * This color matrix will be applied to each pixel to get luminance from rgb by below formula: - * Luminance = .2126f * r + .7152f * g + .0722f * b. - */ - private static final float[] LUMINOSITY_MATRIX = new float[] { - .2126f, .0000f, .0000f, .0000f, .0000f, - .0000f, .7152f, .0000f, .0000f, .0000f, - .0000f, .0000f, .0722f, .0000f, .0000f, - .0000f, .0000f, .0000f, 1.000f, .0000f - }; - - private final Handler mHandler = new Handler(new Callback() { - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_PER85: - mPer85 = (float) msg.obj; - return true; - default: - return false; - } - } - }); - - private float mPer85 = DEFAULT_PER85; - - void startComputingPercentile85(Bitmap bitmap) { - new Per85ComputeTask(mHandler).execute(bitmap); - } - - float getPercentile85() { - return mPer85; - } - - private static class Per85ComputeTask extends AsyncTask<Bitmap, Void, Float> { - private Handler mUpdateHandler; - - Per85ComputeTask(Handler handler) { - super(handler); - mUpdateHandler = handler; - } - - @Override - protected Float doInBackground(Bitmap... bitmaps) { - Bitmap bitmap = bitmaps[0]; - if (bitmap != null) { - int[] histogram = processHistogram(bitmap); - return computePercentile85(bitmap, histogram); - } - Log.e(TAG, "Per85ComputeTask: Can't get bitmap"); - return DEFAULT_PER85; - } - - @Override - protected void onPostExecute(Float result) { - Message msg = mUpdateHandler.obtainMessage(MSG_UPDATE_PER85, result); - mUpdateHandler.sendMessage(msg); - } - - private int[] processHistogram(Bitmap bitmap) { - int width = bitmap.getWidth(); - int height = bitmap.getHeight(); - - Bitmap target = Bitmap.createBitmap(width, height, bitmap.getConfig()); - Canvas canvas = new Canvas(target); - ColorMatrix cm = new ColorMatrix(LUMINOSITY_MATRIX); - Paint paint = new Paint(); - paint.setColorFilter(new ColorMatrixColorFilter(cm)); - canvas.drawBitmap(bitmap, new Matrix(), paint); - - // TODO: Fine tune the performance here, tracking on b/123615079. - int[] histogram = new int[256]; - for (int row = 0; row < height; row++) { - for (int col = 0; col < width; col++) { - int pixel = target.getPixel(col, row); - int y = Color.red(pixel) + Color.green(pixel) + Color.blue(pixel); - histogram[y]++; - } - } - - return histogram; - } - - private float computePercentile85(Bitmap bitmap, int[] histogram) { - float per85 = DEFAULT_PER85; - int pixelCount = bitmap.getWidth() * bitmap.getHeight(); - float[] acc = new float[256]; - for (int i = 0; i < acc.length; i++) { - acc[i] = (float) histogram[i] / pixelCount; - float prev = i == 0 ? 0f : acc[i - 1]; - float next = acc[i]; - float idx = (float) (i + 1) / 255; - float sum = prev + next; - if (prev < 0.85f && sum >= 0.85f) { - per85 = idx; - } - if (i > 0) { - acc[i] += acc[i - 1]; - } - } - return per85; - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java deleted file mode 100644 index 787972c08e4a..000000000000 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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.glwallpaper; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ValueAnimator; - -import com.android.systemui.Interpolators; - -/** - * Use ValueAnimator and appropriate interpolator to control the progress of reveal transition. - * The transition will happen while getting awake and quit events. - */ -class ImageRevealHelper { - private static final String TAG = ImageRevealHelper.class.getSimpleName(); - private static final float MAX_REVEAL = 0f; - private static final float MIN_REVEAL = 1f; - private static final int REVEAL_DURATION = 1000; - - private final ValueAnimator mAnimator; - private final RevealStateListener mRevealListener; - private float mReveal = MIN_REVEAL; - private boolean mAwake = false; - - ImageRevealHelper(RevealStateListener listener) { - mRevealListener = listener; - mAnimator = ValueAnimator.ofFloat(); - mAnimator.setDuration(REVEAL_DURATION); - mAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); - mAnimator.addUpdateListener(animator -> { - mReveal = (float) animator.getAnimatedValue(); - if (mRevealListener != null) { - mRevealListener.onRevealStateChanged(); - } - }); - mAnimator.addListener(new AnimatorListenerAdapter() { - private boolean mIsCanceled; - - @Override - public void onAnimationCancel(Animator animation) { - mIsCanceled = true; - } - - @Override - public void onAnimationEnd(Animator animation) { - if (!mIsCanceled) { - mAwake = !mAwake; - } - mIsCanceled = false; - } - }); - } - - private void animate() { - mAnimator.cancel(); - mAnimator.setFloatValues(mReveal, !mAwake ? MIN_REVEAL : MAX_REVEAL); - mAnimator.start(); - } - - public float getReveal() { - return mReveal; - } - - public boolean isAwake() { - return mAwake; - } - - void updateAwake(boolean awake) { - mAwake = awake; - animate(); - } - - void sleep() { - mReveal = MIN_REVEAL; - mAwake = false; - } - - /** - * A listener to trace value changes of reveal. - */ - public interface RevealStateListener { - - /** - * Called back while reveal status changes. - */ - void onRevealStateChanged(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java deleted file mode 100644 index 8916b28f201a..000000000000 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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.glwallpaper; - -import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; -import static android.opengl.GLES20.glClear; -import static android.opengl.GLES20.glClearColor; -import static android.opengl.GLES20.glUniform1f; -import static android.opengl.GLES20.glUniform1i; -import static android.opengl.GLES20.glViewport; - -import android.app.WallpaperManager; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Rect; -import android.opengl.GLSurfaceView; -import android.util.Log; - -import com.android.systemui.ImageWallpaper; -import com.android.systemui.ImageWallpaper.ImageGLView; -import com.android.systemui.R; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -/** - * A GL renderer for image wallpaper. - */ -public class ImageWallpaperRenderer implements GLSurfaceView.Renderer, - ImageWallpaper.SensorEventListener, ImageWallpaper.WallpaperStatusListener, - ImageRevealHelper.RevealStateListener { - private static final String TAG = ImageWallpaperRenderer.class.getSimpleName(); - - private final WallpaperManager mWallpaperManager; - private final ImageGLProgram mProgram; - private final ImageGLWallpaper mWallpaper; - private final ImageProcessHelper mImageProcessHelper; - private final ImageRevealHelper mImageRevealHelper; - private final ImageGLView mGLView; - private boolean mIsInAmbientMode; - private float mXOffset = 0f; - private float mYOffset = 0f; - - public ImageWallpaperRenderer(Context context, ImageGLView glView) { - mWallpaperManager = context.getSystemService(WallpaperManager.class); - if (mWallpaperManager == null) { - Log.w(TAG, "WallpaperManager not available"); - } - - mProgram = new ImageGLProgram(context); - mWallpaper = new ImageGLWallpaper(mProgram); - mImageProcessHelper = new ImageProcessHelper(); - mImageRevealHelper = new ImageRevealHelper(this); - mGLView = glView; - - if (mWallpaperManager != null) { - // Compute per85 as transition threshold, this is an async work. - mImageProcessHelper.startComputingPercentile85(mWallpaperManager.getBitmap()); - } - } - - @Override - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - glClearColor(0f, 0f, 0f, 1.0f); - mProgram.useGLProgram( - R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader); - mWallpaper.setup(); - mWallpaper.setupTexture(mWallpaperManager.getBitmap()); - } - - @Override - public void onSurfaceChanged(GL10 gl, int width, int height) { - glViewport(0, 0, width, height); - mWallpaper.adjustTextureCoordinates(mWallpaperManager.getBitmap(), - width, height, mXOffset, mYOffset); - } - - @Override - public void onDrawFrame(GL10 gl) { - float threshold = mImageProcessHelper.getPercentile85(); - float reveal = mImageRevealHelper.getReveal(); - - glClear(GL_COLOR_BUFFER_BIT); - - glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), .25f); - glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_CENTER_REVEAL), threshold); - glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal); - glUniform1i(mWallpaper.getHandle(ImageGLWallpaper.U_AOD_MODE), mIsInAmbientMode ? 1 : 0); - - mWallpaper.useTexture(); - mWallpaper.draw(); - } - - @Override - public void onSensorEvent(boolean awake) { - mImageRevealHelper.updateAwake(awake); - } - - @Override - public void onAmbientModeChanged(boolean inAmbientMode) { - mIsInAmbientMode = inAmbientMode; - if (inAmbientMode) { - mImageRevealHelper.sleep(); - } - requestRender(); - } - - @Override - public void onOffsetsChanged(float xOffset, float yOffset, Rect frame) { - if (frame == null || mWallpaperManager == null - || (xOffset == mXOffset && yOffset == mYOffset)) { - return; - } - - Bitmap bitmap = mWallpaperManager.getBitmap(); - if (bitmap == null) { - return; - } - - int width = frame.width(); - int height = frame.height(); - mXOffset = xOffset; - mYOffset = yOffset; - - mWallpaper.adjustTextureCoordinates(bitmap, width, height, mXOffset, mYOffset); - requestRender(); - } - - @Override - public void onRevealStateChanged() { - requestRender(); - } - - private void requestRender() { - if (mGLView != null) { - mGLView.render(); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 4527f73ab118..66cfadf9d6e8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -884,6 +884,7 @@ public class KeyguardViewMediator extends SystemUI { // Just to make sure, make sure the device is awake. mContext.getSystemService(PowerManager.class).wakeUp(SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_CAMERA_LAUNCH, "com.android.systemui:CAMERA_GESTURE_PREVENT_LOCK"); mPendingLock = false; mPendingReset = false; @@ -1854,8 +1855,9 @@ public class KeyguardViewMediator extends SystemUI { // It's possible that the device was unlocked in a dream state. It's time to wake up. if (mAodShowing) { - PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:BOUNCER_DOZING"); + PowerManager pm = mContext.getSystemService(PowerManager.class); + pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, + "com.android.systemui:BOUNCER_DOZING"); } synchronized (KeyguardViewMediator.this) { diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt index fa1426e45142..cff7fe449be1 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt @@ -69,7 +69,7 @@ class OngoingPrivacyDialog constructor( setPositiveButton(R.string.ongoing_privacy_dialog_ok, null) setNeutralButton(R.string.ongoing_privacy_dialog_open_settings, object : DialogInterface.OnClickListener { - val intent = Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS).putExtra( + val intent = Intent(Settings.ACTION_PRIVACY_SETTINGS).putExtra( Intent.EXTRA_DURATION_MILLIS, TimeUnit.MINUTES.toMillis(1)) @Suppress("DEPRECATION") @@ -167,7 +167,7 @@ class OngoingPrivacyDialog constructor( // Check if package exists context.packageManager.getPackageInfo(app.packageName, 0) item.setOnClickListener(object : View.OnClickListener { - val intent = Intent(Intent.ACTION_REVIEW_APP_PERMISSION_USAGE) + val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS) .putExtra(Intent.EXTRA_PACKAGE_NAME, app.packageName) .putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(app.uid)) override fun onClick(v: View?) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java index de78d3376500..effa935c5c20 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Intent; import android.hardware.display.ColorDisplayManager; +import android.hardware.display.NightDisplayListener; import android.metrics.LogMaker; import android.provider.Settings; import android.service.quicksettings.Tile; @@ -31,7 +32,6 @@ import android.widget.Switch; import androidx.annotation.StringRes; -import com.android.internal.app.ColorDisplayController; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.plugins.qs.QSTile.BooleanState; @@ -46,8 +46,9 @@ import java.util.TimeZone; import javax.inject.Inject; -public class NightDisplayTile extends QSTileImpl<BooleanState> - implements ColorDisplayController.Callback { +/** Quick settings tile: Night display **/ +public class NightDisplayTile extends QSTileImpl<BooleanState> implements + NightDisplayListener.Callback { /** * Pattern for {@link java.time.format.DateTimeFormatter} used to approximate the time to the @@ -57,13 +58,15 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> private static final String PATTERN_HOUR_MINUTE = "h:mm a"; private static final String PATTERN_HOUR_NINUTE_24 = "HH:mm"; - private ColorDisplayController mController; + private final ColorDisplayManager mManager; + private NightDisplayListener mListener; private boolean mIsListening; @Inject public NightDisplayTile(QSHost host) { super(host); - mController = new ColorDisplayController(mContext, ActivityManager.getCurrentUser()); + mManager = mContext.getSystemService(ColorDisplayManager.class); + mListener = new NightDisplayListener(mContext, ActivityManager.getCurrentUser()); } @Override @@ -81,27 +84,27 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> // Enroll in forced auto mode if eligible. if ("1".equals(Settings.Global.getString(mContext.getContentResolver(), Settings.Global.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE)) - && mController.getAutoModeRaw() == -1) { - mController.setAutoMode(ColorDisplayManager.AUTO_MODE_CUSTOM_TIME); + && mManager.getNightDisplayAutoModeRaw() == -1) { + mManager.setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_CUSTOM_TIME); Log.i("NightDisplayTile", "Enrolled in forced night display auto mode"); } // Change current activation state. final boolean activated = !mState.value; - mController.setActivated(activated); + mManager.setNightDisplayActivated(activated); } @Override protected void handleUserSwitch(int newUserId) { // Stop listening to the old controller. if (mIsListening) { - mController.setListener(null); + mListener.setCallback(null); } // Make a new controller for the new user. - mController = new ColorDisplayController(mContext, newUserId); + mListener = new NightDisplayListener(mContext, newUserId); if (mIsListening) { - mController.setListener(this); + mListener.setCallback(this); } super.handleUserSwitch(newUserId); @@ -109,7 +112,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> @Override protected void handleUpdateState(BooleanState state, Object arg) { - state.value = mController.isActivated(); + state.value = mManager.isNightDisplayActivated(); state.label = mContext.getString(R.string.quick_settings_night_display_label); state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_night_display_on); state.expandedAccessibilityClassName = Switch.class.getName(); @@ -121,12 +124,12 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> } /** - * Returns a {@link String} for the secondary label that reflects when the light will be turned - * on or off based on the current auto mode and night light activated status. + * Returns a String for the secondary label that reflects when the light will be turned on or + * off based on the current auto mode and night light activated status. */ @Nullable private String getSecondaryLabel(boolean isNightLightActivated) { - switch(mController.getAutoMode()) { + switch (mManager.getNightDisplayAutoMode()) { case ColorDisplayManager.AUTO_MODE_TWILIGHT: // Auto mode related to sunrise & sunset. If the light is on, it's guaranteed to be // turned off at sunrise. If it's off, it's guaranteed to be turned on at sunset. @@ -143,10 +146,10 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> final DateTimeFormatter toggleTimeFormat; if (isNightLightActivated) { - toggleTime = mController.getCustomEndTime(); + toggleTime = mManager.getNightDisplayCustomEndTime(); toggleTimeStringRes = R.string.quick_settings_secondary_label_until; } else { - toggleTime = mController.getCustomStartTime(); + toggleTime = mManager.getNightDisplayCustomStartTime(); toggleTimeStringRes = R.string.quick_settings_night_secondary_label_on_at; } @@ -175,7 +178,8 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> @Override public LogMaker populate(LogMaker logMaker) { - return super.populate(logMaker).addTaggedData(FIELD_QS_MODE, mController.getAutoModeRaw()); + return super.populate(logMaker) + .addTaggedData(FIELD_QS_MODE, mManager.getNightDisplayAutoModeRaw()); } @Override @@ -187,10 +191,10 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> protected void handleSetListening(boolean listening) { mIsListening = listening; if (listening) { - mController.setListener(this); + mListener.setCallback(this); refreshState(); } else { - mController.setListener(null); + mListener.setCallback(null); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 491f310cedf2..b820dc09657a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -132,7 +132,8 @@ public class NotificationRemoteInputManager implements Dumpable { @Override public boolean onClickHandler( View view, PendingIntent pendingIntent, RemoteViews.RemoteResponse response) { - mShadeController.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view); + mShadeController.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view, + "NOTIFICATION_CLICK"); if (handleRemoteInput(view, pendingIntent)) { return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java index 49f1a8d6f248..b788f537316b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java @@ -52,7 +52,7 @@ public final class NotificationClicker implements View.OnClickListener { return; } - mShadeController.wakeUpIfDozing(SystemClock.uptimeMillis(), v); + mShadeController.wakeUpIfDozing(SystemClock.uptimeMillis(), v, "NOTIFICATION_CLICK"); final ExpandableNotificationRow row = (ExpandableNotificationRow) v; final StatusBarNotification sbn = row.getStatusBarNotification(); 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 b6948fc4bd1f..c7b2fab54fff 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 @@ -537,7 +537,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G mChosenImportance = IMPORTANCE_LOW; confirmationText.setText(R.string.notification_channel_silenced); } else { - mChosenImportance = IMPORTANCE_HIGH; + mChosenImportance = IMPORTANCE_DEFAULT; confirmationText.setText(R.string.notification_channel_unsilenced); } break; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java index b96c55b37c48..c9be2c8f6703 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java @@ -16,11 +16,11 @@ package com.android.systemui.statusbar.phone; import android.content.Context; import android.hardware.display.ColorDisplayManager; +import android.hardware.display.NightDisplayListener; import android.os.Handler; import android.provider.Settings.Secure; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.ColorDisplayController; import com.android.systemui.Dependency; import com.android.systemui.qs.AutoAddTracker; import com.android.systemui.qs.QSTileHost; @@ -50,7 +50,7 @@ public class AutoTileManager { private final HotspotController mHotspotController; private final DataSaverController mDataSaverController; private final ManagedProfileController mManagedProfileController; - private final ColorDisplayController mColorDisplayController; + private final NightDisplayListener mNightDisplayListener; @Inject public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host, @@ -58,7 +58,7 @@ public class AutoTileManager { HotspotController hotspotController, DataSaverController dataSaverController, ManagedProfileController managedProfileController, - ColorDisplayController colorDisplayController) { + NightDisplayListener nightDisplayListener) { mAutoTracker = autoAddTracker; mContext = context; mHost = host; @@ -66,7 +66,7 @@ public class AutoTileManager { mHotspotController = hotspotController; mDataSaverController = dataSaverController; mManagedProfileController = managedProfileController; - mColorDisplayController = colorDisplayController; + mNightDisplayListener = nightDisplayListener; if (!mAutoTracker.isAdded(HOTSPOT)) { hotspotController.addCallback(mHotspotCallback); } @@ -93,7 +93,7 @@ public class AutoTileManager { } if (!mAutoTracker.isAdded(NIGHT) && ColorDisplayManager.isNightDisplayAvailable(mContext)) { - colorDisplayController.setListener(mColorDisplayCallback); + nightDisplayListener.setCallback(mNightDisplayCallback); } } @@ -106,7 +106,7 @@ public class AutoTileManager { mDataSaverController.removeCallback(mDataSaverListener); mManagedProfileController.removeCallback(mProfileCallback); if (ColorDisplayManager.isNightDisplayAvailable(mContext)) { - mColorDisplayController.setListener(null); + mNightDisplayListener.setCallback(null); } } @@ -157,8 +157,8 @@ public class AutoTileManager { }; @VisibleForTesting - final ColorDisplayController.Callback mColorDisplayCallback = - new ColorDisplayController.Callback() { + final NightDisplayListener.Callback mNightDisplayCallback = + new NightDisplayListener.Callback() { @Override public void onActivated(boolean activated) { if (activated) { @@ -178,7 +178,7 @@ public class AutoTileManager { if (mAutoTracker.isAdded(NIGHT)) return; mHost.addTile(NIGHT); mAutoTracker.setTileAdded(NIGHT); - mHandler.post(() -> mColorDisplayController.setListener(null)); + mHandler.post(() -> mNightDisplayListener.setCallback(null)); } }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 304d2ee70c35..2162ea70fe84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -232,7 +232,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { if (DEBUG_BIO_WAKELOCK) { Log.i(TAG, "bio wakelock: Authenticated, waking up..."); } - mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:BIOMETRIC"); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, + "android.policy:BIOMETRIC"); } if (delayWakeUp) { mKeyguardViewMediator.onWakeAndUnlocking(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java index f9262186968f..234a968e9f75 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java @@ -14,6 +14,7 @@ package com.android.systemui.statusbar.phone; +import android.annotation.NonNull; import android.view.View; import com.android.systemui.statusbar.StatusBarState; @@ -96,8 +97,9 @@ public interface ShadeController { * * @param time when to wake up * @param view the view requesting the wakeup + * @param why the reason for the wake up */ - void wakeUpIfDozing(long time, View view); + void wakeUpIfDozing(long time, View view, @NonNull String why); /** * If secure with redaction: Show bouncer, go to unlocked shade. 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 3532af560557..37a0610d4de5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -482,7 +482,8 @@ public class StatusBar extends SystemUI implements DemoMode, updateAodMaskVisibility(deviceSupportsAodWallpaper && aodImageWallpaperEnabled); // If WallpaperInfo is null, it must be ImageWallpaper. final boolean supportsAmbientMode = deviceSupportsAodWallpaper - && (info == null || info.supportsAmbientMode()); + && (info == null && aodImageWallpaperEnabled + || info != null && info.supportsAmbientMode()); mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode); mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode); @@ -551,7 +552,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final View.OnClickListener mGoToLockedShadeListener = v -> { if (mState == StatusBarState.KEYGUARD) { - wakeUpIfDozing(SystemClock.uptimeMillis(), v); + wakeUpIfDozing(SystemClock.uptimeMillis(), v, "SHADE_CLICK"); goToLockedShade(null); } }; @@ -1090,10 +1091,10 @@ public class StatusBar extends SystemUI implements DemoMode, } @Override - public void wakeUpIfDozing(long time, View where) { + public void wakeUpIfDozing(long time, View where, String why) { if (mDozing) { - PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - pm.wakeUp(time, "com.android.systemui:NODOZE"); + PowerManager pm = mContext.getSystemService(PowerManager.class); + pm.wakeUp(time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why); mWakeUpComingFromTouch = true; where.getLocationInWindow(mTmpInt2); mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, @@ -3729,7 +3730,8 @@ public class StatusBar extends SystemUI implements DemoMode, } if (!mDeviceInteractive) { PowerManager pm = mContext.getSystemService(PowerManager.class); - pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE"); + pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH, + "com.android.systemui:CAMERA_GESTURE"); mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); } vibrateForCameraGesture(); @@ -3890,7 +3892,8 @@ public class StatusBar extends SystemUI implements DemoMode, public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { mScrimController.setPulseReason(reason); if (reason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS) { - mPowerManager.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:NODOZE"); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, + "com.android.systemui:LONG_PRESS"); startAssist(new Bundle()); return; } 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 8b25c3469abe..c39e17266b56 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -112,7 +112,7 @@ public class StatusBarWindowView extends FrameLayout { mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); mFalsingManager = FalsingManager.getInstance(context); mDoubleTapHelper = new DoubleTapHelper(this, active -> {}, () -> { - mService.wakeUpIfDozing(SystemClock.uptimeMillis(), this); + mService.wakeUpIfDozing(SystemClock.uptimeMillis(), this, "DOUBLE_TAP"); return true; }, null, null); } diff --git a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java index dd1d0ca06fa8..52cabe278e2d 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java +++ b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java @@ -156,8 +156,6 @@ public class AodMaskView extends ImageView implements StatusBarStateController.S private boolean checkIfNeedMask() { // We need mask for ImageWallpaper / LockScreen Wallpaper (Music album art). - // Because of conflicting with another wallpaper feature, - // we only support LockScreen wallpaper currently. return mWallpaperManager.getWallpaperInfo() == null || ScrimState.AOD.hasBackdrop(); } 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 2a64445f342a..105bd9dd8793 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 @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.row; import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; -import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.app.NotificationManager.IMPORTANCE_NONE; @@ -1067,7 +1066,7 @@ public class NotificationInfoTest extends SysuiTestCase { anyString(), eq(TEST_UID), updated.capture()); assertTrue((updated.getValue().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); - assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance()); + assertEquals(IMPORTANCE_DEFAULT, updated.getValue().getImportance()); } @Test @@ -1111,7 +1110,7 @@ public class NotificationInfoTest extends SysuiTestCase { anyString(), eq(TEST_UID), updated.capture()); assertTrue((updated.getValue().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); - assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance()); + assertEquals(IMPORTANCE_DEFAULT, updated.getValue().getImportance()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java index 1ded835e9651..f3740c4d51d0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java @@ -21,13 +21,13 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.hardware.display.ColorDisplayManager; +import android.hardware.display.NightDisplayListener; import android.os.Handler; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; -import com.android.internal.app.ColorDisplayController; import com.android.systemui.SysuiTestCase; import com.android.systemui.qs.AutoAddTracker; import com.android.systemui.qs.QSTileHost; @@ -58,7 +58,7 @@ public class AutoTileManagerTest extends SysuiTestCase { mock(HotspotController.class), mock(DataSaverController.class), mock(ManagedProfileController.class), - mock(ColorDisplayController.class)); + mock(NightDisplayListener.class)); } @Test @@ -66,7 +66,7 @@ public class AutoTileManagerTest extends SysuiTestCase { if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { return; } - mAutoTileManager.mColorDisplayCallback.onActivated(true); + mAutoTileManager.mNightDisplayCallback.onActivated(true); verify(mQsTileHost).addTile("night"); } @@ -75,7 +75,7 @@ public class AutoTileManagerTest extends SysuiTestCase { if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { return; } - mAutoTileManager.mColorDisplayCallback.onActivated(false); + mAutoTileManager.mNightDisplayCallback.onActivated(false); verify(mQsTileHost, never()).addTile("night"); } @@ -84,7 +84,7 @@ public class AutoTileManagerTest extends SysuiTestCase { if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { return; } - mAutoTileManager.mColorDisplayCallback.onAutoModeChanged( + mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( ColorDisplayManager.AUTO_MODE_TWILIGHT); verify(mQsTileHost).addTile("night"); } @@ -94,7 +94,7 @@ public class AutoTileManagerTest extends SysuiTestCase { if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { return; } - mAutoTileManager.mColorDisplayCallback.onAutoModeChanged( + mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( ColorDisplayManager.AUTO_MODE_CUSTOM_TIME); verify(mQsTileHost).addTile("night"); } @@ -104,7 +104,7 @@ public class AutoTileManagerTest extends SysuiTestCase { if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { return; } - mAutoTileManager.mColorDisplayCallback.onAutoModeChanged( + mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( ColorDisplayManager.AUTO_MODE_DISABLED); verify(mQsTileHost, never()).addTile("night"); } diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk index b8a57ae7b98f..1294dbbbfa87 100644 --- a/packages/overlays/Android.mk +++ b/packages/overlays/Android.mk @@ -16,17 +16,13 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := frameworks-base-overlays - LOCAL_REQUIRED_MODULES := \ - ExperimentNavigationBarFloatingOverlay \ - ExperimentNavigationBarDefaultOverlay \ - ExperimentNavigationBarSlimOverlay32 \ - ExperimentNavigationBarSlimOverlay40 \ - ExperimentNavigationBarLargeOverlay56 \ - ExperimentNavigationBarLargeOverlay64 \ AccentColorBlackOverlay \ AccentColorGreenOverlay \ AccentColorPurpleOverlay \ + DisplayCutoutEmulationCornerOverlay \ + DisplayCutoutEmulationDoubleOverlay \ + DisplayCutoutEmulationTallOverlay \ FontNotoSerifSourceOverlay \ IconPackCircularAndroidOverlay \ IconPackCircularSettingsOverlay \ @@ -42,7 +38,17 @@ LOCAL_REQUIRED_MODULES := \ IconShapeSquircleOverlay \ IconShapeTeardropOverlay - include $(BUILD_PHONY_PACKAGE) +include $(CLEAR_VARS) +LOCAL_MODULE := frameworks-base-overlays-debug +LOCAL_REQUIRED_MODULES := \ + ExperimentNavigationBarFloatingOverlay \ + ExperimentNavigationBarDefaultOverlay \ + ExperimentNavigationBarSlimOverlay32 \ + ExperimentNavigationBarSlimOverlay40 \ + ExperimentNavigationBarLargeOverlay56 \ + ExperimentNavigationBarLargeOverlay64 + +include $(BUILD_PHONY_PACKAGE) include $(call first-makefiles-under,$(LOCAL_PATH)) diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 8886ee2365c0..1bce11ee95de 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -180,7 +180,7 @@ final class AutofillManagerServiceImpl mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(master.getContext(), com.android.internal.R.string.config_defaultAugmentedAutofillService); mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback( - (u, s) -> updateRemoteAugmentedAutofillService()); + (u, s) -> updateRemoteAugmentedAutofillService(s)); updateLocked(disabled); } @@ -1048,8 +1048,12 @@ final class AutofillManagerServiceImpl componentName, mUserId, new RemoteAugmentedAutofillServiceCallbacks() { @Override public void onServiceDied(@NonNull RemoteAugmentedAutofillService service) { - // TODO(b/123100811): properly implement Slog.w(TAG, "remote augmented autofill service died"); + final RemoteAugmentedAutofillService remoteService = + mRemoteAugmentedAutofillService; + if (remoteService != null) { + remoteService.destroy(); + } } }, mMaster.isInstantServiceAllowed(), mMaster.verbose); } @@ -1060,8 +1064,7 @@ final class AutofillManagerServiceImpl /** * Called when the {@link #mAugmentedAutofillResolver} changed (among other places). */ - private void updateRemoteAugmentedAutofillService() { - final String serviceName = mAugmentedAutofillResolver.getServiceName(mUserId); + private void updateRemoteAugmentedAutofillService(@Nullable String serviceName) { if (serviceName == null) { if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!"); if (mRemoteAugmentedAutofillService != null) { diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 194332ab8451..04fc2588134e 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -2595,8 +2595,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final int mode; if ((supportedModes & FLAG_SMART_SUGGESTION_SYSTEM) != 0) { mode = FLAG_SMART_SUGGESTION_SYSTEM; - } else if ((supportedModes & AutofillManager.FLAG_SMART_SUGGESTION_LEGACY) != 0) { - mode = AutofillManager.FLAG_SMART_SUGGESTION_LEGACY; } else { Slog.w(TAG, "Unsupported Smart Suggestion mode: " + supportedModes); return null; diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/ByteRange.java b/services/backup/java/com/android/server/backup/encryption/chunking/ByteRange.java new file mode 100644 index 000000000000..004d9e3b45f1 --- /dev/null +++ b/services/backup/java/com/android/server/backup/encryption/chunking/ByteRange.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.chunking; + +import com.android.internal.util.Preconditions; + +/** Representation of a range of bytes to be downloaded. */ +final class ByteRange { + private final long mStart; + private final long mEnd; + + /** Creates a range of bytes which includes {@code mStart} and {@code mEnd}. */ + ByteRange(long start, long end) { + Preconditions.checkArgument(start >= 0); + Preconditions.checkArgument(end >= start); + mStart = start; + mEnd = end; + } + + /** Returns the start of the {@code ByteRange}. The start is included in the range. */ + long getStart() { + return mStart; + } + + /** Returns the end of the {@code ByteRange}. The end is included in the range. */ + long getEnd() { + return mEnd; + } + + /** Returns the number of bytes included in the {@code ByteRange}. */ + int getLength() { + return (int) (mEnd - mStart + 1); + } + + /** Creates a new {@link ByteRange} from {@code mStart} to {@code mEnd + length}. */ + ByteRange extend(long length) { + Preconditions.checkArgument(length > 0); + return new ByteRange(mStart, mEnd + length); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ByteRange)) { + return false; + } + + ByteRange byteRange = (ByteRange) o; + return (mEnd == byteRange.mEnd && mStart == byteRange.mStart); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + (int) (mStart ^ (mStart >>> 32)); + result = 31 * result + (int) (mEnd ^ (mEnd >>> 32)); + return result; + } + + @Override + public String toString() { + return String.format("ByteRange{mStart=%d, mEnd=%d}", mStart, mEnd); + } +} diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptBackupWriter.java b/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptBackupWriter.java new file mode 100644 index 000000000000..69fb5cbf606d --- /dev/null +++ b/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptBackupWriter.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.chunking; + +import com.android.internal.annotations.VisibleForTesting; + +import java.io.IOException; +import java.io.OutputStream; + +/** Writes backup data to a diff script, using a {@link SingleStreamDiffScriptWriter}. */ +public class DiffScriptBackupWriter implements BackupWriter { + /** + * The maximum size of a chunk in the diff script. The diff script writer {@code mWriter} will + * buffer this many bytes in memory. + */ + private static final int ENCRYPTION_DIFF_SCRIPT_MAX_CHUNK_SIZE_BYTES = 1024 * 1024; + + private final SingleStreamDiffScriptWriter mWriter; + private long mBytesWritten; + + /** + * Constructs a new writer which writes the diff script to the given output stream, using the + * maximum new chunk size {@code ENCRYPTION_DIFF_SCRIPT_MAX_CHUNK_SIZE_BYTES}. + */ + public static DiffScriptBackupWriter newInstance(OutputStream outputStream) { + SingleStreamDiffScriptWriter writer = + new SingleStreamDiffScriptWriter( + outputStream, ENCRYPTION_DIFF_SCRIPT_MAX_CHUNK_SIZE_BYTES); + return new DiffScriptBackupWriter(writer); + } + + @VisibleForTesting + DiffScriptBackupWriter(SingleStreamDiffScriptWriter writer) { + mWriter = writer; + } + + @Override + public void writeBytes(byte[] bytes) throws IOException { + for (byte b : bytes) { + mWriter.writeByte(b); + } + + mBytesWritten += bytes.length; + } + + @Override + public void writeChunk(long start, int length) throws IOException { + mWriter.writeChunk(start, length); + mBytesWritten += length; + } + + @Override + public long getBytesWritten() { + return mBytesWritten; + } + + @Override + public void flush() throws IOException { + mWriter.flush(); + } +} diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptWriter.java b/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptWriter.java new file mode 100644 index 000000000000..49d15712d4cc --- /dev/null +++ b/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptWriter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.chunking; + +import java.io.IOException; +import java.io.OutputStream; + +/** Writer that formats a Diff Script and writes it to an output source. */ +interface DiffScriptWriter { + /** Adds a new byte to the diff script. */ + void writeByte(byte b) throws IOException; + + /** Adds a known chunk to the diff script. */ + void writeChunk(long chunkStart, int chunkLength) throws IOException; + + /** Indicates that no more bytes or chunks will be added to the diff script. */ + void flush() throws IOException; + + interface Factory { + DiffScriptWriter create(OutputStream outputStream); + } +} diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/OutputStreamWrapper.java b/services/backup/java/com/android/server/backup/encryption/chunking/OutputStreamWrapper.java new file mode 100644 index 000000000000..4aea60121810 --- /dev/null +++ b/services/backup/java/com/android/server/backup/encryption/chunking/OutputStreamWrapper.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.chunking; + +import java.io.OutputStream; + +/** An interface that wraps one {@link OutputStream} with another for filtration purposes. */ +public interface OutputStreamWrapper { + /** Wraps a given {@link OutputStream}. */ + OutputStream wrap(OutputStream outputStream); +} diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriter.java b/services/backup/java/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriter.java new file mode 100644 index 000000000000..0e4bd58345d5 --- /dev/null +++ b/services/backup/java/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriter.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.chunking; + +import android.annotation.Nullable; + +import com.android.internal.util.Preconditions; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.Locale; + +/** + * A {@link DiffScriptWriter} that writes an entire diff script to a single {@link OutputStream}. + */ +public class SingleStreamDiffScriptWriter implements DiffScriptWriter { + static final byte LINE_SEPARATOR = 0xA; + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + private final int mMaxNewByteChunkSize; + private final OutputStream mOutputStream; + private final byte[] mByteBuffer; + private int mBufferSize = 0; + // Each chunk could be written immediately to the output stream. However, + // it is possible that chunks may overlap. We therefore cache the most recent + // reusable chunk and try to merge it with future chunks. + private ByteRange mReusableChunk; + + public SingleStreamDiffScriptWriter(OutputStream outputStream, int maxNewByteChunkSize) { + mOutputStream = outputStream; + mMaxNewByteChunkSize = maxNewByteChunkSize; + mByteBuffer = new byte[maxNewByteChunkSize]; + } + + @Override + public void writeByte(byte b) throws IOException { + if (mReusableChunk != null) { + writeReusableChunk(); + } + mByteBuffer[mBufferSize++] = b; + if (mBufferSize == mMaxNewByteChunkSize) { + writeByteBuffer(); + } + } + + @Override + public void writeChunk(long chunkStart, int chunkLength) throws IOException { + Preconditions.checkArgument(chunkStart >= 0); + Preconditions.checkArgument(chunkLength > 0); + if (mBufferSize != 0) { + writeByteBuffer(); + } + + if (mReusableChunk != null && mReusableChunk.getEnd() + 1 == chunkStart) { + // The new chunk overlaps the old, so combine them into a single byte range. + mReusableChunk = mReusableChunk.extend(chunkLength); + } else { + writeReusableChunk(); + mReusableChunk = new ByteRange(chunkStart, chunkStart + chunkLength - 1); + } + } + + @Override + public void flush() throws IOException { + Preconditions.checkState(!(mBufferSize != 0 && mReusableChunk != null)); + if (mBufferSize != 0) { + writeByteBuffer(); + } + if (mReusableChunk != null) { + writeReusableChunk(); + } + mOutputStream.flush(); + } + + private void writeByteBuffer() throws IOException { + mOutputStream.write(Integer.toString(mBufferSize).getBytes(UTF_8)); + mOutputStream.write(LINE_SEPARATOR); + mOutputStream.write(mByteBuffer, 0, mBufferSize); + mOutputStream.write(LINE_SEPARATOR); + mBufferSize = 0; + } + + private void writeReusableChunk() throws IOException { + if (mReusableChunk != null) { + mOutputStream.write( + String.format( + Locale.US, + "%d-%d", + mReusableChunk.getStart(), + mReusableChunk.getEnd()) + .getBytes(UTF_8)); + mOutputStream.write(LINE_SEPARATOR); + mReusableChunk = null; + } + } + + /** A factory that creates {@link SingleStreamDiffScriptWriter}s. */ + public static class Factory implements DiffScriptWriter.Factory { + private final int mMaxNewByteChunkSize; + private final OutputStreamWrapper mOutputStreamWrapper; + + public Factory(int maxNewByteChunkSize, @Nullable OutputStreamWrapper outputStreamWrapper) { + mMaxNewByteChunkSize = maxNewByteChunkSize; + mOutputStreamWrapper = outputStreamWrapper; + } + + @Override + public SingleStreamDiffScriptWriter create(OutputStream outputStream) { + if (mOutputStreamWrapper != null) { + outputStream = mOutputStreamWrapper.wrap(outputStream); + } + return new SingleStreamDiffScriptWriter(outputStream, mMaxNewByteChunkSize); + } + } +} diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java index 2f78276bb533..39d5c9d0b777 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java @@ -77,6 +77,15 @@ public final class ContentCaptureManagerServiceShellCommand extends ShellCommand 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(""); @@ -91,6 +100,8 @@ public final class ContentCaptureManagerServiceShellCommand extends ShellCommand switch(what) { case "bind-instant-service-allowed": return getBindInstantService(pw); + case "default-service-enabled": + return getDefaultServiceEnabled(pw); default: pw.println("Invalid set: " + what); return -1; @@ -105,6 +116,8 @@ public final class ContentCaptureManagerServiceShellCommand extends ShellCommand return setBindInstantService(pw); case "temporary-service": return setTemporaryService(pw); + case "default-service-enabled": + return setDefaultServiceEnabled(); default: pw.println("Invalid set: " + what); return -1; @@ -149,6 +162,20 @@ public final class ContentCaptureManagerServiceShellCommand extends ShellCommand return 0; } + private int setDefaultServiceEnabled() { + final int userId = getNextIntArgRequired(); + final boolean enabled = Boolean.parseBoolean(getNextArg()); + mService.setDefaultServiceEnabled(userId, enabled); + return 0; + } + + private int getDefaultServiceEnabled(PrintWriter pw) { + final int userId = getNextIntArgRequired(); + final boolean enabled = mService.isDefaultServiceEnabled(userId); + pw.println(enabled); + return 0; + } + private int requestDestroy(PrintWriter pw) { if (!isNextArgSessions(pw)) { return -1; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 80b3d67217fd..fe4411c1dbb5 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1833,14 +1833,20 @@ public class ConnectivityService extends IConnectivityManager.Stub "ConnectivityService"); } - private void enforceAnyPermissionOf(String... permissions) { + private boolean checkAnyPermissionOf(String... permissions) { for (String permission : permissions) { if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { - return; + return true; } } - throw new SecurityException( - "Requires one of the following permissions: " + String.join(", ", permissions) + "."); + return false; + } + + private void enforceAnyPermissionOf(String... permissions) { + if (!checkAnyPermissionOf(permissions)) { + throw new SecurityException("Requires one of the following permissions: " + + String.join(", ", permissions) + "."); + } } private void enforceInternetPermission() { @@ -1860,19 +1866,22 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void enforceSettingsPermission() { - mContext.enforceCallingOrSelfPermission( + enforceAnyPermissionOf( android.Manifest.permission.NETWORK_SETTINGS, - "ConnectivityService"); + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } private boolean checkSettingsPermission() { - return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( - android.Manifest.permission.NETWORK_SETTINGS); + return checkAnyPermissionOf( + android.Manifest.permission.NETWORK_SETTINGS, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } private boolean checkSettingsPermission(int pid, int uid) { return PERMISSION_GRANTED == mContext.checkPermission( - android.Manifest.permission.NETWORK_SETTINGS, pid, uid); + android.Manifest.permission.NETWORK_SETTINGS, pid, uid) + || PERMISSION_GRANTED == mContext.checkPermission( + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid); } private void enforceTetherAccessPermission() { @@ -1882,9 +1891,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void enforceConnectivityInternalPermission() { - mContext.enforceCallingOrSelfPermission( + enforceAnyPermissionOf( android.Manifest.permission.CONNECTIVITY_INTERNAL, - "ConnectivityService"); + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } private void enforceControlAlwaysOnVpnPermission() { @@ -1895,20 +1904,16 @@ public class ConnectivityService extends IConnectivityManager.Stub private void enforceNetworkStackSettingsOrSetup() { enforceAnyPermissionOf( - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_SETUP_WIZARD, - android.Manifest.permission.NETWORK_STACK); - } - - private void enforceNetworkStackPermission() { - mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, - "ConnectivityService"); + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } private boolean checkNetworkStackPermission() { - return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( - android.Manifest.permission.NETWORK_STACK); + return checkAnyPermissionOf( + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } private void enforceConnectivityRestrictedNetworksPermission() { @@ -3240,6 +3245,25 @@ public class ConnectivityService extends IConnectivityManager.Stub }); } + /** + * NetworkStack endpoint to start the captive portal app. The NetworkStack needs to use this + * endpoint as it does not have INTERACT_ACROSS_USERS_FULL itself. + * @param appExtras Bundle to use as intent extras for the captive portal application. + * Must be treated as opaque to avoid preventing the captive portal app to + * update its arguments. + */ + @Override + public void startCaptivePortalAppInternal(Bundle appExtras) { + mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + + final Intent appIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN); + appIntent.putExtras(appExtras); + appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); + + Binder.withCleanCallingIdentity(() -> + mContext.startActivityAsUser(appIntent, UserHandle.CURRENT)); + } + public boolean avoidBadWifi() { return mMultinetworkPolicyTracker.getAvoidBadWifi(); } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 5278bbbb4af2..4834ce0da9b3 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -792,7 +792,7 @@ public class LocationManagerService extends ILocationManager.Stub { String[] testProviderStrings = resources.getStringArray( com.android.internal.R.array.config_testLocationProviders); for (String testProviderString : testProviderStrings) { - String fragments[] = testProviderString.split(","); + String[] fragments = testProviderString.split(","); String name = fragments[0].trim(); ProviderProperties properties = new ProviderProperties( Boolean.parseBoolean(fragments[1]) /* requiresNetwork */, @@ -816,12 +816,6 @@ public class LocationManagerService extends ILocationManager.Stub { return; } - // this call has the side effect of forcing a write to the LOCATION_MODE setting in an OS - // upgrade case, and ensures that if anyone checks the LOCATION_MODE setting directly, they - // will see it in an appropriate state (at least after that user becomes foreground for the - // first time...) - isLocationEnabledForUser(userId); - // let providers know the current user is on the way out before changing the user for (LocationProvider p : mProviders) { p.onUserChangingLocked(); @@ -934,17 +928,22 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(mName + " provider:"); + pw.print(" " + mName + " provider"); if (isMock()) { - pw.println(" mock=true"); + pw.print(" [mock]"); } - pw.println(" attached=" + (mProvider != null)); - if (mIsManagedBySettings) { - pw.println(" allowed=" + mAllowed); + pw.println(":"); + + pw.println(" useable=" + mUseable); + if (!mUseable) { + pw.println(" attached=" + (mProvider != null)); + if (mIsManagedBySettings) { + pw.println(" allowed=" + mAllowed); + } + pw.println(" enabled=" + mEnabled); } - pw.println(" enabled=" + mEnabled); - pw.println(" useable=" + mUseable); - pw.println(" properties=" + mProperties); + + pw.println(" properties=" + mProperties); if (mProvider != null) { long identity = Binder.clearCallingIdentity(); @@ -1397,14 +1396,10 @@ public class LocationManagerService extends ILocationManager.Stub { public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { if (mListener != null) { try { - synchronized (this) { - // synchronize to ensure incrementPendingBroadcastsLocked() - // is called before decrementPendingBroadcasts() - mListener.onStatusChanged(provider, status, extras); - // call this after broadcasting so we do not increment - // if we throw an exeption. - incrementPendingBroadcastsLocked(); - } + mListener.onStatusChanged(provider, status, extras); + // call this after broadcasting so we do not increment + // if we throw an exception. + incrementPendingBroadcastsLocked(); } catch (RemoteException e) { return false; } @@ -1413,16 +1408,12 @@ public class LocationManagerService extends ILocationManager.Stub { statusChanged.putExtras(new Bundle(extras)); statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); try { - synchronized (this) { - // synchronize to ensure incrementPendingBroadcastsLocked() - // is called before decrementPendingBroadcasts() - mPendingIntent.send(mContext, 0, statusChanged, this, mHandler, - getResolutionPermission(mAllowedResolutionLevel), - PendingIntentUtils.createDontSendToRestrictedAppsBundle(null)); - // call this after broadcasting so we do not increment - // if we throw an exeption. - incrementPendingBroadcastsLocked(); - } + mPendingIntent.send(mContext, 0, statusChanged, this, mHandler, + getResolutionPermission(mAllowedResolutionLevel), + PendingIntentUtils.createDontSendToRestrictedAppsBundle(null)); + // call this after broadcasting so we do not increment + // if we throw an exception. + incrementPendingBroadcastsLocked(); } catch (PendingIntent.CanceledException e) { return false; } @@ -1433,14 +1424,10 @@ public class LocationManagerService extends ILocationManager.Stub { public boolean callLocationChangedLocked(Location location) { if (mListener != null) { try { - synchronized (this) { - // synchronize to ensure incrementPendingBroadcastsLocked() - // is called before decrementPendingBroadcasts() - mListener.onLocationChanged(new Location(location)); - // call this after broadcasting so we do not increment - // if we throw an exeption. - incrementPendingBroadcastsLocked(); - } + mListener.onLocationChanged(new Location(location)); + // call this after broadcasting so we do not increment + // if we throw an exception. + incrementPendingBroadcastsLocked(); } catch (RemoteException e) { return false; } @@ -1449,16 +1436,12 @@ public class LocationManagerService extends ILocationManager.Stub { locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location)); try { - synchronized (this) { - // synchronize to ensure incrementPendingBroadcastsLocked() - // is called before decrementPendingBroadcasts() - mPendingIntent.send(mContext, 0, locationChanged, this, mHandler, - getResolutionPermission(mAllowedResolutionLevel), - PendingIntentUtils.createDontSendToRestrictedAppsBundle(null)); - // call this after broadcasting so we do not increment - // if we throw an exeption. - incrementPendingBroadcastsLocked(); - } + mPendingIntent.send(mContext, 0, locationChanged, this, mHandler, + getResolutionPermission(mAllowedResolutionLevel), + PendingIntentUtils.createDontSendToRestrictedAppsBundle(null)); + // call this after broadcasting so we do not increment + // if we throw an exception. + incrementPendingBroadcastsLocked(); } catch (PendingIntent.CanceledException e) { return false; } @@ -1473,18 +1456,14 @@ public class LocationManagerService extends ILocationManager.Stub { if (mListener != null) { try { - synchronized (this) { - // synchronize to ensure incrementPendingBroadcastsLocked() - // is called before decrementPendingBroadcasts() - if (enabled) { - mListener.onProviderEnabled(provider); - } else { - mListener.onProviderDisabled(provider); - } - // call this after broadcasting so we do not increment - // if we throw an exeption. - incrementPendingBroadcastsLocked(); + if (enabled) { + mListener.onProviderEnabled(provider); + } else { + mListener.onProviderDisabled(provider); } + // call this after broadcasting so we do not increment + // if we throw an exception. + incrementPendingBroadcastsLocked(); } catch (RemoteException e) { return false; } @@ -1492,16 +1471,12 @@ public class LocationManagerService extends ILocationManager.Stub { Intent providerIntent = new Intent(); providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); try { - synchronized (this) { - // synchronize to ensure incrementPendingBroadcastsLocked() - // is called before decrementPendingBroadcasts() - mPendingIntent.send(mContext, 0, providerIntent, this, mHandler, - getResolutionPermission(mAllowedResolutionLevel), - PendingIntentUtils.createDontSendToRestrictedAppsBundle(null)); - // call this after broadcasting so we do not increment - // if we throw an exeption. - incrementPendingBroadcastsLocked(); - } + mPendingIntent.send(mContext, 0, providerIntent, this, mHandler, + getResolutionPermission(mAllowedResolutionLevel), + PendingIntentUtils.createDontSendToRestrictedAppsBundle(null)); + // call this after broadcasting so we do not increment + // if we throw an exception. + incrementPendingBroadcastsLocked(); } catch (PendingIntent.CanceledException e) { return false; } @@ -1515,8 +1490,6 @@ public class LocationManagerService extends ILocationManager.Stub { synchronized (mLock) { removeUpdatesLocked(this); - } - synchronized (this) { clearPendingBroadcastsLocked(); } } @@ -1524,7 +1497,7 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras) { - synchronized (this) { + synchronized (mLock) { decrementPendingBroadcastsLocked(); } } @@ -1533,13 +1506,25 @@ public class LocationManagerService extends ILocationManager.Stub { // containing the sending of the broadcaset private void incrementPendingBroadcastsLocked() { mPendingBroadcasts++; - mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS); + // so wakelock calls will succeed + long identity = Binder.clearCallingIdentity(); + try { + mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS); + } finally { + Binder.restoreCallingIdentity(identity); + } } private void decrementPendingBroadcastsLocked() { if (--mPendingBroadcasts == 0) { - if (mWakeLock.isHeld()) { - mWakeLock.release(); + // so wakelock calls will succeed + long identity = Binder.clearCallingIdentity(); + try { + if (mWakeLock.isHeld()) { + mWakeLock.release(); + } + } finally { + Binder.restoreCallingIdentity(identity); } } } @@ -1547,8 +1532,14 @@ public class LocationManagerService extends ILocationManager.Stub { public void clearPendingBroadcastsLocked() { if (mPendingBroadcasts > 0) { mPendingBroadcasts = 0; - if (mWakeLock.isHeld()) { - mWakeLock.release(); + // so wakelock calls will succeed + long identity = Binder.clearCallingIdentity(); + try { + if (mWakeLock.isHeld()) { + mWakeLock.release(); + } + } finally { + Binder.restoreCallingIdentity(identity); } } } @@ -1561,18 +1552,9 @@ public class LocationManagerService extends ILocationManager.Stub { //LocationListener was removed when it had a pending broadcast and should //not be added back. synchronized (mLock) { - IBinder binder = listener.asBinder(); - Receiver receiver = mReceivers.get(binder); + Receiver receiver = mReceivers.get(listener.asBinder()); if (receiver != null) { - synchronized (receiver) { - // so wakelock calls will succeed - long identity = Binder.clearCallingIdentity(); - try { - receiver.decrementPendingBroadcastsLocked(); - } finally { - Binder.restoreCallingIdentity(identity); - } - } + receiver.decrementPendingBroadcastsLocked(); } } } @@ -2072,6 +2054,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (!provider.isUseableLocked()) { if (isSettingsExemptLocked(record)) { providerRequest.forceLocation = true; + providerRequest.lowPowerMode = false; } else { continue; } @@ -2080,7 +2063,9 @@ public class LocationManagerService extends ILocationManager.Stub { LocationRequest locationRequest = record.mRealRequest; long interval = locationRequest.getInterval(); - if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) { + // if we're forcing location, don't apply any throttling + if (!providerRequest.forceLocation && !isThrottlingExemptLocked( + record.mReceiver.mCallerIdentity)) { if (!record.mIsForegroundUid) { interval = Math.max(interval, backgroundThrottleInterval); } @@ -2174,11 +2159,8 @@ public class LocationManagerService extends ILocationManager.Stub { return true; } - if (isProviderPackage(callerIdentity.mPackageName)) { - return true; - } + return isProviderPackage(callerIdentity.mPackageName); - return false; } @GuardedBy("mLock") @@ -2192,11 +2174,8 @@ public class LocationManagerService extends ILocationManager.Stub { return true; } - if (isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName)) { - return true; - } + return isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName); - return false; } private class UpdateRecord { @@ -2504,9 +2483,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { receiver.getListener().asBinder().unlinkToDeath(receiver, 0); - synchronized (receiver) { - receiver.clearPendingBroadcastsLocked(); - } + receiver.clearPendingBroadcastsLocked(); } receiver.updateMonitoring(false); @@ -2682,7 +2659,6 @@ public class LocationManagerService extends ILocationManager.Stub { // geo-fence manager uses the public location API, need to clear identity int uid = Binder.getCallingUid(); - // TODO: http://b/23822629 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) { // temporary measure until geofences work for secondary users Log.w(TAG, "proximity alerts are currently available only to the primary user"); @@ -2723,8 +2699,6 @@ public class LocationManagerService extends ILocationManager.Stub { return false; } - // TODO(b/120449926): The GNSS status listeners should be handled similar to the GNSS - // measurements listeners. return mGnssStatusProvider.addListener(callback, new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName)); } @@ -2744,7 +2718,6 @@ public class LocationManagerService extends ILocationManager.Stub { synchronized (mLock) { CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName); - // TODO(b/120481270): Register for client death notification and update map. mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity); long identity = Binder.clearCallingIdentity(); try { @@ -2768,9 +2741,9 @@ public class LocationManagerService extends ILocationManager.Stub { android.Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to inject GNSS measurement corrections."); if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) { - mGnssMeasurementsProvider.injectGnssMeasurementCorrections(measurementCorrections); - } else { Slog.e(TAG, "Can not inject GNSS corrections due to no permission."); + } else { + mGnssMeasurementsProvider.injectGnssMeasurementCorrections(measurementCorrections); } } @@ -2809,7 +2782,6 @@ public class LocationManagerService extends ILocationManager.Stub { CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName); - // TODO(b/120481270): Register for client death notification and update map. mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity); long identity = Binder.clearCallingIdentity(); try { @@ -3382,7 +3354,9 @@ public class LocationManagerService extends ILocationManager.Stub { return; } pw.println("Current Location Manager state:"); - pw.println(" Location Mode: " + isLocationEnabled()); + pw.println(" Current user: " + mCurrentUserId + " " + Arrays.toString( + mCurrentUserProfiles)); + pw.println(" Location mode: " + isLocationEnabled()); pw.println(" Location Listeners:"); for (Receiver receiver : mReceivers.values()) { pw.println(" " + receiver); @@ -3406,14 +3380,6 @@ public class LocationManagerService extends ILocationManager.Stub { + callerIdentity.mPackageName + ": " + isThrottlingExemptLocked(callerIdentity)); } - pw.println(" Overlay Provider Packages:"); - for (LocationProvider provider : mProviders) { - if (provider.mProvider instanceof LocationProviderProxy) { - pw.println(" " + provider.getName() + ": " - + ((LocationProviderProxy) provider.mProvider) - .getProviderPackages()); - } - } pw.println(" Historical Records by Provider:"); for (Map.Entry<PackageProviderKey, PackageStatistics> entry : mRequestStatistics.statistics.entrySet()) { diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 360d2960f61a..01946247bd12 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -56,6 +56,8 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class); sGlobalSettingToTypeMap.put( + Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, String.class); + sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, String.class); sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class); diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index a3bae521a162..0dc73d9278a2 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -381,11 +381,11 @@ import java.util.ArrayList; //--------------------------------------------------------------------- // Message handling on behalf of helper classes - /*package*/ void broadcastScoConnectionState(int state) { + /*package*/ void postBroadcastScoConnectionState(int state) { sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state); } - /*package*/ void broadcastBecomingNoisy() { + /*package*/ void postBroadcastBecomingNoisy() { sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); } @@ -415,6 +415,22 @@ import java.util.ArrayList; delay); } + /*package*/ void postDisconnectA2dp() { + sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE); + } + + /*package*/ void postDisconnectA2dpSink() { + sendMsgNoDelay(MSG_DISCONNECT_A2DP_SINK, SENDMSG_QUEUE); + } + + /*package*/ void postDisconnectHearingAid() { + sendMsgNoDelay(MSG_DISCONNECT_HEARING_AID, SENDMSG_QUEUE); + } + + /*package*/ void postDisconnectHeadset() { + sendMsgNoDelay(MSG_DISCONNECT_HEADSET, SENDMSG_QUEUE); + } + //--------------------------------------------------------------------- // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) // only call from a "handle"* method or "on"* method @@ -444,23 +460,6 @@ import java.util.ArrayList; } } - /*package*/ void handleDisconnectA2dp() { - synchronized (mDeviceStateLock) { - mDeviceInventory.disconnectA2dp(); - } - } - /*package*/ void handleDisconnectA2dpSink() { - synchronized (mDeviceStateLock) { - mDeviceInventory.disconnectA2dpSink(); - } - } - - /*package*/ void handleDisconnectHearingAid() { - synchronized (mDeviceStateLock) { - mDeviceInventory.disconnectHearingAid(); - } - } - /*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { final int intState = (state == BluetoothA2dp.STATE_CONNECTED) @@ -482,7 +481,7 @@ import java.util.ArrayList; state, btDeviceInfo, delay); } - /*package*/ void handleSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state, + /*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0; sendILMsgNoDelay(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, state, @@ -710,6 +709,26 @@ import java.util.ArrayList; (BtHelper.BluetoothA2dpDeviceInfo) msg.obj); } break; + case MSG_DISCONNECT_A2DP: + synchronized (mDeviceStateLock) { + mDeviceInventory.disconnectA2dp(); + } + break; + case MSG_DISCONNECT_A2DP_SINK: + synchronized (mDeviceStateLock) { + mDeviceInventory.disconnectA2dpSink(); + } + break; + case MSG_DISCONNECT_HEARING_AID: + synchronized (mDeviceStateLock) { + mDeviceInventory.disconnectHearingAid(); + } + break; + case MSG_DISCONNECT_HEADSET: + synchronized (mDeviceStateLock) { + mBtHelper.disconnectHeadset(); + } + break; default: Log.wtf(TAG, "Invalid message " + msg.what); } @@ -745,6 +764,10 @@ import java.util.ArrayList; private static final int MSG_I_DISCONNECT_BT_SCO = 16; private static final int MSG_TOGGLE_HDMI = 17; 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 boolean isMessageHandledUnderWakelock(int msgId) { diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 11fdc8f05033..37f0496c0db3 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -859,7 +859,7 @@ public final class AudioDeviceInventory { // also checks whether media routing if affected by a dynamic policy if (((device == musicDevice) || mDeviceBroker.isInCommunication()) && (device == devices) && !mDeviceBroker.hasMediaDynamicPolicy()) { - mDeviceBroker.broadcastBecomingNoisy(); + mDeviceBroker.postBroadcastBecomingNoisy(); delay = 1000; } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index de63d0ef8edf..a6643d49c79f 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -5120,7 +5120,7 @@ public class AudioService extends IAudioService.Stub if (mUserSwitchedReceived) { // attempt to stop music playback for background user except on first user // switch (i.e. first boot) - mDeviceBroker.broadcastBecomingNoisy(); + mDeviceBroker.postBroadcastBecomingNoisy(); } mUserSwitchedReceived = true; // the current audio focus owner is no longer valid diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index b63af8a31cd9..e9189974e988 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -374,10 +374,10 @@ public class BtHelper { } /*package*/ synchronized void disconnectAllBluetoothProfiles() { - mDeviceBroker.handleDisconnectA2dp(); - mDeviceBroker.handleDisconnectA2dpSink(); - disconnectHeadset(); - mDeviceBroker.handleDisconnectHearingAid(); + mDeviceBroker.postDisconnectA2dp(); + mDeviceBroker.postDisconnectA2dpSink(); + mDeviceBroker.postDisconnectHeadset(); + mDeviceBroker.postDisconnectHearingAid(); } /*package*/ synchronized void resetBluetoothSco() { @@ -388,9 +388,14 @@ public class BtHelper { mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco"); } + /*package*/ synchronized void disconnectHeadset() { + setBtScoActiveDevice(null); + mBluetoothHeadset = null; + } + //---------------------------------------------------------------------- private void broadcastScoConnectionState(int state) { - mDeviceBroker.broadcastScoConnectionState(state); + mDeviceBroker.postBroadcastScoConnectionState(state); } private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) { @@ -487,7 +492,7 @@ public class BtHelper { btDevice = deviceList.get(0); final @BluetoothProfile.BtProfileState int state = proxy.getConnectionState(btDevice); - mDeviceBroker.handleSetA2dpSourceConnectionState( + mDeviceBroker.postSetA2dpSourceConnectionState( state, new BluetoothA2dpDeviceInfo(btDevice)); } break; @@ -558,19 +563,19 @@ public class BtHelper { switch (profile) { case BluetoothProfile.A2DP: - mDeviceBroker.handleDisconnectA2dp(); + mDeviceBroker.postDisconnectA2dp(); break; case BluetoothProfile.A2DP_SINK: - mDeviceBroker.handleDisconnectA2dpSink(); + mDeviceBroker.postDisconnectA2dpSink(); break; case BluetoothProfile.HEADSET: - disconnectHeadset(); + mDeviceBroker.postDisconnectHeadset(); break; case BluetoothProfile.HEARING_AID: - mDeviceBroker.handleDisconnectHearingAid(); + mDeviceBroker.postDisconnectHearingAid(); break; default: @@ -579,11 +584,6 @@ public class BtHelper { } }; - private void disconnectHeadset() { - setBtScoActiveDevice(null); - mBluetoothHeadset = null; - } - //---------------------------------------------------------------------- private class ScoClient implements IBinder.DeathRecipient { private IBinder mCb; // To be notified of client's death 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 90342ee31c3e..017503a03816 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/face/FaceService.java @@ -168,6 +168,7 @@ public class FaceService extends BiometricServiceBase { String opPackageName, int cookie, int callingUid, int callingPid, int callingUserId) { checkPermission(USE_BIOMETRIC_INTERNAL); + updateActiveGroup(groupId, opPackageName); final boolean restricted = true; // BiometricPrompt is always restricted final AuthenticationClientImpl client = new FaceAuthClient(getContext(), mDaemonWrapper, mHalDeviceId, token, 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 62947c7dd8b4..9e0a1c0c2ef2 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java @@ -192,6 +192,7 @@ public class FingerprintService extends BiometricServiceBase { IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName, int cookie, int callingUid, int callingPid, int callingUserId) { checkPermission(MANAGE_BIOMETRIC); + updateActiveGroup(groupId, opPackageName); final boolean restricted = true; // BiometricPrompt is always restricted final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(), mDaemonWrapper, mHalDeviceId, token, diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java index 727cf0e9f084..126beeffbb96 100644 --- a/services/core/java/com/android/server/display/BrightnessTracker.java +++ b/services/core/java/com/android/server/display/BrightnessTracker.java @@ -34,6 +34,7 @@ import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.AmbientBrightnessDayStats; import android.hardware.display.BrightnessChangeEvent; +import android.hardware.display.ColorDisplayManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayedContentSample; @@ -57,7 +58,6 @@ import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.ColorDisplayController; import com.android.internal.os.BackgroundThread; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.RingBuffer; @@ -382,9 +382,8 @@ public class BrightnessTracker { return; } - builder.setNightMode(mInjector.isNightModeActive(mContext, UserHandle.USER_CURRENT)); - builder.setColorTemperature(mInjector.getColorTemperature(mContext, - UserHandle.USER_CURRENT)); + builder.setNightMode(mInjector.isNightDisplayActivated(mContext)); + builder.setColorTemperature(mInjector.getNightDisplayColorTemperature(mContext)); if (mColorSamplingEnabled) { DisplayedContentSample sample = mInjector.sampleColor(mNoFramesToSample); @@ -1096,12 +1095,13 @@ public class BrightnessTracker { return context.getSystemService(PowerManager.class).isInteractive(); } - public int getColorTemperature(Context context, int userId) { - return new ColorDisplayController(context, userId).getColorTemperature(); + public int getNightDisplayColorTemperature(Context context) { + return context.getSystemService(ColorDisplayManager.class) + .getNightDisplayColorTemperature(); } - public boolean isNightModeActive(Context context, int userId) { - return new ColorDisplayController(context, userId).isActivated(); + public boolean isNightDisplayActivated(Context context) { + return context.getSystemService(ColorDisplayManager.class).isNightDisplayActivated(); } public DisplayedContentSample sampleColor(int noFramesToSample) { diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java index 0d0ce55c2792..9cb6eeec2126 100644 --- a/services/core/java/com/android/server/display/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/ColorDisplayService.java @@ -72,7 +72,6 @@ import android.view.animation.AnimationUtils; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.ColorDisplayController; import com.android.internal.util.DumpUtils; import com.android.server.DisplayThread; import com.android.server.SystemService; @@ -115,6 +114,7 @@ public final class ColorDisplayService extends SystemService { private static final int MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE = 0; private static final int MSG_APPLY_NIGHT_DISPLAY_ANIMATED = 1; private static final int MSG_APPLY_GLOBAL_SATURATION = 2; + private static final int MSG_APPLY_DISPLAY_WHITE_BALANCE = 3; /** * Return value if a setting has not been set. @@ -447,7 +447,6 @@ public final class ColorDisplayService extends SystemService { private ContentObserver mUserSetupObserver; private boolean mBootCompleted; - private ColorDisplayController mNightDisplayController; private ContentObserver mContentObserver; private DisplayWhiteBalanceListener mDisplayWhiteBalanceListener; @@ -546,8 +545,6 @@ public final class ColorDisplayService extends SystemService { private void setUp() { Slog.d(TAG, "setUp: currentUser=" + mCurrentUser); - mNightDisplayController = new ColorDisplayController(getContext(), mCurrentUser); - // Listen for external changes to any of the settings. if (mContentObserver == null) { mContentObserver = new ContentObserver(new Handler(DisplayThread.get().getLooper())) { @@ -585,7 +582,7 @@ public final class ColorDisplayService extends SystemService { getNightDisplayCustomEndTimeInternal().getLocalTime()); break; case System.DISPLAY_COLOR_MODE: - onDisplayColorModeChanged(mNightDisplayController.getColorMode()); + onDisplayColorModeChanged(getColorModeInternal()); break; case Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED: onAccessibilityInversionChanged(); @@ -633,7 +630,7 @@ public final class ColorDisplayService extends SystemService { // Set the color mode, if valid, and immediately apply the updated tint matrix based on the // existing activated state. This ensures consistency of tint across the color mode change. - onDisplayColorModeChanged(mNightDisplayController.getColorMode()); + onDisplayColorModeChanged(getColorModeInternal()); if (mNightDisplayTintController.isAvailable(getContext())) { // Reset the activated state. @@ -666,10 +663,6 @@ public final class ColorDisplayService extends SystemService { getContext().getContentResolver().unregisterContentObserver(mContentObserver); - if (mNightDisplayController != null) { - mNightDisplayController = null; - } - if (mNightDisplayTintController.isAvailable(getContext())) { if (mNightDisplayAutoMode != null) { mNightDisplayAutoMode.onStop(); @@ -739,7 +732,7 @@ public final class ColorDisplayService extends SystemService { } private void onAccessibilityActivated() { - onDisplayColorModeChanged(mNightDisplayController.getColorMode()); + onDisplayColorModeChanged(getColorModeInternal()); } /** @@ -870,7 +863,7 @@ public final class ColorDisplayService extends SystemService { // If disabled, clear the tint. If enabled, do nothing more here and let the next // temperature update set the correct tint. if (!activated) { - applyTint(mDisplayWhiteBalanceTintController, false); + mHandler.sendEmptyMessage(MSG_APPLY_DISPLAY_WHITE_BALANCE); } } @@ -1002,8 +995,7 @@ public final class ColorDisplayService extends SystemService { mCurrentUser); } - private @ColorMode - int getColorModeInternal() { + private @ColorMode int getColorModeInternal() { final ContentResolver cr = getContext().getContentResolver(); if (Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUser) == 1 @@ -1542,7 +1534,7 @@ public final class ColorDisplayService extends SystemService { mDisplayWhiteBalanceTintController.setMatrix(cct); if (mDisplayWhiteBalanceTintController.isActivated()) { - applyTint(mDisplayWhiteBalanceTintController, false); + mHandler.sendEmptyMessage(MSG_APPLY_DISPLAY_WHITE_BALANCE); return true; } return false; @@ -1602,6 +1594,9 @@ public final class ColorDisplayService extends SystemService { case MSG_APPLY_NIGHT_DISPLAY_ANIMATED: applyTint(mNightDisplayTintController, false); break; + case MSG_APPLY_DISPLAY_WHITE_BALANCE: + applyTint(mDisplayWhiteBalanceTintController, false); + break; } } } diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java index 2f277e4f2ff5..31b497d001eb 100644 --- a/services/core/java/com/android/server/display/ColorFade.java +++ b/services/core/java/com/android/server/display/ColorFade.java @@ -636,7 +636,7 @@ final class ColorFade { mSurfaceLayout = null; SurfaceControl.openTransaction(); try { - mSurfaceControl.destroy(); + mSurfaceControl.remove(); mSurface.release(); } finally { SurfaceControl.closeTransaction(); diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java index b1b7d3c8769b..ef92401bf3fd 100644 --- a/services/core/java/com/android/server/display/DisplayTransformManager.java +++ b/services/core/java/com/android/server/display/DisplayTransformManager.java @@ -87,7 +87,7 @@ public class DisplayTransformManager { * Map of level -> color transformation matrix. */ @GuardedBy("mColorMatrix") - private final SparseArray<float[]> mColorMatrix = new SparseArray<>(3); + private final SparseArray<float[]> mColorMatrix = new SparseArray<>(5); /** * Temporary matrix used internally by {@link #computeColorMatrixLocked()}. */ @@ -148,6 +148,21 @@ public class DisplayTransformManager { } /** + * Sets the current Daltonization mode. This adjusts the color space to correct for or simulate + * various types of color blindness. + * + * @param mode the new Daltonization mode, or -1 to disable + */ + public void setDaltonizerMode(int mode) { + synchronized (mDaltonizerModeLock) { + if (mDaltonizerMode != mode) { + mDaltonizerMode = mode; + applyDaltonizerMode(mode); + } + } + } + + /** * Returns the composition of all current color matrices, or {@code null} if there are none. */ @GuardedBy("mColorMatrix") @@ -167,30 +182,6 @@ public class DisplayTransformManager { } /** - * Returns the current Daltonization mode. - */ - public int getDaltonizerMode() { - synchronized (mDaltonizerModeLock) { - return mDaltonizerMode; - } - } - - /** - * Sets the current Daltonization mode. This adjusts the color space to correct for or simulate - * various types of color blindness. - * - * @param mode the new Daltonization mode, or -1 to disable - */ - public void setDaltonizerMode(int mode) { - synchronized (mDaltonizerModeLock) { - if (mDaltonizerMode != mode) { - mDaltonizerMode = mode; - applyDaltonizerMode(mode); - } - } - } - - /** * Propagates the provided color transformation matrix to the SurfaceFlinger. */ private static void applyColorMatrix(float[] m) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 7376ed2b0679..072238ee7f55 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -2412,7 +2412,8 @@ public class HdmiControlService extends SystemService { void wakeUp() { assertRunOnServiceThread(); mWakeUpMessageReceived = true; - mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.hdmi:WAKE"); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_HDMI, + "android.server.hdmi:WAKE"); // PowerManger will send the broadcast Intent.ACTION_SCREEN_ON and after this gets // the intent, the sequence will continue at onWakeUp(). } @@ -2637,7 +2638,8 @@ public class HdmiControlService extends SystemService { playback().sendStandby(0 /* unused */); } } else if (isPowerStandbyOrTransient() && !isStandbyModeOn) { - mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.hdmi:WAKE"); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_HDMI, + "android.server.hdmi:WAKE"); if (playback() != null) { oneTouchPlay(new IHdmiControlCallback.Stub() { @Override diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java index 532aa01f4438..2bfb31f6e74f 100644 --- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java +++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java @@ -286,6 +286,46 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } /** + * Sets whether the default service should be used. + * + * <p>Typically used during CTS tests to make sure only the default service doesn't interfere + * with the test results. + * + * @throws SecurityException if caller is not allowed to manage this service's settings. + */ + public final void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) { + Slog.i(mTag, "setDefaultServiceEnabled() for userId " + userId + ": " + enabled); + enforceCallingPermissionForManagement(); + + synchronized (mLock) { + final S oldService = peekServiceForUserLocked(userId); + if (oldService != null) { + oldService.removeSelfFromCacheLocked(); + } + mServiceNameResolver.setDefaultServiceEnabled(userId, enabled); + + // Must update the service on cache so its initialization code is triggered + updateCachedServiceLocked(userId); + } + } + + /** + * Checks whether the default service should be used. + * + * <p>Typically used during CTS tests to make sure only the default service doesn't interfere + * with the test results. + * + * @throws SecurityException if caller is not allowed to manage this service's settings. + */ + public final boolean isDefaultServiceEnabled(@UserIdInt int userId) { + enforceCallingPermissionForManagement(); + + synchronized (mLock) { + return mServiceNameResolver.isDefaultServiceEnabled(userId); + } + } + + /** * Gets the maximum time the service implementation can be changed. * * @throws UnsupportedOperationException if subclass doesn't override it. diff --git a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java index 7f198acfd743..cf84e22e7dd1 100644 --- a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java +++ b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java @@ -27,6 +27,7 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; @@ -61,6 +62,15 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR private final SparseArray<String> mTemporaryServiceNames = new SparseArray<>(); /** + * Map of default services that have been disabled by + * {@link #setDefaultServiceEnabled(int, boolean)},keyed by {@code userId}. + * + * <p>Typically used by Shell command and/or CTS tests. + */ + @GuardedBy("mLock") + private final SparseBooleanArray mDefaultServicesDisabled = new SparseBooleanArray(); + + /** * When the temporary service will expire (and reset back to the default). */ @GuardedBy("mLock") @@ -99,12 +109,18 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR final String temporaryName = mTemporaryServiceNames.get(userId); if (temporaryName != null) { // Always log it, as it should only be used on CTS or during development - Slog.w(TAG, "getComponentName(): using temporary name " + temporaryName + Slog.w(TAG, "getServiceName(): using temporary name " + temporaryName + " for user " + userId); return temporaryName; - } else { - return getDefaultServiceName(userId); } + final boolean disabled = mDefaultServicesDisabled.get(userId); + if (disabled) { + // Always log it, as it should only be used on CTS or during development + Slog.w(TAG, "getServiceName(): temporary name not set and default disabled for " + + "user " + userId); + return null; + } + return getDefaultServiceName(userId); } } @@ -158,6 +174,24 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR } @Override + public void setDefaultServiceEnabled(int userId, boolean enabled) { + synchronized (mLock) { + if (enabled) { + mDefaultServicesDisabled.removeAt(userId); + } else { + mDefaultServicesDisabled.put(userId, true); + } + } + } + + @Override + public boolean isDefaultServiceEnabled(int userId) { + synchronized (mLock) { + return mDefaultServicesDisabled.get(userId); + } + } + + @Override public String toString() { return "FrameworkResourcesServiceNamer[temps=" + mTemporaryServiceNames + "]"; } @@ -168,6 +202,7 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR synchronized (mLock) { pw.print("FrameworkResourcesServiceNamer: resId="); pw.print(mResourceId); pw.print(", numberTemps="); pw.print(mTemporaryServiceNames.size()); + pw.print(", enabledDefaults="); pw.print(mDefaultServicesDisabled.size()); } } @@ -181,7 +216,9 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR final long ttl = mTemporaryServiceExpiration - SystemClock.elapsedRealtime(); pw.print(" (expires in "); TimeUtils.formatDuration(ttl, pw); pw.print("), "); } - pw.print("defaultName="); pw.println(getDefaultServiceName(userId)); + pw.print("defaultName="); pw.print(getDefaultServiceName(userId)); + final boolean disabled = mDefaultServicesDisabled.get(userId); + pw.println(disabled ? " (disabled)" : " (enabled)"); } } diff --git a/services/core/java/com/android/server/infra/ServiceNameResolver.java b/services/core/java/com/android/server/infra/ServiceNameResolver.java index bc11ff302ca9..5b60413eefad 100644 --- a/services/core/java/com/android/server/infra/ServiceNameResolver.java +++ b/services/core/java/com/android/server/infra/ServiceNameResolver.java @@ -108,6 +108,36 @@ public interface ServiceNameResolver { } /** + * Sets whether the default service should be used when the temporary service is not set. + * + * <p>Typically used during CTS tests to make sure only the default service doesn't interfere + * with the test results. + * + * @param userId user handle + * @param enabled whether the default service should be used when the temporary service is not + * set + * + * @throws UnsupportedOperationException if not implemented. + */ + default void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) { + throw new UnsupportedOperationException("changing default service not supported"); + } + + /** + * Checks whether the default service should be used when the temporary service is not set. + * + * <p>Typically used during CTS tests to make sure only the default service doesn't interfere + * with the test results. + * + * @param userId user handle + * + * @throws UnsupportedOperationException if not implemented. + */ + default boolean isDefaultServiceEnabled(@UserIdInt int userId) { + throw new UnsupportedOperationException("checking default service not supported"); + } + + /** * Dumps the generic info in just one line (without calling {@code println}. */ // TODO(b/117779333): support proto diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java index 34c8786b00b3..afe34737fdee 100644 --- a/services/core/java/com/android/server/location/LocationProviderProxy.java +++ b/services/core/java/com/android/server/location/LocationProviderProxy.java @@ -183,12 +183,17 @@ public class LocationProviderProxy extends AbstractLocationProvider { @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(" service=" + mServiceWatcher); + pw.println(" service=" + mServiceWatcher); + synchronized (mProviderPackagesLock) { + if (mProviderPackages.size() > 1) { + pw.println(" additional packages=" + mProviderPackages); + } + } mServiceWatcher.runOnBinderBlocking(binder -> { try { TransferPipe.dumpAsync(binder, fd, args); } catch (IOException | RemoteException e) { - pw.println(" failed to dump location provider"); + pw.println(" <failed to dump location provider: " + e + ">"); } return null; }, null); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index d06fc513c0e8..1b719048bc89 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -44,7 +44,6 @@ import static com.android.server.pm.PackageInstallerService.prepareStageDir; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; -import android.apex.IApexService; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.IIntentReceiver; @@ -80,7 +79,6 @@ import android.os.ParcelableException; import android.os.Process; import android.os.RemoteException; import android.os.RevocableFileDescriptor; -import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.StorageManager; @@ -1084,6 +1082,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null); return; } + if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) { + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_INTERNAL_ERROR, + "APEX packages can only be installed using staged sessions."); + } final PackageManagerService.ActiveInstallSession committingSession = makeSessionActiveLocked(); if (committingSession == null) { @@ -1101,12 +1104,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final PackageManagerService.ActiveInstallSession activeSession = session.makeSessionActiveLocked(); if (activeSession != null) { - if ((activeSession.getSessionParams().installFlags - & PackageManager.INSTALL_APEX) != 0) { - throw new PackageManagerException( - PackageManager.INSTALL_FAILED_INTERNAL_ERROR, - "Atomic install is not supported for APEX packages."); - } childSessions.add(activeSession); } } catch (PackageManagerException e) { @@ -1124,27 +1121,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } mPm.installStage(childSessions); } else { - if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) { - commitApexLocked(); - } else { - mPm.installStage(committingSession); - } - } - } - - @GuardedBy("mLock") - private void commitApexLocked() throws PackageManagerException { - try { - IApexService apex = IApexService.Stub.asInterface( - ServiceManager.getService("apexservice")); - apex.stagePackage(mResolvedBaseFile.toString()); - } catch (Throwable e) { - // Convert all exceptions into package manager exceptions as only those are handled - // in the code above - throw new PackageManagerException(e); - } finally { - destroyInternal(); - dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "APEX installed", null); + mPm.installStage(committingSession); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 32dc98837854..eaedec597359 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -195,7 +195,6 @@ import android.content.pm.SharedLibraryInfo; import android.content.pm.Signature; import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; -import android.content.pm.UsesPermissionInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; import android.content.pm.VersionedPackage; @@ -11313,26 +11312,6 @@ public class PackageManagerService extends IPackageManager.Stub } } } - - // Check permission usage info requirements. - if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) { - for (UsesPermissionInfo upi : pkg.usesPermissionInfos) { - if (!mPermissionManager.isPermissionUsageInfoRequired(upi.getPermission())) { - continue; - } - if (upi.getDataSentOffDevice() == UsesPermissionInfo.USAGE_UNDEFINED - || upi.getDataSharedWithThirdParty() - == UsesPermissionInfo.USAGE_UNDEFINED - || upi.getDataUsedForMonetization() - == UsesPermissionInfo.USAGE_UNDEFINED - || upi.getDataRetention() == UsesPermissionInfo.RETENTION_UNDEFINED) { - // STOPSHIP: Make this throw - Slog.e(TAG, "Package " + pkg.packageName + " does not provide usage " - + "information for permission " + upi.getPermission() - + ". This will be a fatal error in Q."); - } - } - } } } diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 2213901b2049..ee6995b11430 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -228,8 +228,11 @@ public class DexManager { continue; } - mDexLogger.recordDex(loaderUserId, dexPath, searchResult.mOwningPackageName, - loadingAppInfo.packageName); + if (!primaryOrSplit) { + // Record loading of a DEX file from an app data directory. + mDexLogger.recordDex(loaderUserId, dexPath, searchResult.mOwningPackageName, + loadingAppInfo.packageName); + } if (classLoaderContexts != null) { diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 173d9a0551df..1957eb89fd0c 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -105,8 +105,6 @@ public final class BasePermission { */ private boolean perUser; - boolean usageInfoRequired; - public BasePermission(String _name, String _sourcePackageName, @PermissionType int _type) { name = _name; sourcePackageName = _sourcePackageName; @@ -375,7 +373,6 @@ public final class BasePermission { } if (bp.perm == p) { bp.protectionLevel = p.info.protectionLevel; - bp.usageInfoRequired = p.info.usageInfoRequired; } if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) { Log.d(TAG, " Permissions: " + r); @@ -455,7 +452,6 @@ public final class BasePermission { permissionInfo.packageName = sourcePackageName; permissionInfo.nonLocalizedLabel = name; permissionInfo.protectionLevel = protectionLevel; - permissionInfo.usageInfoRequired = usageInfoRequired; return permissionInfo; } @@ -484,7 +480,6 @@ public final class BasePermission { bp.protectionLevel = readInt(parser, null, "protection", PermissionInfo.PROTECTION_NORMAL); bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel); - bp.usageInfoRequired = readInt(parser, null, "usageInfoRequired", 0) != 0; if (dynamic) { final PermissionInfo pi = new PermissionInfo(); pi.packageName = sourcePackage.intern(); @@ -492,7 +487,6 @@ public final class BasePermission { pi.icon = readInt(parser, null, "icon", 0); pi.nonLocalizedLabel = parser.getAttributeValue(null, "label"); pi.protectionLevel = bp.protectionLevel; - pi.usageInfoRequired = bp.usageInfoRequired; bp.pendingPermissionInfo = pi; } out.put(bp.name, bp); @@ -525,7 +519,6 @@ public final class BasePermission { if (protectionLevel != PermissionInfo.PROTECTION_NORMAL) { serializer.attribute(null, "protection", Integer.toString(protectionLevel)); } - serializer.attribute(null, "usageInfoRequired", usageInfoRequired ? "1" : "0"); if (type == BasePermission.TYPE_DYNAMIC) { final PermissionInfo pi = perm != null ? perm.info : pendingPermissionInfo; if (pi != null) { @@ -562,7 +555,6 @@ public final class BasePermission { if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false; // We'll take care of setting this one. if (!compareStrings(pi1.packageName, pi2.packageName)) return false; - if (pi1.usageInfoRequired != pi2.usageInfoRequired) return false; // These are not currently stored in settings. //if (!compareStrings(pi1.group, pi2.group)) return false; //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false; @@ -610,8 +602,6 @@ public final class BasePermission { pw.print(" enforced="); pw.println(readEnforced); } - pw.print(" usageInfoRequired="); - pw.println(usageInfoRequired); return true; } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java index 189d0f476a8c..f4979746bae3 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java @@ -181,9 +181,4 @@ public abstract class PermissionManagerInternal { /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */ public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName); - - /** - * Returns {@code true} if {@code permName} has {@code usageInfoRequired} set. - */ - public abstract boolean isPermissionUsageInfoRequired(@NonNull String permName); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index a4413f963642..38940d6241a6 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -2737,12 +2737,5 @@ public class PermissionManagerService { return mSettings.getPermissionLocked(permName); } } - @Override - public boolean isPermissionUsageInfoRequired(String permName) { - synchronized (PermissionManagerService.this.mLock) { - BasePermission bp = mSettings.getPermissionLocked(permName); - return bp != null && bp.usageInfoRequired; - } - } } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 0796a9c896a3..b00193f5453f 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -148,6 +148,7 @@ import android.os.IBinder; import android.os.IDeviceIdleController; import android.os.Message; import android.os.PowerManager; +import android.os.PowerManager.WakeReason; import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; @@ -189,6 +190,7 @@ import android.view.ViewConfiguration; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManagerGlobal; +import android.view.WindowManagerPolicyConstants; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; @@ -809,7 +811,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false, "Wake Up"); wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture, - "android.policy:GESTURE"); + PowerManager.WAKE_REASON_GESTURE, "android.policy:GESTURE"); } } } @@ -3527,7 +3529,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (lidOpen) { wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, - "android.policy:LID"); + PowerManager.WAKE_REASON_LID, "android.policy:LID"); } else if (!mLidControlsSleep) { mPowerManager.userActivity(SystemClock.uptimeMillis(), false); } @@ -3550,7 +3552,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); } wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, - "android.policy:CAMERA_COVER"); + PowerManager.WAKE_REASON_CAMERA_LAUNCH, "android.policy:CAMERA_COVER"); startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); } mCameraLensCoverState = lensCoverState; @@ -3679,7 +3681,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (isValidGlobalKey(keyCode) && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, + PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY"); } return result; } @@ -4025,7 +4028,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, + PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY"); } return result; @@ -4125,7 +4129,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { if ((policyFlags & FLAG_WAKE) != 0) { if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, - "android.policy:MOTION")) { + PowerManager.WAKE_REASON_WAKE_MOTION, "android.policy:MOTION")) { return 0; } } @@ -4139,7 +4143,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // wake up in this case. if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, - "android.policy:MOTION"); + PowerManager.WAKE_REASON_WAKE_MOTION, "android.policy:MOTION"); } return 0; @@ -4371,7 +4375,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override public void startedGoingToSleep(int why) { - if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); + if (DEBUG_WAKEUP) { + Slog.i(TAG, "Started going to sleep... (why=" + + WindowManagerPolicyConstants.offReasonToString(why) + ")"); + } mGoingToSleep = true; mRequestedOrGoingToSleep = true; @@ -4385,7 +4392,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void finishedGoingToSleep(int why) { EventLog.writeEvent(70000, 0); - if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); + if (DEBUG_WAKEUP) { + Slog.i(TAG, "Finished going to sleep... (why=" + + WindowManagerPolicyConstants.offReasonToString(why) + ")"); + } MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); mGoingToSleep = false; @@ -4409,9 +4419,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override - public void startedWakingUp() { + public void startedWakingUp(@OnReason int why) { EventLog.writeEvent(70000, 1); - if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); + if (DEBUG_WAKEUP) { + Slog.i(TAG, "Started waking up... (why=" + + WindowManagerPolicyConstants.onReasonToString(why) + ")"); + } mDefaultDisplayPolicy.setAwake(true); @@ -4432,8 +4445,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override - public void finishedWakingUp() { - if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); + public void finishedWakingUp(@OnReason int why) { + if (DEBUG_WAKEUP) { + Slog.i(TAG, "Finished waking up... (why=" + + WindowManagerPolicyConstants.onReasonToString(why) + ")"); + } if (mKeyguardDelegate != null) { mKeyguardDelegate.onFinishedWakingUp(); @@ -4441,10 +4457,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void wakeUpFromPowerKey(long eventTime) { - wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); + wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, + PowerManager.WAKE_REASON_POWER_BUTTON, "android.policy:POWER"); } - private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { + private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason, + String details) { final boolean theaterModeEnabled = isTheaterModeEnabled(); if (!wakeInTheaterMode && theaterModeEnabled) { return false; @@ -4455,7 +4473,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Global.THEATER_MODE_ON, 0); } - mPowerManager.wakeUp(wakeTime, reason); + mPowerManager.wakeUp(wakeTime, reason, details); return true; } @@ -4786,7 +4804,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardDelegate.onBootCompleted(); } } - startedWakingUp(); + startedWakingUp(ON_BECAUSE_OF_UNKNOWN); screenTurningOn(null); screenTurnedOn(); } diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index e18cd179b113..d1bd102f11dc 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -1070,12 +1070,12 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { /** * Called when the device has started waking up. */ - public void startedWakingUp(); + void startedWakingUp(@OnReason int reason); /** * Called when the device has finished waking up. */ - public void finishedWakingUp(); + void finishedWakingUp(@OnReason int reason); /** * Called when the device has started going to sleep. diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index c3f20aab568e..1a82858147f4 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -36,6 +36,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PowerManager; +import android.os.PowerManager.WakeReason; import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; @@ -48,6 +49,7 @@ import android.provider.Settings; import android.util.EventLog; import android.util.Slog; import android.util.StatsLog; +import android.view.WindowManagerPolicyConstants.OnReason; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; @@ -136,6 +138,7 @@ public class Notifier { // broadcasted state over the course of reporting the transition asynchronously. private boolean mInteractive = true; private int mInteractiveChangeReason; + private long mInteractiveChangeStartTime; // In SystemClock.uptimeMillis() private boolean mInteractiveChanging; // The pending interactive state that we will eventually want to broadcast. @@ -371,7 +374,7 @@ public class Notifier { * which case it will assume that the state did not fully converge before the * next transition began and will recover accordingly. */ - public void onWakefulnessChangeStarted(final int wakefulness, int reason) { + public void onWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime) { final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); if (DEBUG) { Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness @@ -410,6 +413,7 @@ public class Notifier { // Handle early behaviors. mInteractive = interactive; mInteractiveChangeReason = reason; + mInteractiveChangeStartTime = eventTime; mInteractiveChanging = true; handleEarlyInteractiveChange(); } @@ -440,8 +444,8 @@ public class Notifier { mHandler.post(new Runnable() { @Override public void run() { - // Note a SCREEN tron event is logged in PowerManagerService. - mPolicy.startedWakingUp(); + final int why = translateOnReason(mInteractiveChangeReason); + mPolicy.startedWakingUp(why); } }); @@ -470,12 +474,21 @@ public class Notifier { */ private void handleLateInteractiveChange() { synchronized (mLock) { + final int interactiveChangeLatency = + (int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime); if (mInteractive) { // Finished waking up... + final int why = translateOnReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run() { - mPolicy.finishedWakingUp(); + LogMaker log = new LogMaker(MetricsEvent.SCREEN); + log.setType(MetricsEvent.TYPE_OPEN); + log.setSubtype(why); + log.setLatency(interactiveChangeLatency); + MetricsLogger.action(log); + EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency); + mPolicy.finishedWakingUp(why); } }); } else { @@ -499,8 +512,9 @@ public class Notifier { LogMaker log = new LogMaker(MetricsEvent.SCREEN); log.setType(MetricsEvent.TYPE_CLOSE); log.setSubtype(why); + log.setLatency(interactiveChangeLatency); MetricsLogger.action(log); - EventLogTags.writePowerScreenState(0, why, 0, 0, 0); + EventLogTags.writePowerScreenState(0, why, 0, 0, interactiveChangeLatency); mPolicy.finishedGoingToSleep(why); } }); @@ -524,6 +538,23 @@ public class Notifier { } } + private static @OnReason int translateOnReason(@WakeReason int reason) { + switch (reason) { + case PowerManager.WAKE_REASON_POWER_BUTTON: + case PowerManager.WAKE_REASON_PLUGGED_IN: + case PowerManager.WAKE_REASON_GESTURE: + case PowerManager.WAKE_REASON_CAMERA_LAUNCH: + case PowerManager.WAKE_REASON_WAKE_KEY: + case PowerManager.WAKE_REASON_WAKE_MOTION: + case PowerManager.WAKE_REASON_LID: + return WindowManagerPolicy.ON_BECAUSE_OF_USER; + case PowerManager.WAKE_REASON_APPLICATION: + return WindowManagerPolicy.ON_BECAUSE_OF_APPLICATION; + default: + return WindowManagerPolicy.ON_BECAUSE_OF_UNKNOWN; + } + } + /** * Called when screen brightness boost begins or ends. */ @@ -565,14 +596,16 @@ public class Notifier { /** * Called when the screen has turned on. */ - public void onWakeUp(String reason, int reasonUid, String opPackageName, int opUid) { + public void onWakeUp(int reason, String details, int reasonUid, String opPackageName, + int opUid) { if (DEBUG) { - Slog.d(TAG, "onWakeUp: event=" + reason + ", reasonUid=" + reasonUid + Slog.d(TAG, "onWakeUp: reason=" + PowerManager.wakeReasonToString(reason) + + ", details=" + details + ", reasonUid=" + reasonUid + " opPackageName=" + opPackageName + " opUid=" + opUid); } try { - mBatteryStats.noteWakeUp(reason, reasonUid); + mBatteryStats.noteWakeUp(details, reasonUid); if (opPackageName != null) { mAppOps.noteOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName); } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 3ccd2341fbeb..af3bff0c96ba 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -39,7 +39,6 @@ import android.hardware.SystemSensorManager; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; import android.hardware.power.V1_0.PowerHint; -import android.metrics.LogMaker; import android.net.Uri; import android.os.BatteryManager; import android.os.BatteryManagerInternal; @@ -52,6 +51,7 @@ import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.PowerManager.ServiceType; +import android.os.PowerManager.WakeReason; import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.Process; @@ -82,8 +82,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.internal.hardware.AmbientDisplayConfiguration; -import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; import com.android.server.EventLogTags; @@ -295,6 +293,7 @@ public final class PowerManagerService extends SystemService private long mLastSleepTime; // Last reason the device went to sleep. + private @WakeReason int mLastWakeReason; private int mLastSleepReason; // Timestamp of the last call to user activity. @@ -1119,8 +1118,9 @@ public final class PowerManagerService extends SystemService opPackageName = wakeLock.mPackageName; opUid = wakeLock.mOwnerUid; } - wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), wakeLock.mTag, opUid, - opPackageName, opUid); + wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_APPLICATION, wakeLock.mTag, + opUid, opPackageName, opUid); } } @@ -1410,17 +1410,17 @@ public final class PowerManagerService extends SystemService } } - private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName, - int opUid) { + private void wakeUpInternal(long eventTime, @WakeReason int reason, String details, int uid, + String opPackageName, int opUid) { synchronized (mLock) { - if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) { + if (wakeUpNoUpdateLocked(eventTime, reason, details, uid, opPackageName, opUid)) { updatePowerStateLocked(); } } } - private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid, - String opPackageName, int opUid) { + private boolean wakeUpNoUpdateLocked(long eventTime, @WakeReason int reason, String details, + int reasonUid, String opPackageName, int opUid) { if (DEBUG_SPEW) { Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid); } @@ -1434,25 +1434,18 @@ public final class PowerManagerService extends SystemService Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp"); try { - switch (mWakefulness) { - case WAKEFULNESS_ASLEEP: - Slog.i(TAG, "Waking up from sleep (uid=" + reasonUid + " reason=" + reason - + ")..."); - break; - case WAKEFULNESS_DREAMING: - Slog.i(TAG, "Waking up from dream (uid=" + reasonUid + " reason=" + reason - + ")..."); - break; - case WAKEFULNESS_DOZING: - Slog.i(TAG, "Waking up from dozing (uid=" + reasonUid + " reason=" + reason - + ")..."); - break; - } + Slog.i(TAG, "Waking up from " + + PowerManagerInternal.wakefulnessToString(mWakefulness) + + " (uid=" + reasonUid + + ", reason=" + PowerManager.wakeReasonToString(reason) + + ", details=" + details + + ")..."); mLastWakeTime = eventTime; - setWakefulnessLocked(WAKEFULNESS_AWAKE, 0); + mLastWakeReason = reason; + setWakefulnessLocked(WAKEFULNESS_AWAKE, reason, eventTime); - mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid); + mNotifier.onWakeUp(reason, details, reasonUid, opPackageName, opUid); userActivityNoUpdateLocked( eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid); } finally { @@ -1520,7 +1513,7 @@ public final class PowerManagerService extends SystemService mLastSleepTime = eventTime; mLastSleepReason = reason; mSandmanSummoned = true; - setWakefulnessLocked(WAKEFULNESS_DOZING, reason); + setWakefulnessLocked(WAKEFULNESS_DOZING, reason, eventTime); // Report the number of wake locks that will be cleared by going to sleep. int numWakeLocksCleared = 0; @@ -1570,7 +1563,7 @@ public final class PowerManagerService extends SystemService Slog.i(TAG, "Nap time (uid " + uid +")..."); mSandmanSummoned = true; - setWakefulnessLocked(WAKEFULNESS_DREAMING, 0); + setWakefulnessLocked(WAKEFULNESS_DREAMING, 0, eventTime); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } @@ -1593,7 +1586,8 @@ public final class PowerManagerService extends SystemService try { Slog.i(TAG, "Sleeping (uid " + uid +")..."); - setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, + eventTime); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } @@ -1601,13 +1595,13 @@ public final class PowerManagerService extends SystemService } @VisibleForTesting - void setWakefulnessLocked(int wakefulness, int reason) { + void setWakefulnessLocked(int wakefulness, int reason, long eventTime) { if (mWakefulness != wakefulness) { mWakefulness = wakefulness; mWakefulnessChanging = true; mDirty |= DIRTY_WAKEFULNESS; if (mNotifier != null) { - mNotifier.onWakefulnessChangeStarted(wakefulness, reason); + mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime); } mAttentionDetector.onWakefulnessChangeStarted(wakefulness); } @@ -1631,23 +1625,6 @@ public final class PowerManagerService extends SystemService } } - private void logScreenOn() { - Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0); - - final int latencyMs = (int) (SystemClock.uptimeMillis() - mLastWakeTime); - - LogMaker log = new LogMaker(MetricsEvent.SCREEN); - log.setType(MetricsEvent.TYPE_OPEN); - log.setSubtype(0); // not user initiated - log.setLatency(latencyMs); // How long it took. - MetricsLogger.action(log); - EventLogTags.writePowerScreenState(1, 0, 0, 0, latencyMs); - - if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) { - Slog.w(TAG, "Screen on took " + latencyMs+ " ms"); - } - } - private void finishWakefulnessChangeIfNeededLocked() { if (mWakefulnessChanging && mDisplayReady) { if (mWakefulness == WAKEFULNESS_DOZING @@ -1658,7 +1635,11 @@ public final class PowerManagerService extends SystemService logSleepTimeoutRecapturedLocked(); } if (mWakefulness == WAKEFULNESS_AWAKE) { - logScreenOn(); + Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0); + final int latencyMs = (int) (SystemClock.uptimeMillis() - mLastWakeTime); + if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) { + Slog.w(TAG, "Screen on took " + latencyMs + " ms"); + } } mWakefulnessChanging = false; mNotifier.onWakefulnessChangeFinished(); @@ -1786,7 +1767,8 @@ public final class PowerManagerService extends SystemService final long now = SystemClock.uptimeMillis(); if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType, dockedOnWirelessCharger)) { - wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID, + wakeUpNoUpdateLocked(now, PowerManager.WAKE_REASON_PLUGGED_IN, + "android.server.power:PLUGGED:" + mIsPowered, Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID); } userActivityNoUpdateLocked( @@ -2369,8 +2351,10 @@ public final class PowerManagerService extends SystemService PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID); updatePowerStateLocked(); } else { - wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM", - Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID); + wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_UNKNOWN, + "android.server.power:DREAM_FINISHED", Process.SYSTEM_UID, + mContext.getOpPackageName(), Process.SYSTEM_UID); updatePowerStateLocked(); } } else if (wakefulness == WAKEFULNESS_DOZING) { @@ -4375,7 +4359,8 @@ public final class PowerManagerService extends SystemService } @Override // Binder call - public void wakeUp(long eventTime, String reason, String opPackageName) { + public void wakeUp(long eventTime, @WakeReason int reason, String details, + String opPackageName) { if (eventTime > SystemClock.uptimeMillis()) { throw new IllegalArgumentException("event time must not be in the future"); } @@ -4386,7 +4371,7 @@ public final class PowerManagerService extends SystemService final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { - wakeUpInternal(eventTime, reason, uid, opPackageName, uid); + wakeUpInternal(eventTime, reason, details, uid, opPackageName, uid); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java index bd46a50f97de..fac95f9af42c 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java @@ -665,8 +665,7 @@ public class BatterySaverPolicy extends ContentObserver { config.getEnableAdjustBrightness(), config.getEnableDataSaver(), config.getEnableFirewall(), - // TODO: add option to config - config.getAdvertiseIsEnabled(), + config.getEnableNightMode(), config.getEnableQuickDoze(), /* filesForInteractive */ (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(), @@ -674,7 +673,7 @@ public class BatterySaverPolicy extends ContentObserver { (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(), config.getForceAllAppsStandby(), config.getForceBackgroundCheck(), - config.getGpsMode() + config.getLocationMode() ); } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 24d5bd14bc44..95c3f4c43313 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -340,12 +340,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // for apex? if (!info.isApex()) { String installerPackageName = pm.getInstallerPackageName(info.getPackageName()); - if (installerPackageName == null) { - sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE, - "Cannot find installer package"); - return; + if (installerPackageName != null) { + params.setInstallerPackageName(installerPackageName); } - params.setInstallerPackageName(installerPackageName); } params.setAllowDowngrade(true); if (data.isStaged()) { diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 071dde74f103..b0ef8a0d4209 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -2243,9 +2243,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub synchronized (mLock) { mInAmbientMode = inAmbientMode; final WallpaperData data = mWallpaperMap.get(mCurrentUserId); + final boolean hasConnection = data != null && data.connection != null; + final WallpaperInfo info = hasConnection ? data.connection.mInfo : null; + // The wallpaper info is null for image wallpaper, also use the engine in this case. - if (data != null && data.connection != null && (data.connection.mInfo == null - || data.connection.mInfo.supportsAmbientMode())) { + if (hasConnection && (info == null && isAodImageWallpaperEnabled() + || info != null && info.supportsAmbientMode())) { // TODO(multi-display) Extends this method with specific display. engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine; } else { diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index c0fe6e937422..0a3c2fba3930 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -97,7 +97,6 @@ import android.app.servertransaction.LaunchActivityItem; import android.app.servertransaction.PauseActivityItem; import android.app.servertransaction.ResumeActivityItem; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -467,7 +466,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { * initialized. So we initialize our wakelocks afterwards. */ void initPowerManagement() { - mPowerManager = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE); + mPowerManager = mService.mContext.getSystemService(PowerManager.class); mGoingToSleep = mPowerManager .newWakeLock(PARTIAL_WAKE_LOCK, "ActivityManager-Sleep"); mLaunchingActivity = mPowerManager.newWakeLock(PARTIAL_WAKE_LOCK, "*launch*"); @@ -2456,7 +2455,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } void wakeUp(String reason) { - mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.am:TURN_ON:" + reason); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_APPLICATION, + "android.server.am:TURN_ON:" + reason); } /** diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java index 6fcc331bf62f..0e14e46e77de 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 @@ class AppWindowThumbnail implements Animatable { void destroy() { mSurfaceAnimator.cancelAnimation(); - mSurfaceControl.destroy(); + mSurfaceControl.remove(); } /** diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 3246a8702cd1..2cc85e2076e0 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -2504,7 +2504,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree public void onAnimationLeashDestroyed(Transaction t) { super.onAnimationLeashDestroyed(t); if (mAnimationBoundsLayer != null) { - t.reparent(mAnimationBoundsLayer, null); + t.remove(mAnimationBoundsLayer); mAnimationBoundsLayer = null; } diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java index c90f5bfb7ee0..497e4121f12e 100644 --- a/services/core/java/com/android/server/wm/BlackFrame.java +++ b/services/core/java/com/android/server/wm/BlackFrame.java @@ -153,7 +153,7 @@ public class BlackFrame { if (mBlackSurfaces[i] != null) { if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM, " BLACK " + mBlackSurfaces[i].surface + ": DESTROY"); - mBlackSurfaces[i].surface.destroy(); + mBlackSurfaces[i].surface.remove(); mBlackSurfaces[i] = null; } } diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java index c39060ee1922..1373e1879d14 100644 --- a/services/core/java/com/android/server/wm/Dimmer.java +++ b/services/core/java/com/android/server/wm/Dimmer.java @@ -129,7 +129,7 @@ class Dimmer { final DimAnimatable dimAnimatable = new DimAnimatable(dimLayer); mSurfaceAnimator = new SurfaceAnimator(dimAnimatable, () -> { if (!mDimming) { - dimAnimatable.getPendingTransaction().reparent(mDimLayer, null); + dimAnimatable.getPendingTransaction().remove(mDimLayer); } }, mHost.mWmService); } @@ -300,7 +300,7 @@ class Dimmer { if (!mDimState.mDimming) { if (!mDimState.mAnimateExit) { - t.reparent(mDimState.mDimLayer, null); + t.remove(mDimState.mDimLayer); } else { startDimExit(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 7a8fd49361b6..928b57cf050b 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4418,13 +4418,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo .show(mSplitScreenDividerAnchor); scheduleAnimation(); } else { - mAppAnimationLayer.destroy(); + mAppAnimationLayer.remove(); mAppAnimationLayer = null; - mBoostedAppAnimationLayer.destroy(); + mBoostedAppAnimationLayer.remove(); mBoostedAppAnimationLayer = null; - mHomeAppAnimationLayer.destroy(); + mHomeAppAnimationLayer.remove(); mHomeAppAnimationLayer = null; - mSplitScreenDividerAnchor.destroy(); + mSplitScreenDividerAnchor.remove(); mSplitScreenDividerAnchor = null; } } diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java index 434084cc1f3d..987492024546 100644 --- a/services/core/java/com/android/server/wm/Letterbox.java +++ b/services/core/java/com/android/server/wm/Letterbox.java @@ -107,10 +107,10 @@ public class Letterbox { mOuter.setEmpty(); mInner.setEmpty(); - mTop.destroy(); - mLeft.destroy(); - mBottom.destroy(); - mRight.destroy(); + mTop.remove(); + mLeft.remove(); + mBottom.remove(); + mRight.remove(); } /** Returns whether a call to {@link #applySurfaceChanges} would change the surface. */ @@ -154,9 +154,9 @@ public class Letterbox { mSurface.setColor(new float[]{0, 0, 0}); } - public void destroy() { + public void remove() { if (mSurface != null) { - mSurface.destroy(); + mSurface.remove(); mSurface = null; } } diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 3947bd47b588..84cd8d1632cf 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -626,7 +626,7 @@ class ScreenRotationAnimation { if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM, " FREEZE " + mSurfaceControl + ": DESTROY"); - mSurfaceControl.destroy(); + mSurfaceControl.remove(); mSurfaceControl = null; } if (mCustomBlackFrame != null) { diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index c600e0f4a657..5ea24518370b 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -280,7 +280,7 @@ class SurfaceAnimator { } mService.mAnimationTransferMap.remove(mAnimation); if (mLeash != null && destroyLeash) { - t.reparent(mLeash, null); + t.remove(mLeash); scheduleAnim = true; } mLeash = null; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 53cd5ea8bf16..7b742fd2e0f3 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -1006,7 +1006,7 @@ public class TaskStack extends WindowContainer<Task> implements EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId); if (mAnimationBackgroundSurface != null) { - mAnimationBackgroundSurface.destroy(); + mAnimationBackgroundSurface.remove(); mAnimationBackgroundSurface = null; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index a054148e26b9..76f080b233a8 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -320,7 +320,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } if (mSurfaceControl != null) { - mPendingTransaction.reparent(mSurfaceControl, null); + mPendingTransaction.remove(mSurfaceControl); // Merge to parent transaction to ensure the transactions on this WindowContainer are // applied in native even if WindowContainer is removed. diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 4bc140095f1b..85b251a99f83 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -156,6 +156,7 @@ import android.os.Binder; import android.os.Debug; import android.os.IBinder; import android.os.PowerManager; +import android.os.PowerManager.WakeReason; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; @@ -611,7 +612,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } interface PowerManagerWrapper { - void wakeUp(long time, String reason); + void wakeUp(long time, @WakeReason int reason, String details); boolean isInteractive(); @@ -623,8 +624,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId, ownerCanAddInternalSystemWindow, new PowerManagerWrapper() { @Override - public void wakeUp(long time, String reason) { - service.mPowerManager.wakeUp(time, reason); + public void wakeUp(long time, @WakeReason int reason, String details) { + service.mPowerManager.wakeUp(time, reason, details); } @Override @@ -2253,7 +2254,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP Slog.v(TAG, "Relayout window turning screen on: " + this); } mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(), - "android.server.wm:TURN_ON"); + PowerManager.WAKE_REASON_APPLICATION, "android.server.wm:SCREEN_ON_FLAG"); } if (mAppToken != null) { diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index dea3597989be..e796b99f3989 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -161,7 +161,7 @@ class WindowSurfaceController { } try { if (mSurfaceControl != null) { - mSurfaceControl.destroy(); + mSurfaceControl.remove(); } } catch (RuntimeException e) { Slog.w(TAG, "Error destroying surface in: " + this, e); diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ByteRangeTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ByteRangeTest.java new file mode 100644 index 000000000000..8df08262c9fa --- /dev/null +++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ByteRangeTest.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.server.backup.encryption.chunking; + +import static org.junit.Assert.assertEquals; +import static org.testng.Assert.assertThrows; + +import android.platform.test.annotations.Presubmit; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link ByteRange}. */ +@RunWith(RobolectricTestRunner.class) +@Presubmit +public class ByteRangeTest { + @Test + public void getLength_includesEnd() throws Exception { + ByteRange byteRange = new ByteRange(5, 10); + + int length = byteRange.getLength(); + + assertEquals(6, length); + } + + @Test + public void constructor_rejectsNegativeStart() { + assertThrows(IllegalArgumentException.class, () -> new ByteRange(-1, 10)); + } + + @Test + public void constructor_rejectsEndBeforeStart() { + assertThrows(IllegalArgumentException.class, () -> new ByteRange(10, 9)); + } + + @Test + public void extend_withZeroLength_throwsException() { + ByteRange byteRange = new ByteRange(5, 10); + + assertThrows(IllegalArgumentException.class, () -> byteRange.extend(0)); + } +} diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriterTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriterTest.java new file mode 100644 index 000000000000..2af6f2bee8ff --- /dev/null +++ b/services/robotests/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriterTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.chunking; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.platform.test.annotations.Presubmit; + +import com.google.common.primitives.Bytes; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.robolectric.RobolectricTestRunner; + +import java.io.IOException; + +/** Tests for {@link DiffScriptBackupWriter}. */ +@RunWith(RobolectricTestRunner.class) +@Presubmit +public class DiffScriptBackupWriterTest { + private static final byte[] TEST_BYTES = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + + @Captor private ArgumentCaptor<Byte> mBytesCaptor; + @Mock private SingleStreamDiffScriptWriter mDiffScriptWriter; + private BackupWriter mBackupWriter; + + @Before + public void setUp() { + mDiffScriptWriter = mock(SingleStreamDiffScriptWriter.class); + mBackupWriter = new DiffScriptBackupWriter(mDiffScriptWriter); + mBytesCaptor = ArgumentCaptor.forClass(Byte.class); + } + + @Test + public void writeBytes_writesBytesToWriter() throws Exception { + mBackupWriter.writeBytes(TEST_BYTES); + + verify(mDiffScriptWriter, atLeastOnce()).writeByte(mBytesCaptor.capture()); + assertThat(mBytesCaptor.getAllValues()) + .containsExactlyElementsIn(Bytes.asList(TEST_BYTES)) + .inOrder(); + } + + @Test + public void writeChunk_writesChunkToWriter() throws Exception { + mBackupWriter.writeChunk(0, 10); + + verify(mDiffScriptWriter).writeChunk(0, 10); + } + + @Test + public void getBytesWritten_returnsTotalSum() throws Exception { + mBackupWriter.writeBytes(TEST_BYTES); + mBackupWriter.writeBytes(TEST_BYTES); + mBackupWriter.writeChunk(/*start=*/ 0, /*length=*/ 10); + + long bytesWritten = mBackupWriter.getBytesWritten(); + + assertThat(bytesWritten).isEqualTo(2 * TEST_BYTES.length + 10); + } + + @Test + public void flush_flushesWriter() throws IOException { + mBackupWriter.flush(); + + verify(mDiffScriptWriter).flush(); + } +} diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriterTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriterTest.java new file mode 100644 index 000000000000..73baf80a2c70 --- /dev/null +++ b/services/robotests/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriterTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.encryption.chunking; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.testng.Assert.assertThrows; + +import android.platform.test.annotations.Presubmit; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Locale; + +/** Tests for {@link SingleStreamDiffScriptWriter}. */ +@RunWith(RobolectricTestRunner.class) +@Presubmit +public class SingleStreamDiffScriptWriterTest { + private static final int MAX_CHUNK_SIZE_IN_BYTES = 256; + /** By default this Locale does not use Arabic numbers for %d formatting. */ + private static final Locale HINDI = new Locale("hi", "IN"); + + private Locale mDefaultLocale; + private ByteArrayOutputStream mOutputStream; + private SingleStreamDiffScriptWriter mDiffScriptWriter; + + @Before + public void setUp() { + mDefaultLocale = Locale.getDefault(); + mOutputStream = new ByteArrayOutputStream(); + mDiffScriptWriter = + new SingleStreamDiffScriptWriter(mOutputStream, MAX_CHUNK_SIZE_IN_BYTES); + } + + @After + public void tearDown() { + Locale.setDefault(mDefaultLocale); + } + + @Test + public void writeChunk_withNegativeStart_throwsException() { + assertThrows( + IllegalArgumentException.class, + () -> mDiffScriptWriter.writeChunk(-1, 50)); + } + + @Test + public void writeChunk_withZeroLength_throwsException() { + assertThrows( + IllegalArgumentException.class, + () -> mDiffScriptWriter.writeChunk(0, 0)); + } + + @Test + public void writeChunk_withExistingBytesInBuffer_writesBufferFirst() + throws IOException { + String testString = "abcd"; + writeStringAsBytesToWriter(testString, mDiffScriptWriter); + + mDiffScriptWriter.writeChunk(0, 20); + mDiffScriptWriter.flush(); + + // Expected format: length of abcd, newline, abcd, newline, chunk start - chunk end + assertThat(mOutputStream.toString("UTF-8")).isEqualTo( + String.format("%d\n%s\n%d-%d\n", testString.length(), testString, 0, 19)); + } + + @Test + public void writeChunk_overlappingPreviousChunk_combinesChunks() throws IOException { + mDiffScriptWriter.writeChunk(3, 4); + + mDiffScriptWriter.writeChunk(7, 5); + mDiffScriptWriter.flush(); + + assertThat(mOutputStream.toString("UTF-8")).isEqualTo(String.format("3-11\n")); + } + + @Test + public void writeChunk_formatsByteIndexesUsingArabicNumbers() throws Exception { + Locale.setDefault(HINDI); + + mDiffScriptWriter.writeChunk(0, 12345); + mDiffScriptWriter.flush(); + + assertThat(mOutputStream.toString("UTF-8")).isEqualTo("0-12344\n"); + } + + @Test + public void flush_flushesOutputStream() throws IOException { + ByteArrayOutputStream mockOutputStream = mock(ByteArrayOutputStream.class); + SingleStreamDiffScriptWriter diffScriptWriter = + new SingleStreamDiffScriptWriter(mockOutputStream, MAX_CHUNK_SIZE_IN_BYTES); + + diffScriptWriter.flush(); + + verify(mockOutputStream).flush(); + } + + private void writeStringAsBytesToWriter(String string, SingleStreamDiffScriptWriter writer) + throws IOException { + byte[] bytes = string.getBytes("UTF-8"); + for (int i = 0; i < bytes.length; i++) { + writer.writeByte(bytes[i]); + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java index e3b1245f20a5..7081d2e3b370 100644 --- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java @@ -962,13 +962,13 @@ public class BrightnessTrackerTest { } @Override - public int getColorTemperature(Context context, int userId) { + public int getNightDisplayColorTemperature(Context context) { return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, mDefaultNightModeColorTemperature); } @Override - public boolean isNightModeActive(Context context, int userId) { + public boolean isNightDisplayActivated(Context context) { return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 0) == 1; } diff --git a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java index 0b01657868a8..5900fc57296c 100644 --- a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java @@ -26,6 +26,7 @@ import android.app.AlarmManager; import android.content.Context; import android.content.ContextWrapper; import android.hardware.display.ColorDisplayManager; +import android.hardware.display.Time; import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; @@ -37,7 +38,6 @@ import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; -import com.android.internal.app.ColorDisplayController; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; import com.android.server.SystemService; @@ -71,7 +71,6 @@ public class ColorDisplayServiceTest { private MockTwilightManager mTwilightManager; private ColorDisplayService mColorDisplayService; - private ColorDisplayController mColorDisplayController; private ColorDisplayService.BinderService mBinderService; @BeforeClass @@ -97,7 +96,6 @@ public class ColorDisplayServiceTest { mTwilightManager = new MockTwilightManager(); LocalServices.addService(TwilightManager.class, mTwilightManager); - mColorDisplayController = new ColorDisplayController(mContext, mUserId); mColorDisplayService = new ColorDisplayService(mContext); mBinderService = mColorDisplayService.new BinderService(); } @@ -988,9 +986,11 @@ public class ColorDisplayServiceTest { * @param endTimeOffset the offset relative to now to deactivate Night display (in minutes) */ private void setAutoModeCustom(int startTimeOffset, int endTimeOffset) { - mColorDisplayController.setAutoMode(ColorDisplayManager.AUTO_MODE_CUSTOM_TIME); - mColorDisplayController.setCustomStartTime(getLocalTimeRelativeToNow(startTimeOffset)); - mColorDisplayController.setCustomEndTime(getLocalTimeRelativeToNow(endTimeOffset)); + mBinderService.setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_CUSTOM_TIME); + mBinderService.setNightDisplayCustomStartTime( + new Time(getLocalTimeRelativeToNow(startTimeOffset))); + mBinderService + .setNightDisplayCustomEndTime(new Time(getLocalTimeRelativeToNow(endTimeOffset))); } /** @@ -1000,7 +1000,7 @@ public class ColorDisplayServiceTest { * @param sunriseOffset the offset relative to now for sunrise (in minutes) */ private void setAutoModeTwilight(int sunsetOffset, int sunriseOffset) { - mColorDisplayController.setAutoMode(ColorDisplayManager.AUTO_MODE_TWILIGHT); + mBinderService.setNightDisplayAutoMode(ColorDisplayManager.AUTO_MODE_TWILIGHT); mTwilightManager.setTwilightState( getTwilightStateRelativeToNow(sunsetOffset, sunriseOffset)); } @@ -1041,22 +1041,18 @@ public class ColorDisplayServiceTest { } /** - * Configures color mode via ColorDisplayController. - * - * @param colorMode the color mode to set + * Configures color mode. */ private void setColorMode(int colorMode) { - mColorDisplayController.setColorMode(colorMode); + mBinderService.setColorMode(colorMode); } /** * Returns whether the color mode is valid on the device the tests are running on. - * - * @param mode the mode to check */ private boolean isColorModeValid(int mode) { final int[] availableColorModes = mContext.getResources().getIntArray( - R.array.config_availableColorModes); + R.array.config_availableColorModes); if (availableColorModes != null) { for (int availableMode : availableColorModes) { if (mode == availableMode) { @@ -1073,12 +1069,9 @@ public class ColorDisplayServiceTest { private void startService() { Secure.putIntForUser(mContext.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, mUserId); - InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - mColorDisplayService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); - mColorDisplayService.onStartUser(mUserId); - } + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + mColorDisplayService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); + mColorDisplayService.onStartUser(mUserId); }); } @@ -1100,7 +1093,7 @@ public class ColorDisplayServiceTest { */ private void assertActiveColorMode(int mode) { assertWithMessage("Unexpected color mode setting") - .that(mColorDisplayController.getColorMode()) + .that(mBinderService.getColorMode()) .isEqualTo(mode); } diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index 85909d564a7b..72357ceee099 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -31,7 +31,6 @@ import android.content.pm.ProviderInfo; import android.content.pm.ServiceInfo; import android.content.pm.SharedLibraryInfo; import android.content.pm.Signature; -import android.content.pm.UsesPermissionInfo; import android.os.Bundle; import android.os.Parcel; import android.platform.test.annotations.Presubmit; @@ -466,7 +465,6 @@ public class PackageParserTest { pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo())); pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo())); pkg.requestedPermissions.add("foo7"); - pkg.usesPermissionInfos.add(new UsesPermissionInfo("foo7")); pkg.implicitPermissions.add("foo25"); pkg.protectedBroadcasts = new ArrayList<>(); diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java index 2ddc71f570b8..48ab8d6698bd 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -141,7 +141,8 @@ public class DexManagerTests { assertIsUsedByOtherApps(mBarUser0, pui, true); assertTrue(pui.getDexUseInfoMap().isEmpty()); - assertHasDclInfo(mBarUser0, mFooUser0, mBarUser0.getBaseAndSplitDexPaths()); + // A package loading another package's APK is not DCL (it's not app data). + assertNoDclInfo(mBarUser0); } @Test @@ -334,7 +335,9 @@ public class DexManagerTests { notifyDexLoad(mFooUser0, newSplits, mUser0); PackageUseInfo pui = getPackageUseInfo(mBarUser0); assertIsUsedByOtherApps(newSplits, pui, true); - assertHasDclInfo(mBarUser0, mFooUser0, newSplits); + + // Primary and split APKs are not recorded as DCL. + assertNoDclInfo(mBarUser0); } @Test diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index bfa0b74b6927..63341b6ea38a 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -150,7 +150,7 @@ public class PowerManagerServiceTest extends AndroidTestCase { @SmallTest public void testGetDesiredScreenPolicy_WithVR() throws Exception { // Brighten up the screen - mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, 0); + mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_UNKNOWN, 0); assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( DisplayPowerRequest.POLICY_BRIGHT); @@ -160,12 +160,13 @@ public class PowerManagerServiceTest extends AndroidTestCase { DisplayPowerRequest.POLICY_VR); // Then take a nap - mService.setWakefulnessLocked(WAKEFULNESS_ASLEEP, 0); + mService.setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, + 0); assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( DisplayPowerRequest.POLICY_OFF); // Wake up to VR - mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, 0); + mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_UNKNOWN, 0); assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( DisplayPowerRequest.POLICY_VR); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java index ee228610ab21..2de4ae02828c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -57,7 +57,6 @@ import java.util.Arrays; */ @SmallTest @Presubmit -@FlakyTest(detail="promote once confirmed non-flaky") public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase { private ActivityMetricsLogger mActivityMetricsLogger; private ActivityMetricsLaunchObserver mLaunchObserver; 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 3bf884face42..defe9811ebcf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java @@ -42,7 +42,6 @@ import org.junit.Test; * Build/Install/Run: * atest WmTests:AppChangeTransitionTests */ -@FlakyTest(detail = "Promote when shown to be stable.") @SmallTest public class AppChangeTransitionTests extends WindowTestsBase { diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java index ea5ab7bf0621..dd5f32d248b7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java @@ -87,8 +87,8 @@ public class AppWindowTokenAnimationTests extends WindowTestsBase { verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture()); callbackCaptor.getValue().onAnimationFinished(mSpec); - verify(mTransaction).reparent(eq(leash), eq(null)); - verify(mTransaction).reparent(eq(animationBoundsLayer), eq(null)); + verify(mTransaction).remove(eq(leash)); + verify(mTransaction).remove(eq(animationBoundsLayer)); assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse(); } @@ -100,8 +100,8 @@ public class AppWindowTokenAnimationTests extends WindowTestsBase { final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer; mToken.mSurfaceAnimator.cancelAnimation(); - verify(mTransaction).reparent(eq(leash), eq(null)); - verify(mTransaction).reparent(eq(animationBoundsLayer), eq(null)); + verify(mTransaction).remove(eq(leash)); + verify(mTransaction).remove(eq(animationBoundsLayer)); assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java index f99cd4b18647..5b32fe68feae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java @@ -166,7 +166,7 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mTransaction).show(getDimLayer()); - verify(dimLayer, never()).destroy(); + verify(dimLayer, never()).remove(); } @Test @@ -212,7 +212,7 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any( SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean()); - verify(mHost.getPendingTransaction()).reparent(dimLayer, null); + verify(mHost.getPendingTransaction()).remove(dimLayer); } @Test @@ -228,7 +228,7 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mTransaction).show(dimLayer); - verify(dimLayer, never()).destroy(); + verify(dimLayer, never()).remove(); } @Test @@ -269,7 +269,7 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mSurfaceAnimatorStarter, never()).startAnimation(any(SurfaceAnimator.class), any( SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean()); - verify(mTransaction).reparent(dimLayer, null); + verify(mTransaction).remove(dimLayer); } private SurfaceControl getDimLayer() { diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java index a498a1a9172a..0c363de36328 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java @@ -39,7 +39,6 @@ import org.junit.Before; import org.junit.Test; @SmallTest -@FlakyTest(detail = "Promote once confirmed non-flaky") @Presubmit public class InsetsSourceProviderTest extends WindowTestsBase { diff --git a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java index beaac8e58686..86bf3dbb6973 100644 --- a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java @@ -40,7 +40,6 @@ import org.mockito.MockitoAnnotations; * atest WmTests:PendingRemoteAnimationRegistryTest */ @SmallTest -@FlakyTest @Presubmit public class PendingRemoteAnimationRegistryTest extends ActivityTestsBase { diff --git a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java index 434ba932f8ad..c3d2f33b17dd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java @@ -47,7 +47,6 @@ import java.util.function.Predicate; * atest WmTests:PersisterQueueTests */ @MediumTest -@FlakyTest(detail = "Confirm stable in post-submit before removing") @Presubmit public class PersisterQueueTests implements PersisterQueue.Listener { private static final long INTER_WRITE_DELAY_MS = 50; diff --git a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java index 530fd6d7d70e..dad6c952d7ab 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java @@ -31,7 +31,6 @@ import org.junit.Test; * atest WmTests:SafeActivityOptionsTest */ @MediumTest -@FlakyTest @Presubmit public class SafeActivityOptionsTest { diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java index 9b84215a8f3b..8c32e8cea93c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java @@ -96,7 +96,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { callbackCaptor.getValue().onAnimationFinished(mSpec); assertNotAnimating(mAnimatable); assertTrue(mAnimatable.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(mAnimatable.mLeash), eq(null)); + verify(mTransaction).remove(eq(mAnimatable.mLeash)); // TODO: Verify reparenting once we use mPendingTransaction to reparent it back } @@ -106,7 +106,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { final SurfaceControl firstLeash = mAnimatable.mLeash; mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec2, true /* hidden */); - verify(mTransaction).reparent(eq(firstLeash), eq(null)); + verify(mTransaction).remove(eq(firstLeash)); assertFalse(mAnimatable.mFinishedCallbackCalled); final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( @@ -133,7 +133,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { assertNotAnimating(mAnimatable); verify(mSpec).onAnimationCancelled(any()); assertTrue(mAnimatable.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(mAnimatable.mLeash), eq(null)); + verify(mTransaction).remove(eq(mAnimatable.mLeash)); } @Test @@ -155,7 +155,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { verifyZeroInteractions(mSpec); assertNotAnimating(mAnimatable); assertTrue(mAnimatable.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(mAnimatable.mLeash), eq(null)); + verify(mTransaction).remove(eq(mAnimatable.mLeash)); } @Test @@ -171,15 +171,14 @@ public class SurfaceAnimatorTest extends WindowTestsBase { assertNotAnimating(mAnimatable); assertAnimating(mAnimatable2); assertEquals(leash, mAnimatable2.mSurfaceAnimator.mLeash); - verify(mTransaction, never()).reparent(eq(leash), eq(null)); + verify(mTransaction, never()).remove(eq(leash)); callbackCaptor.getValue().onAnimationFinished(mSpec); assertNotAnimating(mAnimatable2); assertTrue(mAnimatable2.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(leash), eq(null)); + verify(mTransaction).remove(eq(leash)); } @Test - @FlakyTest(detail = "Promote once confirmed non-flaky") public void testDeferFinish() { // Start animation @@ -198,7 +197,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { mDeferFinishAnimatable.mEndDeferFinishCallback.run(); assertNotAnimating(mAnimatable2); assertTrue(mDeferFinishAnimatable.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(mDeferFinishAnimatable.mLeash), eq(null)); + verify(mTransaction).remove(eq(mDeferFinishAnimatable.mLeash)); } private void assertAnimating(MyAnimatable animatable) { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java index df7bc11663bc..12ed3c28161f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java @@ -41,7 +41,6 @@ import org.junit.Test; * Build/Install/Run: * atest WmTests:TaskPersisterTest */ -@FlakyTest(detail = "Promote to presubmit if stable") @Presubmit public class TaskPersisterTest { private static final String TEST_USER_NAME = "AM-Test-User"; diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index d1fe48aa63cd..bfb9193551f2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -28,6 +28,7 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; +import android.os.PowerManager.WakeReason; import android.os.RemoteException; import android.util.proto.ProtoOutputStream; import android.view.IWindow; @@ -182,11 +183,11 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public void startedWakingUp() { + public void startedWakingUp(@WakeReason int reason) { } @Override - public void finishedWakingUp() { + public void finishedWakingUp(@WakeReason int reason) { } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java index de3567ed5018..af8ccc981bae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java @@ -37,7 +37,6 @@ import org.junit.Test; * Build/Install/Run: * atest FrameworksServicesTests:WindowContainerControllerTests */ -@FlakyTest(bugId = 74078662) @SmallTest @Presubmit public class WindowContainerControllerTests extends WindowTestsBase { 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 c09cd46a6c04..8876214b9636 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90; import static android.view.InsetsState.TYPE_TOP_BAR; import static android.view.Surface.ROTATION_0; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; @@ -48,6 +49,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -60,13 +62,15 @@ import android.util.Size; import android.view.DisplayCutout; import android.view.InsetsSource; import android.view.SurfaceControl; +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.BeforeClass; import org.junit.Test; import java.util.LinkedList; @@ -77,10 +81,23 @@ import java.util.LinkedList; * Build/Install/Run: * atest FrameworksServicesTests:WindowStateTests */ -@FlakyTest(bugId = 74078662) @SmallTest @Presubmit public class WindowStateTests extends WindowTestsBase { + private static int sPreviousNewInsetsMode; + + @BeforeClass + public static void setUpOnce() { + sPreviousNewInsetsMode = ViewRootImpl.sNewInsetsMode; + // To let the insets provider control the insets visibility, the insets mode has to be + // NEW_INSETS_MODE_FULL. + ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL; + } + + @AfterClass + public static void tearDownOnce() { + ViewRootImpl.sNewInsetsMode = sPreviousNewInsetsMode; + } @Test public void testIsParentWindowHidden() { @@ -263,12 +280,12 @@ public class WindowStateTests extends WindowTestsBase { reset(sPowerManagerWrapper); first.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyString()); + verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString()); assertTrue(appWindowToken.canTurnScreenOn()); reset(sPowerManagerWrapper); second.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper).wakeUp(anyLong(), anyString()); + verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); assertFalse(appWindowToken.canTurnScreenOn()); // Call prepareWindowToDisplayDuringRelayout for two window that have FLAG_TURN_SCREEN_ON @@ -279,12 +296,12 @@ public class WindowStateTests extends WindowTestsBase { reset(sPowerManagerWrapper); first.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper).wakeUp(anyLong(), anyString()); + verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); assertFalse(appWindowToken.canTurnScreenOn()); reset(sPowerManagerWrapper); second.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyString()); + verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString()); assertFalse(appWindowToken.canTurnScreenOn()); // Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an @@ -300,11 +317,11 @@ public class WindowStateTests extends WindowTestsBase { reset(sPowerManagerWrapper); firstWindow.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper).wakeUp(anyLong(), anyString()); + verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); reset(sPowerManagerWrapper); secondWindow.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/); - verify(sPowerManagerWrapper).wakeUp(anyLong(), anyString()); + verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); } @Test @@ -435,6 +452,6 @@ public class WindowStateTests extends WindowTestsBase { root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/); - verify(sPowerManagerWrapper).wakeUp(anyLong(), anyString()); + verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString()); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java index 3048f1a3487b..d55688665f70 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java @@ -39,7 +39,6 @@ import org.junit.Test; * Build/Install/Run: * atest FrameworksServicesTests:WindowTokenTests */ -@FlakyTest(bugId = 74078662) @SmallTest @Presubmit public class WindowTokenTests extends WindowTestsBase { 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 b81a8e72301a..b6b9a861a282 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java @@ -60,7 +60,6 @@ import java.nio.charset.StandardCharsets; * Build/Install/Run: * atest FrameworksServicesTests:WindowTracingTest */ -@FlakyTest(bugId = 74078662) @SmallTest @Presubmit public class WindowTracingTest { diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/RotationCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/utils/RotationCacheTest.java index 33f34b465576..05d8237b4da4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/utils/RotationCacheTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/utils/RotationCacheTest.java @@ -37,7 +37,6 @@ import org.junit.Test; * atest WmTests:RotationCacheTest */ @SmallTest -@FlakyTest(bugId = 74078662) @Presubmit public class RotationCacheTest { diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index a6d7ee6d85e2..df2f45512465 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -493,6 +493,8 @@ public class UsageStatsService extends SystemService implements switch (event.mEventType) { case Event.ACTIVITY_RESUMED: synchronized (mVisibleActivities) { + // check if this activity has already been resumed + if (mVisibleActivities.get(event.mInstanceId) != null) break; mVisibleActivities.put(event.mInstanceId, event.getClassName()); try { mAppTimeLimit.noteUsageStart(packageName, userId); diff --git a/startop/view_compiler/OWNERS b/startop/view_compiler/OWNERS new file mode 100644 index 000000000000..e5aead9ddac8 --- /dev/null +++ b/startop/view_compiler/OWNERS @@ -0,0 +1,2 @@ +eholk@google.com +mathieuc@google.com diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 964a31304db5..9080e23eb88f 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -21,7 +21,6 @@ import android.os.SystemProperties; import android.telephony.PhoneNumberUtils; import android.telephony.SmsCbLocation; import android.telephony.SmsCbMessage; -import android.telephony.TelephonyManager; import android.telephony.cdma.CdmaSmsCbProgramData; import android.telephony.Rlog; import android.util.Log; @@ -746,8 +745,10 @@ public class SmsMessage extends SmsMessageBase { /** * Parses a broadcast SMS, possibly containing a CMAS alert. + * + * @param plmn the PLMN for a broadcast SMS */ - public SmsCbMessage parseBroadcastSms() { + public SmsCbMessage parseBroadcastSms(String plmn) { BearerData bData = BearerData.decode(mEnvelope.bearerData, mEnvelope.serviceCategory); if (bData == null) { Rlog.w(LOG_TAG, "BearerData.decode() returned null"); @@ -758,7 +759,6 @@ public class SmsMessage extends SmsMessageBase { Rlog.d(LOG_TAG, "MT raw BearerData = " + HexDump.toHexString(mEnvelope.bearerData)); } - String plmn = TelephonyManager.getDefault().getNetworkOperator(); SmsCbLocation location = new SmsCbLocation(plmn); return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2, @@ -858,11 +858,11 @@ public class SmsMessage extends SmsMessageBase { bearerData.userData = userData; byte[] encodedBearerData = BearerData.encode(bearerData); + if (encodedBearerData == null) return null; if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) { Rlog.d(LOG_TAG, "MO (encoded) BearerData = " + bearerData); Rlog.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'"); } - if (encodedBearerData == null) return null; int teleservice = bearerData.hasUserDataHeader ? SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT; diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 4b277ae850c5..f07ae9f65b1b 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -685,7 +685,7 @@ public class RollbackTest { ActivityManager am = context.getSystemService(ActivityManager.class); am.killBackgroundProcesses(TEST_APP_A); // Allow another package launch - crashQueue.offer(intent.getIntExtra("count", 0), 5, TimeUnit.SECONDS); + crashQueue.put(intent.getIntExtra("count", 0)); } catch (InterruptedException e) { fail("Failed to communicate with test app"); } @@ -694,14 +694,9 @@ public class RollbackTest { context.registerReceiver(crashCountReceiver, crashCountFilter); // Start apps PackageWatchdog#TRIGGER_FAILURE_COUNT times so TEST_APP_A crashes - Integer crashCount = null; do { RollbackTestUtils.launchPackage(TEST_APP_A); - crashCount = crashQueue.poll(5, TimeUnit.SECONDS); - if (crashCount == null) { - fail("Timed out waiting for crash signal from test app"); - } - } while(crashCount < 5); + } while(crashQueue.take() < 5); // TEST_APP_A is automatically rolled back by the RollbackPackageHealthObserver assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp index 257043b30704..a8d970edaa85 100644 --- a/tools/stats_log_api_gen/Collation.cpp +++ b/tools/stats_log_api_gen/Collation.cpp @@ -48,6 +48,7 @@ AtomDecl::AtomDecl(const AtomDecl& that) primaryFields(that.primaryFields), exclusiveField(that.exclusiveField), uidField(that.uidField), + whitelisted(that.whitelisted), binaryFields(that.binaryFields) {} AtomDecl::AtomDecl(int c, const string& n, const string& m) @@ -162,6 +163,7 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> *signature) { int errorCount = 0; + // Build a sorted list of the fields. Descriptor has them in source file // order. map<int, const FieldDescriptor *> fields; @@ -387,6 +389,11 @@ int collate_atoms(const Descriptor *descriptor, Atoms *atoms) { const Descriptor *atom = atomField->message_type(); AtomDecl atomDecl(atomField->number(), atomField->name(), atom->name()); + + if (atomField->options().GetExtension(os::statsd::allow_from_any_uid) == true) { + atomDecl.whitelisted = true; + } + vector<java_type_t> signature; errorCount += collate_atom(atom, &atomDecl, &signature); if (atomDecl.primaryFields.size() != 0 && atomDecl.exclusiveField == 0) { diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h index 450b30547c21..6b86b862dfad 100644 --- a/tools/stats_log_api_gen/Collation.h +++ b/tools/stats_log_api_gen/Collation.h @@ -89,6 +89,8 @@ struct AtomDecl { int uidField = 0; + bool whitelisted = false; + vector<int> binaryFields; AtomDecl(); diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp index 4491a8567441..55440d2261d3 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -158,6 +158,20 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, } } } + + fprintf(out, "};\n"); + fprintf(out, "\n"); + + fprintf(out, + "const std::set<int> AtomsInfo::kWhitelistedAtoms = {\n"); + for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); + atom != atoms.decls.end(); atom++) { + if (atom->whitelisted) { + string constant = make_constant_name(atom->name); + fprintf(out, " %s,\n", constant.c_str()); + } + } + fprintf(out, "};\n"); fprintf(out, "\n"); @@ -728,6 +742,8 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio fprintf(out, " const static std::map<int, std::vector<int>> " "kBytesFieldAtoms;"); + fprintf(out, + " const static std::set<int> kWhitelistedAtoms;\n"); fprintf(out, "};\n"); fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n", diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto index 3be87d95df15..24ebf4de031a 100644 --- a/tools/stats_log_api_gen/test.proto +++ b/tools/stats_log_api_gen/test.proto @@ -195,4 +195,22 @@ message GoodStateAtom3 { [(android.os.statsd.state_field_option).option = PRIMARY]; optional int32 state = 3 [(android.os.statsd.state_field_option).option = EXCLUSIVE]; +} + +message WhitelistedAtom { + optional int32 field = 1; +} + +message NonWhitelistedAtom { + optional int32 field = 1; +} + +message ListedAtoms { + oneof event { + // Atoms can be whitelisted i.e. they can be triggered by any source + WhitelistedAtom whitelisted_atom = 1 [(android.os.statsd.allow_from_any_uid) = true]; + // Atoms are not whitelisted by default, so they can only be triggered + // by whitelisted sources + NonWhitelistedAtom non_whitelisted_atom = 2; + } }
\ No newline at end of file diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp index ad3bffacd442..dc585c1c5dd1 100644 --- a/tools/stats_log_api_gen/test_collation.cpp +++ b/tools/stats_log_api_gen/test_collation.cpp @@ -226,5 +226,25 @@ TEST(CollationTest, FailOnBadBinaryFieldAtom) { EXPECT_TRUE(errorCount > 0); } +TEST(CollationTest, PassOnWhitelistedAtom) { + Atoms atoms; + int errorCount = + collate_atoms(ListedAtoms::descriptor(), &atoms); + EXPECT_EQ(errorCount, 0); + EXPECT_EQ(atoms.decls.size(), 2ul); +} + +TEST(CollationTest, RecogniseWhitelistedAtom) { + Atoms atoms; + collate_atoms(ListedAtoms::descriptor(), &atoms); + for (const auto& atomDecl : atoms.decls) { + if (atomDecl.code == 1) { + EXPECT_TRUE(atomDecl.whitelisted); + } else { + EXPECT_FALSE(atomDecl.whitelisted); + } + } +} + } // namespace stats_log_api_gen } // namespace android
\ No newline at end of file |