Merge "idmap2: fix static checks"
diff --git a/api/current.txt b/api/current.txt
index b321c224..abab901 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -224,6 +224,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
@@ -22643,6 +22620,7 @@
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 @@
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 @@
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 @@
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 @@
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);
@@ -54866,6 +54849,7 @@
method public void deferNotifyDataSetChanged();
method public void fling(int);
method public android.widget.AbsListView.LayoutParams generateLayoutParams(android.util.AttributeSet);
+ method @ColorInt public int getBottomEdgeEffectColor();
method @android.view.ViewDebug.ExportedProperty(category="drawing") @ColorInt public int getCacheColorHint();
method public int getCheckedItemCount();
method public long[] getCheckedItemIds();
@@ -54880,6 +54864,7 @@
method @android.view.ViewDebug.ExportedProperty public android.view.View getSelectedView();
method public android.graphics.drawable.Drawable getSelector();
method public CharSequence getTextFilter();
+ method @ColorInt public int getTopEdgeEffectColor();
method public int getTranscriptMode();
method protected void handleDataChanged();
method public boolean hasTextFilter();
@@ -54907,9 +54892,11 @@
method public void reclaimViews(java.util.List<android.view.View>);
method public void scrollListBy(int);
method public void setAdapter(android.widget.ListAdapter);
+ method public void setBottomEdgeEffectColor(@ColorInt int);
method public void setCacheColorHint(@ColorInt int);
method public void setChoiceMode(int);
method public void setDrawSelectorOnTop(boolean);
+ method public void setEdgeEffectColor(@ColorInt int);
method public void setFastScrollAlwaysVisible(boolean);
method public void setFastScrollEnabled(boolean);
method public void setFastScrollStyle(int);
@@ -54928,6 +54915,7 @@
method public void setSmoothScrollbarEnabled(boolean);
method public void setStackFromBottom(boolean);
method public void setTextFilterEnabled(boolean);
+ method public void setTopEdgeEffectColor(@ColorInt int);
method public void setTranscriptMode(int);
method public void setVelocityScale(float);
method public void smoothScrollBy(int, int);
@@ -55560,6 +55548,7 @@
ctor public EdgeEffect(android.content.Context);
method public boolean draw(android.graphics.Canvas);
method public void finish();
+ method @Nullable public android.graphics.BlendMode getBlendMode();
method @ColorInt public int getColor();
method public int getMaxHeight();
method public boolean isFinished();
@@ -55567,8 +55556,10 @@
method public void onPull(float);
method public void onPull(float, float);
method public void onRelease();
+ method public void setBlendMode(@Nullable android.graphics.BlendMode);
method public void setColor(@ColorInt int);
method public void setSize(int, int);
+ field public static final android.graphics.BlendMode DEFAULT_BLEND_MODE;
}
public class EditText extends android.widget.TextView {
diff --git a/api/system-current.txt b/api/system-current.txt
index b7fc339..02718cb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5777,11 +5777,6 @@
field public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
}
- public static interface DeviceConfig.Runtime {
- field public static final String NAMESPACE = "runtime";
- field public static final String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
- }
-
public static interface DeviceConfig.RuntimeNative {
field public static final String NAMESPACE = "runtime_native";
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 94e83ea..2c8d08c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -767,6 +767,7 @@
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);
@@ -2579,6 +2580,10 @@
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();
@@ -2665,6 +2670,8 @@
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 {
@@ -2714,6 +2721,66 @@
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 056add5..2fef407 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -43,6 +43,7 @@
"libidmap2/PrettyPrintVisitor.cpp",
"libidmap2/RawPrintVisitor.cpp",
"libidmap2/ResourceUtils.cpp",
+ "libidmap2/Result.cpp",
"libidmap2/Xml.cpp",
"libidmap2/ZipFile.cpp",
],
@@ -93,6 +94,7 @@
"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 6189ea3..d88dd51 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 @@
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 fa5ac8e..b19d7a9 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -117,6 +117,12 @@
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 @@
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 @@
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 @@
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 0000000..a5c9999
--- /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 067000a..41d3c69 100755
--- a/cmds/idmap2/static-checks.sh
+++ b/cmds/idmap2/static-checks.sh
@@ -74,6 +74,7 @@
-e 'Found C system header after C++ system header.' \
-e 'Unknown NOLINT error category: cert-dcl50-cpp' \
-e 'Unknown NOLINT error category: misc-non-private-member-variables-in-classes' \
+ -e 'Unknown NOLINT error category: performance-unnecessary-copy-initialization' \
)"
if [[ "$output" ]]; then
echo "$output"
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 9e27ccd..b40521f 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -191,8 +191,8 @@
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 b1ca125..a5588c3 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -52,8 +52,8 @@
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 0000000..d82f0c4
--- /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 e33bd8c..2a3eee2 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -82,4 +82,6 @@
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 07aced6..4f17d69 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -110,7 +110,7 @@
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 @@
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;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index ca68117..6ed6ab50 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -241,12 +241,22 @@
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 @@
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,29 +293,40 @@
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;
+ return false;
}
- } 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 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();
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 80982c3..fdc28ea 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -49,6 +49,10 @@
// 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 d52c9ef..1bd3ef2 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -435,6 +435,10 @@
}
}
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 40cf2e1..0cfefa9 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -61,6 +61,7 @@
if (!mSplitBucketForAppUpgrade) {
return;
}
+ flushIfNeededLocked(eventTimeNs - 1);
if (mIsPulled && mCondition) {
pullAndMatchEventsLocked(eventTimeNs - 1);
}
@@ -212,6 +213,7 @@
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);
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 2979346..91b98ec 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -167,9 +167,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 21d66e5..cc419b8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4565,16 +4565,25 @@
}
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 @@
// 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 a3021f3..d781a96 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -817,28 +817,6 @@
= "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 6d22277..27a5b39 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -204,10 +204,7 @@
* {@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 @@
* {@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 @@
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 @@
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 81ed110..5020a94 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -791,23 +791,18 @@
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 @@
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 @@
newPermsMsg.append(' ');
}
newPermsMsg.append(npi.name);
- addRequestedPermission(pkg, npi.name);
+ pkg.requestedPermissions.add(npi.name);
pkg.implicitPermissions.add(npi.name);
}
}
@@ -2519,7 +2514,7 @@
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 @@
}
} 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 @@
}
/**
- * 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 @@
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 @@
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 @@
+ parser.getPositionDescription());
}
- UsesPermissionInfo info = new UsesPermissionInfo(name, dataSentOffDevice,
- dataSharedWithThirdParty, dataUsedForMonetization, retention, retentionWeeks);
- pkg.usesPermissionInfos.add(info);
-
return true;
}
@@ -3420,10 +3367,6 @@
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 @@
@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 @@
dest.readStringList(requestedPermissions);
internStringArrayList(requestedPermissions);
- dest.readParcelableList(usesPermissionInfos, boot);
dest.readStringList(implicitPermissions);
internStringArrayList(implicitPermissions);
protectedBroadcasts = dest.createStringArrayList();
@@ -7327,7 +7266,6 @@
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 fb63e0d..e245234 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -20,7 +20,6 @@
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 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 @@
descriptionRes = orig.descriptionRes;
requestRes = orig.requestRes;
nonLocalizedDescription = orig.nonLocalizedDescription;
- usageInfoRequired = orig.usageInfoRequired;
}
/**
@@ -540,7 +532,6 @@
dest.writeInt(descriptionRes);
dest.writeInt(requestRes);
TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
- dest.writeInt(usageInfoRequired ? 1 : 0);
}
/** @hide */
@@ -581,6 +572,5 @@
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 d08548f..0000000
--- 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 9e0a9ba..faf17e0 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -1051,6 +1051,14 @@
}
}
+ 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 @@
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 59db49e..a2ae994 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1725,6 +1725,68 @@
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 9898079..da064c9 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1488,6 +1488,32 @@
}
}
}
+
+ /**
+ * 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 1881a0cd..0e4ff78 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1159,9 +1159,10 @@
* <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 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 9c213f2..20fc53f 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -356,12 +356,6 @@
* </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 @@
* </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 3d3a916..5250701 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -2126,6 +2126,7 @@
* <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 @@
/**
* <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 @@
/**
* <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 @@
/**
* <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 @@
* </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 @@
/**
* <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 @@
/**
* <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 @@
* 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 8982b40..13ad092 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2450,6 +2450,7 @@
* <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 @@
/**
* <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 @@
/**
* <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 @@
/**
* <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 @@
* </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 @@
/**
* <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 @@
/**
* <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 @@
* 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 7877a4d..65026b6 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1133,6 +1133,9 @@
/*dynamicDepthConfigurations*/ null,
/*dynamicDepthMinFrameDurations*/ null,
/*dynamicDepthStallDurations*/ null,
+ /*heicconfiguration*/ null,
+ /*heicminduration*/ null,
+ /*heicstallduration*/ null,
/*highspeedvideoconfigurations*/ null,
/*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]);
break;
@@ -1144,6 +1147,9 @@
/*dynamicDepthConfigurations*/ null,
/*dynamicDepthMinFrameDurations*/ null,
/*dynamicDepthStallDurations*/ null,
+ /*heicconfiguration*/ null,
+ /*heicminduration*/ null,
+ /*heicstallduration*/ null,
highSpeedVideoConfigurations,
/*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]);
break;
@@ -1155,6 +1161,9 @@
/*dynamicDepthConfigurations*/ null,
/*dynamicDepthMinFrameDurations*/ null,
/*dynamicDepthStallDurations*/ null,
+ /*heicconfiguration*/ null,
+ /*heicminduration*/ null,
+ /*heicstallduration*/ null,
/*highSpeedVideoConfigurations*/ null,
inputOutputFormatsMap, listHighResolution, supportsPrivate[i]);
break;
@@ -1166,6 +1175,9 @@
/*dynamicDepthConfigurations*/ null,
/*dynamicDepthMinFrameDurations*/ null,
/*dynamicDepthStallDurations*/ null,
+ /*heicconfiguration*/ null,
+ /*heicminduration*/ null,
+ /*heicstallduration*/ null,
/*highSpeedVideoConfigurations*/ null,
/*inputOutputFormatsMap*/ null, listHighResolution, supportsPrivate[i]);
}
@@ -1230,6 +1242,12 @@
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 @@
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 a22e008..996f997 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -79,6 +79,22 @@
* @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 @@
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 @@
* @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 @@
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 @@
"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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* <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 @@
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 @@
* <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 @@
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 @@
!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 @@
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 @@
}
// 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 @@
// 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 @@
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 @@
if (output) {
size += mDepthOutputFormats.size();
size += mDynamicDepthOutputFormats.size();
+ size += mHeicOutputFormats.size();
}
return size;
@@ -1569,6 +1682,7 @@
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 @@
return "RAW_DEPTH";
case ImageFormat.PRIVATE:
return "PRIVATE";
+ case ImageFormat.HEIC:
+ return "HEIC";
default:
return "UNKNOWN";
}
@@ -1795,7 +1911,7 @@
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 @@
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 @@
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/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 68f9288..269c781 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
@@ -59,6 +60,9 @@
private static final boolean DEBUG = false;
private static final String TAG = "GraphicsEnvironment";
+ private static final String SYSTEM_DRIVER_NAME = "system";
+ private static final String SYSTEM_DRIVER_VERSION_NAME = "";
+ private static final long SYSTEM_DRIVER_VERSION_CODE = 0;
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
private static final String ANGLE_RULES_FILE = "a4a_rules.json";
private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
@@ -74,9 +78,14 @@
* Set up GraphicsEnvironment
*/
public void setup(Context context, Bundle coreSettings) {
- setupGpuLayers(context, coreSettings);
- setupAngle(context, coreSettings, context.getPackageName());
- chooseDriver(context, coreSettings);
+ final PackageManager pm = context.getPackageManager();
+ final String packageName = context.getPackageName();
+ setupGpuLayers(context, coreSettings, pm, packageName);
+ setupAngle(context, coreSettings, pm, packageName);
+ if (!chooseDriver(context, coreSettings, pm, packageName)) {
+ setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE,
+ packageName);
+ }
}
/**
@@ -102,11 +111,10 @@
/**
* Return the debug layer app's on-disk and in-APK lib directories
*/
- private static String getDebugLayerAppPaths(Context context, String app) {
+ private static String getDebugLayerAppPaths(PackageManager pm, String app) {
final ApplicationInfo appInfo;
try {
- appInfo = context.getPackageManager().getApplicationInfo(
- app, PackageManager.MATCH_ALL);
+ appInfo = pm.getApplicationInfo(app, PackageManager.MATCH_ALL);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Debug layer app '" + app + "' not installed");
@@ -132,8 +140,8 @@
* Set up layer search paths for all apps
* If debuggable, check for additional debug settings
*/
- private void setupGpuLayers(Context context, Bundle coreSettings) {
-
+ private void setupGpuLayers(
+ Context context, Bundle coreSettings, PackageManager pm, String packageName) {
String layerPaths = "";
// Only enable additional debug functionality if the following conditions are met:
@@ -149,8 +157,6 @@
final String gpuDebugApp = coreSettings.getString(Settings.Global.GPU_DEBUG_APP);
- final String packageName = context.getPackageName();
-
if ((gpuDebugApp != null && packageName != null)
&& (!gpuDebugApp.isEmpty() && !packageName.isEmpty())
&& gpuDebugApp.equals(packageName)) {
@@ -161,14 +167,13 @@
// the layers specified by the app.
layerPaths = mDebugLayerPath + ":";
-
// If there is a debug layer app specified, add its path.
final String gpuDebugLayerApp =
coreSettings.getString(Settings.Global.GPU_DEBUG_LAYER_APP);
if (gpuDebugLayerApp != null && !gpuDebugLayerApp.isEmpty()) {
Log.i(TAG, "GPU debug layer app: " + gpuDebugLayerApp);
- final String paths = getDebugLayerAppPaths(context, gpuDebugLayerApp);
+ final String paths = getDebugLayerAppPaths(pm, gpuDebugLayerApp);
if (paths != null) {
// Append the path so files placed in the app's base directory will
// override the external path
@@ -280,11 +285,11 @@
/**
* Get the ANGLE package name.
*/
- private String getAnglePackageName(Context context) {
+ private String getAnglePackageName(PackageManager pm) {
final Intent intent = new Intent(ACTION_ANGLE_FOR_ANDROID);
- final List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(
- intent, PackageManager.MATCH_SYSTEM_ONLY);
+ final List<ResolveInfo> resolveInfos =
+ pm.queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY);
if (resolveInfos.size() != 1) {
Log.e(TAG, "Invalid number of ANGLE packages. Required: 1, Found: "
+ resolveInfos.size());
@@ -369,14 +374,13 @@
*/
private boolean setupAngleRulesApk(String anglePkgName,
ApplicationInfo angleInfo,
- Context context,
+ PackageManager pm,
String packageName,
String paths,
String devOptIn) {
// Pass the rules file to loader for ANGLE decisions
try {
- final AssetManager angleAssets =
- context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
+ final AssetManager angleAssets = pm.getResourcesForApplication(angleInfo).getAssets();
try {
final AssetFileDescriptor assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
@@ -411,7 +415,7 @@
/**
* Pass ANGLE details down to trigger enable logic
*/
- public void setupAngle(Context context, Bundle bundle, String packageName) {
+ public void setupAngle(Context context, Bundle bundle, PackageManager pm, String packageName) {
if (packageName.isEmpty()) {
Log.v(TAG, "No package name available yet, skipping ANGLE setup");
return;
@@ -449,7 +453,7 @@
Log.v(TAG, "ANGLE developer option for " + packageName + ": " + devOptIn);
}
- final String anglePkgName = getAnglePackageName(context);
+ final String anglePkgName = getAnglePackageName(pm);
if (anglePkgName.isEmpty()) {
Log.e(TAG, "Failed to find ANGLE package.");
return;
@@ -457,8 +461,7 @@
final ApplicationInfo angleInfo;
try {
- angleInfo = context.getPackageManager().getApplicationInfo(anglePkgName,
- PackageManager.MATCH_SYSTEM_ONLY);
+ angleInfo = pm.getApplicationInfo(anglePkgName, PackageManager.MATCH_SYSTEM_ONLY);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed");
return;
@@ -480,7 +483,7 @@
return;
}
- if (setupAngleRulesApk(anglePkgName, angleInfo, context, packageName, paths, devOptIn)) {
+ if (setupAngleRulesApk(anglePkgName, angleInfo, pm, packageName, paths, devOptIn)) {
// We setup ANGLE with rules from the APK, so we're done here.
return;
}
@@ -489,28 +492,30 @@
/**
* Choose whether the current process should use the builtin or an updated driver.
*/
- private static void chooseDriver(Context context, Bundle coreSettings) {
+ private static boolean chooseDriver(
+ Context context, Bundle coreSettings, PackageManager pm, String packageName) {
final String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
if (driverPackageName == null || driverPackageName.isEmpty()) {
- return;
+ return false;
}
- final ApplicationInfo driverInfo;
+ final PackageInfo driverPackageInfo;
try {
- driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName,
- PackageManager.MATCH_SYSTEM_ONLY);
+ driverPackageInfo =
+ pm.getPackageInfo(driverPackageName, PackageManager.MATCH_SYSTEM_ONLY);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
- return;
+ return false;
}
// O drivers are restricted to the sphal linker namespace, so don't try to use
// packages unless they declare they're compatible with that restriction.
- if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+ final ApplicationInfo driverAppInfo = driverPackageInfo.applicationInfo;
+ if (driverAppInfo.targetSdkVersion < Build.VERSION_CODES.O) {
if (DEBUG) {
Log.w(TAG, "updated driver package is not known to be compatible with O");
}
- return;
+ return false;
}
// To minimize risk of driver updates crippling the device beyond user repair, never use an
@@ -519,7 +524,7 @@
final ApplicationInfo ai = context.getApplicationInfo();
if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) {
if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app");
- return;
+ return false;
}
// GAME_DRIVER_ALL_APPS
@@ -531,28 +536,28 @@
if (DEBUG) {
Log.w(TAG, "Game Driver is turned off on this device");
}
- return;
+ return false;
}
if (gameDriverAllApps != 1) {
// GAME_DRIVER_OPT_OUT_APPS has higher priority than GAME_DRIVER_OPT_IN_APPS
if (getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_OUT_APPS)
- .contains(ai.packageName)) {
+ .contains(packageName)) {
if (DEBUG) {
- Log.w(TAG, ai.packageName + " opts out from Game Driver.");
+ Log.w(TAG, packageName + " opts out from Game Driver.");
}
- return;
+ return false;
}
final boolean isOptIn =
getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS)
- .contains(ai.packageName);
+ .contains(packageName);
if (!isOptIn
&& !getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_WHITELIST)
- .contains(ai.packageName)) {
+ .contains(packageName)) {
if (DEBUG) {
- Log.w(TAG, ai.packageName + " is not on the whitelist.");
+ Log.w(TAG, packageName + " is not on the whitelist.");
}
- return;
+ return false;
}
if (!isOptIn) {
@@ -566,12 +571,12 @@
final Blacklists blacklistsProto =
Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS));
final List<Blacklist> blacklists = blacklistsProto.getBlacklistsList();
- final long driverVersionCode = driverInfo.longVersionCode;
+ final long driverVersionCode = driverAppInfo.longVersionCode;
for (Blacklist blacklist : blacklists) {
if (blacklist.getVersionCode() == driverVersionCode) {
- for (String packageName : blacklist.getPackageNamesList()) {
- if (packageName == ai.packageName) {
- return;
+ for (String pkgName : blacklist.getPackageNamesList()) {
+ if (pkgName == packageName) {
+ return false;
}
}
break;
@@ -586,27 +591,32 @@
}
}
- final String abi = chooseAbi(driverInfo);
+ final String abi = chooseAbi(driverAppInfo);
if (abi == null) {
if (DEBUG) {
// This is the normal case for the pre-installed empty driver package, don't spam
- if (driverInfo.isUpdatedSystemApp()) {
+ if (driverAppInfo.isUpdatedSystemApp()) {
Log.w(TAG, "updated driver package has no compatible native libraries");
}
}
- return;
+ return false;
}
+ setGpuStats(driverPackageName, driverPackageInfo.versionName, driverAppInfo.longVersionCode,
+ packageName);
+
final StringBuilder sb = new StringBuilder();
- sb.append(driverInfo.nativeLibraryDir)
+ sb.append(driverAppInfo.nativeLibraryDir)
.append(File.pathSeparator);
- sb.append(driverInfo.sourceDir)
+ sb.append(driverAppInfo.sourceDir)
.append("!/lib/")
.append(abi);
final String paths = sb.toString();
if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths);
setDriverPath(paths);
+
+ return true;
}
/**
@@ -646,7 +656,8 @@
private static native void setDebugLayers(String layers);
private static native void setDebugLayersGLES(String layers);
private static native void setDriverPath(String path);
- private static native void setAngleInfo(String path, String appPackage,
- String devOptIn, FileDescriptor rulesFd,
- long rulesOffset, long rulesLength);
+ private static native void setGpuStats(String driverPackageName, String driverVersionName,
+ long driverVersionCode, String appPackageName);
+ private static native void setAngleInfo(String path, String appPackage, String devOptIn,
+ FileDescriptor rulesFd, long rulesOffset, long rulesLength);
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 5ac31dc..8e7906e 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -154,21 +154,6 @@
}
/**
- * Namespace for all runtime related features.
- *
- * @hide
- */
- @SystemApi
- public interface Runtime {
- String NAMESPACE = "runtime";
-
- /**
- * Whether or not we use the precompiled layout.
- */
- String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
- }
-
- /**
* Namespace for all runtime native related features.
*
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a8976aa..e95d6046 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9300,6 +9300,13 @@
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 @@
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/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 43de1f8..ff4ee9c 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -27,6 +27,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
@@ -281,7 +282,7 @@
}
};
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769467)
public DisplayInfo() {
}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index c130250..6a290b7 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -33,8 +33,6 @@
import android.os.Message;
import android.os.SystemProperties;
import android.os.Trace;
-import android.provider.DeviceConfig;
-import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
@@ -44,14 +42,13 @@
import com.android.internal.R;
import dalvik.system.PathClassLoader;
-
+import java.io.File;
+import java.lang.reflect.Method;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
import java.util.HashMap;
/**
@@ -81,6 +78,8 @@
private static final String TAG = LayoutInflater.class.getSimpleName();
private static final boolean DEBUG = false;
+ private static final String USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY
+ = "view.precompiled_layout_enabled";
private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex";
/** Empty stack trace used to avoid log spam in re-throw exceptions. */
@@ -401,19 +400,8 @@
}
private void initPrecompiledViews() {
- // Use the device config if enabled, otherwise default to the system property.
- String usePrecompiledLayout = DeviceConfig.getProperty(
- DeviceConfig.Runtime.NAMESPACE,
- DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT);
- boolean enabled = false;
- if (TextUtils.isEmpty(usePrecompiledLayout)) {
- enabled = SystemProperties.getBoolean(
- DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT,
- false);
- } else {
- enabled = Boolean.parseBoolean(usePrecompiledLayout);
- }
- initPrecompiledViews(enabled);
+ initPrecompiledViews(
+ SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false));
}
private void initPrecompiledViews(boolean enablePrecompiledViews) {
diff --git a/core/java/android/view/RemotableViewMethod.java b/core/java/android/view/RemotableViewMethod.java
index 03aed9a..5eff848 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 @@
* 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 c0a4028..8028715 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -852,12 +852,11 @@
}
/**
- * 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 @@
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 cd5207c..9f0800f 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -334,7 +334,7 @@
updateSurface();
if (mSurfaceControl != null) {
- mSurfaceControl.destroy();
+ mSurfaceControl.remove();
}
mSurfaceControl = null;
@@ -502,11 +502,11 @@
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 @@
}
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 cb8f703..3f2795b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -35,6 +35,7 @@
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.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;
@@ -821,7 +823,14 @@
*
* @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.
@@ -5079,6 +5088,15 @@
@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()}.
*/
@@ -5254,7 +5272,11 @@
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);
}
@@ -5916,6 +5938,84 @@
}
/**
+ * 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.
*/
@@ -6001,6 +6101,46 @@
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();
@@ -23289,7 +23429,7 @@
/**
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
protected void internalSetPadding(int left, int top, int right, int bottom) {
mUserPaddingLeft = left;
mUserPaddingRight = right;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 67cca56..156972f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1603,7 +1603,7 @@
mSurfaceSession = null;
if (mBoundsSurfaceControl != null) {
- mBoundsSurfaceControl.destroy();
+ mBoundsSurfaceControl.remove();
mBoundsSurface.release();
mBoundsSurfaceControl = null;
}
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index f1c7b69..5608bb3 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -52,11 +52,13 @@
}
/** @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 1c96b87..83fc0173 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -346,9 +346,6 @@
@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/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
index 924bb9a..8d62454 100644
--- a/core/java/android/view/contentcapture/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -34,7 +34,6 @@
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 @@
}
/** @hide */
+ @TestApi
public static void writeToParcel(@NonNull Parcel parcel, @Nullable ViewNode node, int flags) {
if (node == null) {
parcel.writeLong(0);
@@ -598,18 +598,20 @@
}
/** @hide */
+ @TestApi
public static @Nullable ViewNode readFromParcel(@NonNull Parcel parcel) {
final long nodeFlags = parcel.readLong();
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 @@
}
}
- @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/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 542df45..1f8a908 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -708,15 +708,23 @@
/**
* Tracks the state of the top edge glow.
+ *
+ * Even though this field is practically final, we cannot make it final because there are apps
+ * setting it via reflection and they need to keep working until they target Q.
*/
- @UnsupportedAppUsage
- private EdgeEffect mEdgeGlowTop;
+ @NonNull
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769408)
+ private EdgeEffect mEdgeGlowTop = new EdgeEffect(mContext);
/**
* Tracks the state of the bottom edge glow.
+ *
+ * Even though this field is practically final, we cannot make it final because there are apps
+ * setting it via reflection and they need to keep working until they target Q.
*/
- @UnsupportedAppUsage
- private EdgeEffect mEdgeGlowBottom;
+ @NonNull
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768444)
+ private EdgeEffect mEdgeGlowBottom = new EdgeEffect(mContext);
/**
* An estimate of how many pixels are between the top of the list and
@@ -923,21 +931,6 @@
mDensityScale = getContext().getResources().getDisplayMetrics().density;
}
- @Override
- public void setOverScrollMode(int mode) {
- if (mode != OVER_SCROLL_NEVER) {
- if (mEdgeGlowTop == null) {
- Context context = getContext();
- mEdgeGlowTop = new EdgeEffect(context);
- mEdgeGlowBottom = new EdgeEffect(context);
- }
- } else {
- mEdgeGlowTop = null;
- mEdgeGlowBottom = null;
- }
- super.setOverScrollMode(mode);
- }
-
/**
* {@inheritDoc}
*/
@@ -3772,7 +3765,7 @@
}
private void invalidateTopGlow() {
- if (mEdgeGlowTop == null) {
+ if (!shouldDisplayEdgeEffects()) {
return;
}
final boolean clipToPadding = getClipToPadding();
@@ -3783,7 +3776,7 @@
}
private void invalidateBottomGlow() {
- if (mEdgeGlowBottom == null) {
+ if (!shouldDisplayEdgeEffects()) {
return;
}
final boolean clipToPadding = getClipToPadding();
@@ -4208,7 +4201,7 @@
setPressed(false);
- if (mEdgeGlowTop != null) {
+ if (shouldDisplayEdgeEffects()) {
mEdgeGlowTop.onRelease();
mEdgeGlowBottom.onRelease();
}
@@ -4233,6 +4226,10 @@
}
}
+ private boolean shouldDisplayEdgeEffects() {
+ return getOverScrollMode() != OVER_SCROLL_NEVER;
+ }
+
private void onTouchCancel() {
switch (mTouchMode) {
case TOUCH_MODE_OVERSCROLL:
@@ -4258,7 +4255,7 @@
recycleVelocityTracker();
}
- if (mEdgeGlowTop != null) {
+ if (shouldDisplayEdgeEffects()) {
mEdgeGlowTop.onRelease();
mEdgeGlowBottom.onRelease();
}
@@ -4379,7 +4376,7 @@
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
- if (mEdgeGlowTop != null) {
+ if (shouldDisplayEdgeEffects()) {
final int scrollY = mScrollY;
final boolean clipToPadding = getClipToPadding();
final int width;
@@ -6371,7 +6368,7 @@
}
private void finishGlows() {
- if (mEdgeGlowTop != null) {
+ if (shouldDisplayEdgeEffects()) {
mEdgeGlowTop.finish();
mEdgeGlowBottom.finish();
}
@@ -6478,6 +6475,76 @@
}
/**
+ * Sets the edge effect color for both top and bottom edge effects.
+ *
+ * @param color The color for the edge effects.
+ * @see #setTopEdgeEffectColor(int)
+ * @see #setBottomEdgeEffectColor(int)
+ * @see #getTopEdgeEffectColor()
+ * @see #getBottomEdgeEffectColor()
+ */
+ public void setEdgeEffectColor(@ColorInt int color) {
+ setTopEdgeEffectColor(color);
+ setBottomEdgeEffectColor(color);
+ }
+
+ /**
+ * Sets the bottom edge effect color.
+ *
+ * @param color The color for the bottom edge effect.
+ * @see #setTopEdgeEffectColor(int)
+ * @see #setEdgeEffectColor(int)
+ * @see #getTopEdgeEffectColor()
+ * @see #getBottomEdgeEffectColor()
+ */
+ public void setBottomEdgeEffectColor(@ColorInt int color) {
+ mEdgeGlowBottom.setColor(color);
+ invalidateBottomGlow();
+ }
+
+ /**
+ * Sets the top edge effect color.
+ *
+ * @param color The color for the top edge effect.
+ * @see #setBottomEdgeEffectColor(int)
+ * @see #setEdgeEffectColor(int)
+ * @see #getTopEdgeEffectColor()
+ * @see #getBottomEdgeEffectColor()
+ */
+ public void setTopEdgeEffectColor(@ColorInt int color) {
+ mEdgeGlowTop.setColor(color);
+ invalidateTopGlow();
+ }
+
+ /**
+ * Returns the top edge effect color.
+ *
+ * @return The top edge effect color.
+ * @see #setEdgeEffectColor(int)
+ * @see #setTopEdgeEffectColor(int)
+ * @see #setBottomEdgeEffectColor(int)
+ * @see #getBottomEdgeEffectColor()
+ */
+ @ColorInt
+ public int getTopEdgeEffectColor() {
+ return mEdgeGlowTop.getColor();
+ }
+
+ /**
+ * Returns the bottom edge effect color.
+ *
+ * @return The bottom edge effect color.
+ * @see #setEdgeEffectColor(int)
+ * @see #setTopEdgeEffectColor(int)
+ * @see #setBottomEdgeEffectColor(int)
+ * @see #getTopEdgeEffectColor()
+ */
+ @ColorInt
+ public int getBottomEdgeEffectColor() {
+ return mEdgeGlowBottom.getColor();
+ }
+
+ /**
* Sets the recycler listener to be notified whenever a View is set aside in
* the recycler for later reuse. This listener can be used to free resources
* associated to the View.
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 7e42862..fa0af78 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -17,14 +17,15 @@
package android.widget;
import android.annotation.ColorInt;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.BlendMode;
import android.graphics.Canvas;
import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.os.Build;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
@@ -48,6 +49,12 @@
* {@link #draw(Canvas)} method.</p>
*/
public class EdgeEffect {
+
+ /**
+ * The default blend mode used by {@link EdgeEffect}.
+ */
+ public static final BlendMode DEFAULT_BLEND_MODE = BlendMode.SRC_ATOP;
+
@SuppressWarnings("UnusedDeclaration")
private static final String TAG = "EdgeEffect";
@@ -108,7 +115,7 @@
private float mPullDistance;
private final Rect mBounds = new Rect();
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769450)
private final Paint mPaint = new Paint();
private float mRadius;
private float mBaseGlowScale;
@@ -128,7 +135,7 @@
a.recycle();
mPaint.setColor((themeColor & 0xffffff) | 0x33000000);
mPaint.setStyle(Paint.Style.FILL);
- mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
+ mPaint.setBlendMode(DEFAULT_BLEND_MODE);
mInterpolator = new DecelerateInterpolator();
}
@@ -302,6 +309,22 @@
}
/**
+ * Set or clear the blend mode. A blend mode defines how source pixels
+ * (generated by a drawing command) are composited with the destination pixels
+ * (content of the render target).
+ * <p />
+ * Pass null to clear any previous blend mode.
+ * <p />
+ *
+ * @see BlendMode
+ *
+ * @param blendmode May be null. The blend mode to be installed in the paint
+ */
+ public void setBlendMode(@Nullable BlendMode blendmode) {
+ mPaint.setBlendMode(blendmode);
+ }
+
+ /**
* Return the color of this edge effect in argb.
* @return The color of this edge effect in argb
*/
@@ -310,6 +333,20 @@
return mPaint.getColor();
}
+
+ /**
+ * Returns the blend mode. A blend mode defines how source pixels
+ * (generated by a drawing command) are composited with the destination pixels
+ * (content of the render target).
+ * <p />
+ *
+ * @return BlendMode
+ */
+ @Nullable
+ public BlendMode getBlendMode() {
+ return mPaint.getBlendMode();
+ }
+
/**
* Draw into the provided canvas. Assumes that the canvas has been rotated
* accordingly and the size has been set. The effect will be drawn the full
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index d5b1a3d..249f499 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -1013,7 +1013,7 @@
}
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 0f4e23d..d876001 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1055,6 +1055,8 @@
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/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 06625b3..e2e66ce 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -32,6 +32,17 @@
android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
}
+void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName,
+ jstring driverVersionName, jlong driverVersionCode,
+ jstring appPackageName) {
+ ScopedUtfChars driverPackageNameChars(env, driverPackageName);
+ ScopedUtfChars driverVersionNameChars(env, driverVersionName);
+ ScopedUtfChars appPackageNameChars(env, appPackageName);
+ android::GraphicsEnv::getInstance().setGpuStats(driverPackageNameChars.c_str(),
+ driverVersionNameChars.c_str(),
+ driverVersionCode, appPackageNameChars.c_str());
+}
+
void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring devOptIn,
jobject rulesFd, jlong rulesOffset, jlong rulesLength) {
ScopedUtfChars pathChars(env, path);
@@ -68,6 +79,7 @@
const JNINativeMethod g_methods[] = {
{ "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
{ "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
+ { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
{ "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
{ "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
{ "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 4101c04..d493ddf 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1105,6 +1105,46 @@
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 @@
(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 67a56ae..464f249 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 68be005..6b8d8b1 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -178,12 +178,13 @@
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 984e942..3f7c00c 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 @@
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 a160451..d577653 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -259,6 +259,8 @@
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 60b04cf..07dd26e 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 fa3a549..46e14b4 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 881688b..53cae63 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/public.xml b/core/res/res/values/public.xml
index f84f1f1..e6d478a 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 2cb925a..ec57f79 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -210,6 +210,7 @@
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/contentcapture/UserDataRemovalRequestTest.java b/core/tests/coretests/src/android/view/contentcapture/UserDataRemovalRequestTest.java
deleted file mode 100644
index bebb2a8..0000000
--- 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 b84a098..213cd40 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 @@
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 @@
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 @@
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/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 0787d85..6264774 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -716,6 +716,14 @@
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 @@
case RAW_DEPTH:
case Y8:
case DEPTH_JPEG:
+ case HEIC:
return true;
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 73442db..e617c42 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1279,7 +1279,6 @@
* (content of the render target).
* <p />
* Pass null to clear any previous blend mode.
- * As a convenience, the parameter passed is also returned.
* <p />
*
* @see BlendMode
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 20303eb..81afd93 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -704,9 +704,29 @@
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 f29769b..d862182 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -237,6 +237,8 @@
// 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 @@
// 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 602cc3e..59eff64 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 @@
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 @@
*/
@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 @@
/**
* 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 @@
mSnrInDb = measurement.mSnrInDb;
mAutomaticGainControlLevelInDb = measurement.mAutomaticGainControlLevelInDb;
mCodeType = measurement.mCodeType;
+ mOtherCodeTypeName = measurement.mOtherCodeTypeName;
}
/**
@@ -1175,8 +1187,8 @@
/**
* 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 @@
}
/**
+ * 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 @@
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 @@
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 @@
gnssMeasurement.mSnrInDb = parcel.readDouble();
gnssMeasurement.mAutomaticGainControlLevelInDb = parcel.readDouble();
gnssMeasurement.mCodeType = parcel.readInt();
+ gnssMeasurement.mOtherCodeTypeName = parcel.readString();
return gnssMeasurement;
}
@@ -1306,6 +1344,7 @@
parcel.writeDouble(mSnrInDb);
parcel.writeDouble(mAutomaticGainControlLevelInDb);
parcel.writeInt(mCodeType);
+ parcel.writeString(mOtherCodeTypeName);
}
@Override
@@ -1384,6 +1423,9 @@
format,
"CodeType",
hasCodeType() ? getCodeTypeString() : null));
+ builder.append(String.format(
+ format,
+ "OtherCodeTypeName", mOtherCodeTypeName));
return builder.toString();
}
@@ -1409,6 +1451,7 @@
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 26b9b8c..70a343f 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -155,6 +155,13 @@
* 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 60ef1d9..6116429 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -821,6 +821,7 @@
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 @@
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 b77a884..d8a0bb3 100644
--- a/media/java/android/media/ImageUtils.java
+++ b/media/java/android/media/ImageUtils.java
@@ -36,8 +36,8 @@
* {@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 @@
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 @@
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 @@
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/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 458d847..01baadb 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 @@
}
}
-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 @@
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 821c6b2..19c1b88 100644
--- a/media/jni/android_media_Utils.h
+++ b/media/jni/android_media_Utils.h
@@ -119,7 +119,7 @@
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/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 478ee54..cd6abb2 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 fad93cb..6152b8c 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 @@
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/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 194332a..04fc258 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 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/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 360d296..0194624 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 @@
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/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 2f277e4..31b497d 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 @@
mSurfaceLayout = null;
SurfaceControl.openTransaction();
try {
- mSurfaceControl.destroy();
+ mSurfaceControl.remove();
mSurface.release();
} finally {
SurfaceControl.closeTransaction();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 32dc988..eaedec5 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.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 @@
}
}
}
-
- // 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/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 173d9a0..1957eb8 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 @@
*/
private boolean perUser;
- boolean usageInfoRequired;
-
public BasePermission(String _name, String _sourcePackageName, @PermissionType int _type) {
name = _name;
sourcePackageName = _sourcePackageName;
@@ -375,7 +373,6 @@
}
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 @@
permissionInfo.packageName = sourcePackageName;
permissionInfo.nonLocalizedLabel = name;
permissionInfo.protectionLevel = protectionLevel;
- permissionInfo.usageInfoRequired = usageInfoRequired;
return permissionInfo;
}
@@ -484,7 +480,6 @@
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 @@
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 @@
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 @@
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 @@
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 189d0f4..f4979746 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 @@
/** 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 a4413f9..38940d6 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 @@
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/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 6fcc331..0e14e46 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -143,7 +143,7 @@
void destroy() {
mSurfaceAnimator.cancelAnimation();
- mSurfaceControl.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 3246a87..2cc85e2 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 @@
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 c90f5bf..497e412 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 @@
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 c39060e..1373e18 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 @@
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 @@
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 7a8fd49..928b57c 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 @@
.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 434084c..9874920 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 @@
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 @@
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 3947bd4..84cd8d1 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 @@
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 c600e0f..5ea2451 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 @@
}
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 53cd5ea..7b742fd 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 @@
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 a054148..76f080b 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 @@
}
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/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index dea3597..e796b99 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 @@
}
try {
if (mSurfaceControl != null) {
- mSurfaceControl.destroy();
+ mSurfaceControl.remove();
}
} catch (RuntimeException e) {
Slog.w(TAG, "Error destroying surface in: " + this, e);
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 85909d5..72357ce 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.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 @@
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/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index ea5ab7b..dd5f32d 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 @@
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 @@
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 f99cd4b..5b32fe6 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 @@
mDimmer.updateDims(mTransaction, new Rect());
verify(mTransaction).show(getDimLayer());
- verify(dimLayer, never()).destroy();
+ verify(dimLayer, never()).remove();
}
@Test
@@ -212,7 +212,7 @@
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 @@
mDimmer.updateDims(mTransaction, new Rect());
verify(mTransaction).show(dimLayer);
- verify(dimLayer, never()).destroy();
+ verify(dimLayer, never()).remove();
}
@Test
@@ -269,7 +269,7 @@
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/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index edb395a..8c32e8c 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 @@
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 @@
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 @@
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 @@
verifyZeroInteractions(mSpec);
assertNotAnimating(mAnimatable);
assertTrue(mAnimatable.mFinishedCallbackCalled);
- verify(mTransaction).reparent(eq(mAnimatable.mLeash), eq(null));
+ verify(mTransaction).remove(eq(mAnimatable.mLeash));
}
@Test
@@ -171,11 +171,11 @@
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
@@ -197,7 +197,7 @@
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/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index be47153..8876214 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.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;
@@ -61,13 +62,15 @@
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;
@@ -78,10 +81,23 @@
* 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() {
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 257043b..a8d970e 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -48,6 +48,7 @@
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 @@
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 @@
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 450b305..6b86b862 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -89,6 +89,8 @@
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 4491a85..55440d2 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -158,6 +158,20 @@
}
}
}
+
+ 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 @@
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 3be87d9..24ebf4d 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -195,4 +195,22 @@
[(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 ad3bffac..dc585c1 100644
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ b/tools/stats_log_api_gen/test_collation.cpp
@@ -226,5 +226,25 @@
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