diff options
103 files changed, 1917 insertions, 1426 deletions
diff --git a/api/current.txt b/api/current.txt index b321c2248fda..abab90182b01 100644 --- a/api/current.txt +++ b/api/current.txt @@ -224,6 +224,11 @@ package android { public static final class R.attr { ctor public R.attr(); + field public static final int __removed1 = 16844185; // 0x1010599 + field public static final int __removed2 = 16844186; // 0x101059a + field public static final int __removed3 = 16844187; // 0x101059b + field public static final int __removed4 = 16844188; // 0x101059c + field public static final int __removed5 = 16844189; // 0x101059d field public static final int absListViewStyle = 16842858; // 0x101006a field public static final int accessibilityEventTypes = 16843648; // 0x1010380 field public static final int accessibilityFeedbackType = 16843650; // 0x1010382 @@ -484,10 +489,6 @@ package android { field public static final int dashGap = 16843175; // 0x10101a7 field public static final int dashWidth = 16843174; // 0x10101a6 field public static final int data = 16842798; // 0x101002e - field public static final int dataRetentionTime = 16844189; // 0x101059d - field public static final int dataSentOffDevice = 16844186; // 0x101059a - field public static final int dataSharedWithThirdParty = 16844187; // 0x101059b - field public static final int dataUsedForMonetization = 16844188; // 0x101059c field public static final int datePickerDialogTheme = 16843948; // 0x10104ac field public static final int datePickerMode = 16843955; // 0x10104b3 field public static final int datePickerStyle = 16843612; // 0x101035c @@ -1508,7 +1509,6 @@ package android { field @Deprecated public static final int unfocusedMonthDateColor = 16843588; // 0x1010344 field public static final int unselectedAlpha = 16843278; // 0x101020e field public static final int updatePeriodMillis = 16843344; // 0x1010250 - field public static final int usageInfoRequired = 16844185; // 0x1010599 field public static final int use32bitAbi = 16844053; // 0x1010515 field public static final int useAppZygote = 16844184; // 0x1010598 field public static final int useDefaultMargins = 16843641; // 0x1010379 @@ -10265,7 +10265,6 @@ package android.content { field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED"; field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED"; field public static final String ACTION_PASTE = "android.intent.action.PASTE"; - field public static final String ACTION_PERMISSION_USAGE_DETAILS = "android.intent.action.PERMISSION_USAGE_DETAILS"; field public static final String ACTION_PICK = "android.intent.action.PICK"; field public static final String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY"; field public static final String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED"; @@ -10391,7 +10390,6 @@ package android.content { field public static final String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE"; field public static final String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI"; field public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME"; - field public static final String EXTRA_PERMISSION_USAGE_PERMISSIONS = "android.intent.extra.PERMISSION_USAGE_PERMISSIONS"; field public static final String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER"; field public static final String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT"; field public static final String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY"; @@ -11356,8 +11354,8 @@ package android.content.pm { field public android.content.pm.ProviderInfo[] providers; field public android.content.pm.ActivityInfo[] receivers; field public android.content.pm.FeatureInfo[] reqFeatures; - field @Deprecated public String[] requestedPermissions; - field @Deprecated public int[] requestedPermissionsFlags; + field public String[] requestedPermissions; + field public int[] requestedPermissionsFlags; field public android.content.pm.ServiceInfo[] services; field public String sharedUserId; field public int sharedUserLabel; @@ -11365,7 +11363,6 @@ package android.content.pm { field public android.content.pm.SigningInfo signingInfo; field public String[] splitNames; field public int[] splitRevisionCodes; - field public android.content.pm.UsesPermissionInfo[] usesPermissions; field @Deprecated public int versionCode; field public String versionName; } @@ -11865,7 +11862,6 @@ package android.content.pm { field public String group; field public CharSequence nonLocalizedDescription; field @Deprecated public int protectionLevel; - field public boolean usageInfoRequired; } public final class ProviderInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable { @@ -12057,28 +12053,6 @@ package android.content.pm { field public static final android.os.Parcelable.Creator<android.content.pm.SigningInfo> CREATOR; } - public final class UsesPermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { - method public int describeContents(); - method public int getDataRetention(); - method public int getDataRetentionWeeks(); - method public int getDataSentOffDevice(); - method public int getDataSharedWithThirdParty(); - method public int getDataUsedForMonetization(); - method public int getFlags(); - method public String getPermission(); - field public static final android.os.Parcelable.Creator<android.content.pm.UsesPermissionInfo> CREATOR; - field public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 2; // 0x2 - field public static final int RETENTION_NOT_RETAINED = 1; // 0x1 - field public static final int RETENTION_SPECIFIED = 4; // 0x4 - field public static final int RETENTION_UNDEFINED = 0; // 0x0 - field public static final int RETENTION_UNLIMITED = 3; // 0x3 - field public static final int RETENTION_USER_SELECTED = 2; // 0x2 - field public static final int USAGE_NO = 3; // 0x3 - field public static final int USAGE_UNDEFINED = 0; // 0x0 - field public static final int USAGE_USER_TRIGGERED = 2; // 0x2 - field public static final int USAGE_YES = 1; // 0x1 - } - public final class VersionedPackage implements android.os.Parcelable { ctor public VersionedPackage(@NonNull String, int); ctor public VersionedPackage(@NonNull String, long); @@ -12356,8 +12330,10 @@ package android.content.res { public final class Resources.Theme { method public void applyStyle(int, boolean); method public void dump(int, String, String); + method public int[] getAttributeResolutionStack(@AttrRes int, @StyleRes int, @StyleRes int); method public int getChangingConfigurations(); method public android.graphics.drawable.Drawable getDrawable(@DrawableRes int) throws android.content.res.Resources.NotFoundException; + method @StyleRes public int getExplicitStyle(@Nullable android.util.AttributeSet); method public android.content.res.Resources getResources(); method @NonNull public android.content.res.TypedArray obtainStyledAttributes(@NonNull @StyleableRes int[]); method @NonNull public android.content.res.TypedArray obtainStyledAttributes(@StyleRes int, @NonNull @StyleableRes int[]) throws android.content.res.Resources.NotFoundException; @@ -14196,6 +14172,7 @@ package android.graphics { field public static final int DEPTH_POINT_CLOUD = 257; // 0x101 field public static final int FLEX_RGBA_8888 = 42; // 0x2a field public static final int FLEX_RGB_888 = 41; // 0x29 + field public static final int HEIC = 1212500294; // 0x48454946 field public static final int JPEG = 256; // 0x100 field public static final int NV16 = 16; // 0x10 field public static final int NV21 = 17; // 0x11 @@ -22643,6 +22620,7 @@ package android.location { method public int getCodeType(); method public int getConstellationType(); method public int getMultipathIndicator(); + method @NonNull public String getOtherCodeTypeName(); method public double getPseudorangeRateMetersPerSecond(); method public double getPseudorangeRateUncertaintyMetersPerSecond(); method public long getReceivedSvTimeNanos(); @@ -22668,10 +22646,11 @@ package android.location { field public static final int CODE_TYPE_A = 0; // 0x0 field public static final int CODE_TYPE_B = 1; // 0x1 field public static final int CODE_TYPE_C = 2; // 0x2 - field public static final int CODE_TYPE_CODELESS = 13; // 0xd field public static final int CODE_TYPE_I = 3; // 0x3 field public static final int CODE_TYPE_L = 4; // 0x4 field public static final int CODE_TYPE_M = 5; // 0x5 + field public static final int CODE_TYPE_N = 13; // 0xd + field public static final int CODE_TYPE_OTHER = 255; // 0xff field public static final int CODE_TYPE_P = 6; // 0x6 field public static final int CODE_TYPE_Q = 7; // 0x7 field public static final int CODE_TYPE_S = 8; // 0x8 @@ -50327,6 +50306,8 @@ package android.view { method @android.view.ViewDebug.ExportedProperty(category="drawing") public float getAlpha(); method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); + method @NonNull public java.util.List<java.lang.Integer> getAttributeResolutionStack(); + method @NonNull public java.util.Map<java.lang.Integer,java.lang.Integer> getAttributeSourceResourceMap(); method @android.view.ViewDebug.ExportedProperty @Nullable public String[] getAutofillHints(); method public final android.view.autofill.AutofillId getAutofillId(); method public int getAutofillType(); @@ -50357,6 +50338,7 @@ package android.view { method public void getDrawingRect(android.graphics.Rect); method public long getDrawingTime(); method @android.view.ViewDebug.ExportedProperty(category="drawing") public float getElevation(); + method @StyleRes public int getExplicitStyle(); method @android.view.ViewDebug.ExportedProperty public boolean getFilterTouchesWhenObscured(); method @android.view.ViewDebug.ExportedProperty public boolean getFitsSystemWindows(); method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.NOT_FOCUSABLE, to="NOT_FOCUSABLE"), @android.view.ViewDebug.IntToString(from=android.view.View.FOCUSABLE, to="FOCUSABLE"), @android.view.ViewDebug.IntToString(from=android.view.View.FOCUSABLE_AUTO, to="FOCUSABLE_AUTO")}, category="focus") public int getFocusable(); @@ -50651,6 +50633,7 @@ package android.view { method public static int resolveSizeAndState(int, int, int); method public boolean restoreDefaultFocus(); method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>); + method public final void saveAttributeDataForStyleable(@NonNull android.content.Context, @NonNull int[], @Nullable android.util.AttributeSet, @NonNull android.content.res.TypedArray, int, int); method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>); method public void scheduleDrawable(@NonNull android.graphics.drawable.Drawable, @NonNull Runnable, long); method public void scrollBy(int, int); @@ -54866,6 +54849,7 @@ package android.widget { 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 @@ package android.widget { 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 @@ package android.widget { 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 @@ package android.widget { 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 @@ package android.widget { 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 @@ package android.widget { 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 b7fc33950642..02718cbaac07 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5777,11 +5777,6 @@ package android.provider { 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 94e83eac96d2..2c8d08c49fdb 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -767,6 +767,7 @@ package android.location { method public void setCodeType(int); method public void setConstellationType(int); method public void setMultipathIndicator(int); + method public void setOtherCodeTypeName(@NonNull String); method public void setPseudorangeRateMetersPerSecond(double); method public void setPseudorangeRateUncertaintyMetersPerSecond(double); method public void setReceivedSvTimeNanos(long); @@ -2579,6 +2580,10 @@ package android.view { method public void setDisplayId(int); } + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface RemotableViewMethod { + method public abstract String asyncImpl() default ""; + } + @UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback { method public android.view.View getTooltipView(); method public static boolean isDefaultFocusHighlightEnabled(); @@ -2665,6 +2670,8 @@ package android.view.autofill { public final class AutofillId implements android.os.Parcelable { ctor public AutofillId(int); ctor public AutofillId(@NonNull android.view.autofill.AutofillId, int); + ctor public AutofillId(int, int); + ctor public AutofillId(@NonNull android.view.autofill.AutofillId, long, int); } public final class AutofillManager { @@ -2714,6 +2721,66 @@ package android.view.contentcapture { public final class ViewNode extends android.app.assist.AssistStructure.ViewNode { method @Nullable public android.view.autofill.AutofillId getParentAutofillId(); + method @Nullable public static android.view.contentcapture.ViewNode readFromParcel(@NonNull android.os.Parcel); + method public static void writeToParcel(@NonNull android.os.Parcel, @Nullable android.view.contentcapture.ViewNode, int); + } + + public static final class ViewNode.ViewStructureImpl extends android.view.ViewStructure { + ctor public ViewNode.ViewStructureImpl(@NonNull android.view.View); + ctor public ViewNode.ViewStructureImpl(@NonNull android.view.autofill.AutofillId, long, int); + method public int addChildCount(int); + method public void asyncCommit(); + method public android.view.ViewStructure asyncNewChild(int); + method public android.view.autofill.AutofillId getAutofillId(); + method public int getChildCount(); + method public android.os.Bundle getExtras(); + method public CharSequence getHint(); + method public android.view.contentcapture.ViewNode getNode(); + method public android.graphics.Rect getTempRect(); + method public CharSequence getText(); + method public int getTextSelectionEnd(); + method public int getTextSelectionStart(); + method public boolean hasExtras(); + method public android.view.ViewStructure newChild(int); + method public android.view.ViewStructure.HtmlInfo.Builder newHtmlInfoBuilder(String); + method public void setAccessibilityFocused(boolean); + method public void setActivated(boolean); + method public void setAlpha(float); + method public void setAssistBlocked(boolean); + method public void setAutofillHints(String[]); + method public void setAutofillId(android.view.autofill.AutofillId); + method public void setAutofillId(android.view.autofill.AutofillId, int); + method public void setAutofillOptions(CharSequence[]); + method public void setAutofillType(int); + method public void setAutofillValue(android.view.autofill.AutofillValue); + method public void setCheckable(boolean); + method public void setChecked(boolean); + method public void setChildCount(int); + method public void setClassName(String); + method public void setClickable(boolean); + method public void setContentDescription(CharSequence); + method public void setContextClickable(boolean); + method public void setDataIsSensitive(boolean); + method public void setDimens(int, int, int, int, int, int); + method public void setElevation(float); + method public void setEnabled(boolean); + method public void setFocusable(boolean); + method public void setFocused(boolean); + method public void setHint(CharSequence); + method public void setHtmlInfo(android.view.ViewStructure.HtmlInfo); + method public void setId(int, String, String, String); + method public void setInputType(int); + method public void setLocaleList(android.os.LocaleList); + method public void setLongClickable(boolean); + method public void setOpaque(boolean); + method public void setSelected(boolean); + method public void setText(CharSequence); + method public void setText(CharSequence, int, int); + method public void setTextLines(int[], int[]); + method public void setTextStyle(float, int, int, int); + method public void setTransformation(android.graphics.Matrix); + method public void setVisibility(int); + method public void setWebDomain(String); } } diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index 056add5c71b5..2fef407a8e3f 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -43,6 +43,7 @@ cc_library { "libidmap2/PrettyPrintVisitor.cpp", "libidmap2/RawPrintVisitor.cpp", "libidmap2/ResourceUtils.cpp", + "libidmap2/Result.cpp", "libidmap2/Xml.cpp", "libidmap2/ZipFile.cpp", ], @@ -93,6 +94,7 @@ cc_test { "tests/PrettyPrintVisitorTests.cpp", "tests/RawPrintVisitorTests.cpp", "tests/ResourceUtilsTests.cpp", + "tests/ResultTests.cpp", "tests/XmlTests.cpp", "tests/ZipFileTests.cpp", ], diff --git a/cmds/idmap2/include/idmap2/Result.h b/cmds/idmap2/include/idmap2/Result.h index 6189ea371ee1..d88dd5179610 100644 --- a/cmds/idmap2/include/idmap2/Result.h +++ b/cmds/idmap2/include/idmap2/Result.h @@ -18,6 +18,11 @@ #define IDMAP2_INCLUDE_IDMAP2_RESULT_H_ #include <optional> +#include <string> +#include <utility> +#include <variant> + +#include "android-base/logging.h" // CHECK namespace android::idmap2 { @@ -26,6 +31,125 @@ using Result = std::optional<T>; static constexpr std::nullopt_t kResultError = std::nullopt; +namespace v2 { + +using Unit = std::monostate; + +class Error { + public: + explicit Error(const Error& parent) = default; + + // NOLINTNEXTLINE(cert-dcl50-cpp) + explicit Error(const char* fmt, ...) __attribute__((__format__(printf, 2, 3))); + + // NOLINTNEXTLINE(cert-dcl50-cpp) + explicit Error(const Error& parent, const char* fmt, ...) + __attribute__((__format__(printf, 3, 4))); + + inline std::string GetMessage() const { + return msg_; + } + + private: + std::string msg_; +}; + +template <typename T> +class Result { + public: + Result(const T& value); // NOLINT(runtime/explicit) + Result(T&& value) noexcept; // NOLINT(runtime/explicit) + + Result(const Error& error); // NOLINT(runtime/explicit) + Result(Error&& error) noexcept; // NOLINT(runtime/explicit) + + Result(const Result& error) = default; + + Result& operator=(const Result& rhs) = default; + Result& operator=(Result&& rhs) noexcept = default; + + explicit operator bool() const; + + constexpr const T& operator*() const&; + T& operator*() &; + + constexpr const T* operator->() const&; + T* operator->() &; + + std::string GetErrorMessage() const; + Error GetError() const; + + private: + bool is_ok() const; + + std::variant<T, Error> data_; +}; + +template <typename T> +Result<T>::Result(const T& value) : data_(std::in_place_type<T>, value) { +} + +template <typename T> +Result<T>::Result(T&& value) noexcept : data_(std::in_place_type<T>, std::forward<T>(value)) { +} + +template <typename T> +Result<T>::Result(const Error& error) : data_(std::in_place_type<Error>, error) { +} + +template <typename T> +Result<T>::Result(Error&& error) noexcept + : data_(std::in_place_type<Error>, std::forward<Error>(error)) { +} + +template <typename T> +Result<T>::operator bool() const { + return is_ok(); +} + +template <typename T> +constexpr const T& Result<T>::operator*() const& { + CHECK(is_ok()) << "Result<T>::operator* called in ERROR state"; + return std::get<T>(data_); +} + +template <typename T> +T& Result<T>::operator*() & { + CHECK(is_ok()) << "Result<T>::operator* called in ERROR state"; + return std::get<T>(data_); +} + +template <typename T> +constexpr const T* Result<T>::operator->() const& { + CHECK(is_ok()) << "Result<T>::operator-> called in ERROR state"; + return &std::get<T>(data_); +} + +template <typename T> +T* Result<T>::operator->() & { + CHECK(is_ok()) << "Result<T>::operator-> called in ERROR state"; + return &std::get<T>(data_); +} + +template <typename T> +inline std::string Result<T>::GetErrorMessage() const { + CHECK(!is_ok()) << "Result<T>::GetErrorMessage called in OK state"; + return std::get<Error>(data_).GetMessage(); +} + +template <typename T> +inline Error Result<T>::GetError() const { + CHECK(!is_ok()) << "Result<T>::GetError called in OK state"; + return Error(std::get<Error>(data_)); +} + +template <typename T> +inline bool Result<T>::is_ok() const { + return std::holds_alternative<T>(data_); +} + +} // namespace v2 + } // namespace android::idmap2 #endif // IDMAP2_INCLUDE_IDMAP2_RESULT_H_ diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index fa5ac8ea11dc..b19d7a971cb8 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -117,6 +117,12 @@ const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) { return loaded_arsc.GetPackageById(id); } +Result<uint32_t> GetCrc(const ZipFile& zip) { + const Result<uint32_t> a = zip.Crc("resources.arsc"); + const Result<uint32_t> b = zip.Crc("AndroidManifest.xml"); + return a && b ? Result<uint32_t>(*a ^ *b) : kResultError; +} + } // namespace std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) { @@ -153,7 +159,7 @@ bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { return false; } - Result<uint32_t> target_crc = target_zip->Crc("resources.arsc"); + Result<uint32_t> target_crc = GetCrc(*target_zip); if (!target_crc) { out_error << "error: failed to get target crc" << std::endl; return false; @@ -173,7 +179,7 @@ bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { return false; } - Result<uint32_t> overlay_crc = overlay_zip->Crc("resources.arsc"); + Result<uint32_t> overlay_crc = GetCrc(*overlay_zip); if (!overlay_crc) { out_error << "error: failed to get overlay crc" << std::endl; return false; @@ -356,14 +362,14 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( header->magic_ = kIdmapMagic; header->version_ = kIdmapCurrentVersion; - Result<uint32_t> crc = target_zip->Crc("resources.arsc"); + Result<uint32_t> crc = GetCrc(*target_zip); if (!crc) { out_error << "error: failed to get zip crc for target" << std::endl; return nullptr; } header->target_crc_ = *crc; - crc = overlay_zip->Crc("resources.arsc"); + crc = GetCrc(*overlay_zip); if (!crc) { out_error << "error: failed to get zip crc for overlay" << std::endl; return nullptr; diff --git a/cmds/idmap2/libidmap2/Result.cpp b/cmds/idmap2/libidmap2/Result.cpp new file mode 100644 index 000000000000..a5c999916c72 --- /dev/null +++ b/cmds/idmap2/libidmap2/Result.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cstdarg> + +#include "android-base/stringprintf.h" + +#include "idmap2/Result.h" + +namespace android::idmap2 { + +v2::Error::Error(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + base::StringAppendV(&msg_, fmt, ap); + va_end(ap); +} + +v2::Error::Error(const Error& parent, const char* fmt, ...) : msg_(parent.msg_) { + msg_.append(" -> "); + + va_list ap; + va_start(ap, fmt); + base::StringAppendV(&msg_, fmt, ap); + va_end(ap); +} + +} // namespace android::idmap2 diff --git a/cmds/idmap2/static-checks.sh b/cmds/idmap2/static-checks.sh index 067000a38b83..41d3c69540b2 100755 --- a/cmds/idmap2/static-checks.sh +++ b/cmds/idmap2/static-checks.sh @@ -74,6 +74,7 @@ function _cpplint() -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 9e27ccd7cfbb..b40521f054af 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -191,8 +191,8 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U); - ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xab7cf70d); - ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xd470336b); + ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xdd53ca29); + ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xa71ccd77); ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path); ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path); ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path); diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index b1ca12557dcb..a5588c330d85 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -52,8 +52,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos); ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos); - ASSERT_NE(stream.str().find("00000008: ab7cf70d target crc\n"), std::string::npos); - ASSERT_NE(stream.str().find("0000000c: d470336b overlay crc\n"), std::string::npos); + ASSERT_NE(stream.str().find("00000008: dd53ca29 target crc\n"), std::string::npos); + ASSERT_NE(stream.str().find("0000000c: a71ccd77 overlay crc\n"), std::string::npos); ASSERT_NE(stream.str().find("0000021c: 00000000 0x7f010000 -> 0x7f010000 integer/int1\n"), std::string::npos); } diff --git a/cmds/idmap2/tests/ResultTests.cpp b/cmds/idmap2/tests/ResultTests.cpp new file mode 100644 index 000000000000..d82f0c475ea9 --- /dev/null +++ b/cmds/idmap2/tests/ResultTests.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <memory> +#include <type_traits> +#include <utility> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "idmap2/Result.h" + +namespace android::idmap2 { + +struct Container { + uint32_t value; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +// Tests: Error + +TEST(ResultTests, ErrorTraits) { + ASSERT_TRUE(std::is_move_constructible<v2::Error>::value); + ASSERT_TRUE(std::is_move_assignable<v2::Error>::value); + ASSERT_TRUE(std::is_copy_constructible<v2::Error>::value); + ASSERT_TRUE(std::is_copy_assignable<v2::Error>::value); +} + +TEST(ResultTests, ErrorCtorFormat) { + v2::Error e("%s=0x%08x", "resid", 0x7f010002); + ASSERT_EQ(e.GetMessage(), "resid=0x7f010002"); +} + +TEST(ResultTests, ErrorPropagateParent) { + v2::Error e1("foo"); + ASSERT_EQ(e1.GetMessage(), "foo"); + + v2::Error e2(e1, "bar"); + ASSERT_EQ(e2.GetMessage(), "foo -> bar"); + + v2::Error e3(e2); // NOLINT(performance-unnecessary-copy-initialization) + ASSERT_EQ(e3.GetMessage(), "foo -> bar"); + + v2::Error e4(e3, "%02d", 1); + ASSERT_EQ(e4.GetMessage(), "foo -> bar -> 01"); +} + +// Tests: Result<T> member functions + +// Result(const Result&) +TEST(ResultTests, CopyConstructor) { + v2::Result<uint32_t> r1(42U); + + v2::Result<uint32_t> r2(r1); + ASSERT_TRUE(r2); + ASSERT_EQ(*r2, 42U); + + v2::Result<uint32_t> r3 = r2; + ASSERT_TRUE(r3); + ASSERT_EQ(*r3, 42U); +} + +// Result(const T&) +TEST(ResultTests, Constructor) { + uint32_t v = 42U; + v2::Result<uint32_t> r1(v); + ASSERT_TRUE(r1); + ASSERT_EQ(*r1, 42U); + + v2::Error e("foo"); + v2::Result<uint32_t> r2(e); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +// Result(const T&&) +TEST(ResultTests, MoveConstructor) { + v2::Result<uint32_t> r1(42U); + ASSERT_TRUE(r1); + ASSERT_EQ(*r1, 42U); + + v2::Result<uint32_t> r2(v2::Error("foo")); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +// operator= +TEST(ResultTests, CopyAssignmentOperator) { + // note: 'Result<...> r2 = r1;' calls the copy ctor + v2::Result<uint32_t> r1(42U); + v2::Result<uint32_t> r2(0U); + r2 = r1; + ASSERT_TRUE(r2); + ASSERT_EQ(*r2, 42U); + + v2::Result<uint32_t> r3(v2::Error("foo")); + r2 = r3; + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +TEST(ResultTests, MoveAssignmentOperator) { + v2::Result<uint32_t> r(0U); + r = v2::Result<uint32_t>(42U); + ASSERT_TRUE(r); + ASSERT_EQ(*r, 42U); + + r = v2::Result<uint32_t>(v2::Error("foo")); + ASSERT_FALSE(r); + ASSERT_EQ(r.GetErrorMessage(), "foo"); +} + +// operator bool() +TEST(ResultTests, BoolOperator) { + v2::Result<uint32_t> r1(42U); + ASSERT_TRUE(r1); + ASSERT_EQ(*r1, 42U); + + v2::Result<uint32_t> r2(v2::Error("foo")); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +// operator* +TEST(ResultTests, IndirectionOperator) { + const v2::Result<uint32_t> r1(42U); + ASSERT_TRUE(r1); + ASSERT_EQ(*r1, 42U); + + const v2::Result<Container> r2(Container{42U}); + ASSERT_TRUE(r2); + const Container& c = *r2; + ASSERT_EQ(c.value, 42U); + + v2::Result<Container> r3(Container{42U}); + ASSERT_TRUE(r3); + ASSERT_EQ((*r3).value, 42U); + (*r3).value = 0U; + ASSERT_EQ((*r3).value, 0U); +} + +// operator-> +TEST(ResultTests, DereferenceOperator) { + const v2::Result<Container> r1(Container{42U}); + ASSERT_TRUE(r1); + ASSERT_EQ(r1->value, 42U); + + v2::Result<Container> r2(Container{42U}); + ASSERT_TRUE(r2); + ASSERT_EQ(r2->value, 42U); + r2->value = 0U; + ASSERT_EQ(r2->value, 0U); +} + +// Tests: intended use of Result<T> + +TEST(ResultTests, ResultTraits) { + ASSERT_TRUE(std::is_move_constructible<v2::Result<uint32_t>>::value); + ASSERT_TRUE(std::is_move_assignable<v2::Result<uint32_t>>::value); + ASSERT_TRUE(std::is_copy_constructible<v2::Result<uint32_t>>::value); + ASSERT_TRUE(std::is_copy_assignable<v2::Result<uint32_t>>::value); +} + +TEST(ResultTests, UnitTypeResult) { + v2::Result<v2::Unit> r(v2::Unit{}); + ASSERT_TRUE(r); +} + +struct RefCountData { + int ctor; // NOLINT(misc-non-private-member-variables-in-classes) + int copy_ctor; // NOLINT(misc-non-private-member-variables-in-classes) + int dtor; // NOLINT(misc-non-private-member-variables-in-classes) + int move; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +class RefCountContainer { + public: + explicit RefCountContainer(RefCountData& data) : data_(data) { + ++data_.ctor; + } + + RefCountContainer(RefCountContainer const&) = delete; + + RefCountContainer(RefCountContainer&& rhs) noexcept : data_(rhs.data_) { + ++data_.copy_ctor; + } + + RefCountContainer& operator=(RefCountContainer const&) = delete; + + RefCountContainer& operator=(RefCountContainer&& rhs) noexcept { + data_ = rhs.data_; + ++data_.move; + return *this; + } + + ~RefCountContainer() { + ++data_.dtor; + } + + private: + RefCountData& data_; +}; + +TEST(ResultTests, ReferenceCount) { + ASSERT_TRUE(std::is_move_constructible<RefCountContainer>::value); + ASSERT_TRUE(std::is_move_assignable<RefCountContainer>::value); + ASSERT_FALSE(std::is_copy_constructible<RefCountContainer>::value); + ASSERT_FALSE(std::is_copy_assignable<RefCountContainer>::value); + + RefCountData rc{0, 0, 0, 0}; + { v2::Result<RefCountContainer> r(RefCountContainer{rc}); } + ASSERT_EQ(rc.ctor, 1); + ASSERT_EQ(rc.copy_ctor, 1); + ASSERT_EQ(rc.move, 0); + ASSERT_EQ(rc.dtor, 2); +} + +v2::Result<Container> CreateContainer(bool succeed) { + if (!succeed) { + return v2::Error("foo"); + } + return Container{42U}; +} + +TEST(ResultTests, FunctionReturn) { + auto r1 = CreateContainer(true); + ASSERT_TRUE(r1); + ASSERT_EQ(r1->value, 42U); + + auto r2 = CreateContainer(false); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); + ASSERT_EQ(r2.GetError().GetMessage(), "foo"); +} + +v2::Result<Container> FailToCreateContainer() { + auto container = CreateContainer(false); + if (!container) { + return v2::Error(container.GetError(), "bar"); + } + return container; +} + +TEST(ResultTests, CascadeError) { + auto container = FailToCreateContainer(); + ASSERT_FALSE(container); + ASSERT_EQ(container.GetErrorMessage(), "foo -> bar"); +} + +struct NoCopyContainer { + uint32_t value; // NOLINT(misc-non-private-member-variables-in-classes) + DISALLOW_COPY_AND_ASSIGN(NoCopyContainer); +}; + +v2::Result<std::unique_ptr<NoCopyContainer>> CreateNoCopyContainer(bool succeed) { + if (!succeed) { + return v2::Error("foo"); + } + std::unique_ptr<NoCopyContainer> p(new NoCopyContainer{0U}); + p->value = 42U; + return std::move(p); +} + +TEST(ResultTests, UniquePtr) { + auto r1 = CreateNoCopyContainer(true); + ASSERT_TRUE(r1); + ASSERT_EQ((*r1)->value, 42U); + (*r1)->value = 0U; + ASSERT_EQ((*r1)->value, 0U); + + auto r2 = CreateNoCopyContainer(false); + ASSERT_FALSE(r2); + ASSERT_EQ(r2.GetErrorMessage(), "foo"); +} + +} // namespace android::idmap2 diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto index e33bd8c97a07..2a3eee2a7e18 100644 --- a/cmds/statsd/src/atom_field_options.proto +++ b/cmds/statsd/src/atom_field_options.proto @@ -82,4 +82,6 @@ extend google.protobuf.FieldOptions { optional bool is_uid = 50001 [default = false]; optional LogMode log_mode = 50002 [default = MODE_AUTOMATIC]; + + optional bool allow_from_any_uid = 50003 [default = false]; }
\ No newline at end of file diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 07aced6846a4..4f17d69f23f2 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -110,7 +110,7 @@ message Atom { PacketWakeupOccurred packet_wakeup_occurred = 44; WallClockTimeShifted wall_clock_time_shifted = 45; AnomalyDetected anomaly_detected = 46; - AppBreadcrumbReported app_breadcrumb_reported = 47; + AppBreadcrumbReported app_breadcrumb_reported = 47 [(allow_from_any_uid) = true]; AppStartOccurred app_start_occurred = 48; AppStartCanceled app_start_canceled = 49; AppStartFullyDrawn app_start_fully_drawn = 50; @@ -121,7 +121,7 @@ message Atom { AppStartMemoryStateCaptured app_start_memory_state_captured = 55; ShutdownSequenceReported shutdown_sequence_reported = 56; BootSequenceReported boot_sequence_reported = 57; - DaveyOccurred davey_occurred = 58; + DaveyOccurred davey_occurred = 58 [(allow_from_any_uid) = true]; OverlayStateChanged overlay_state_changed = 59; ForegroundServiceStateChanged foreground_service_state_changed = 60; CallStateChanged call_state_changed = 61; diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index ca681176c54a..6ed6ab500597 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -241,12 +241,22 @@ void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs, VLOG("=========================Metric Reports End=========================="); } -// Consume the stats log if it's interesting to this metric. -void MetricsManager::onLogEvent(const LogEvent& event) { - if (!mConfigValid) { - return; + +bool MetricsManager::checkLogCredentials(const LogEvent& event) { + if (android::util::AtomsInfo::kWhitelistedAtoms.find(event.GetTagId()) != + android::util::AtomsInfo::kWhitelistedAtoms.end()) + { + return true; } + std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex); + if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) { + VLOG("log source %d not on the whitelist", event.GetUid()); + return false; + } + return true; +} +bool MetricsManager::eventSanityCheck(const LogEvent& event) { if (event.GetTagId() == android::util::APP_BREADCRUMB_REPORTED) { // Check that app breadcrumb reported fields are valid. status_t err = NO_ERROR; @@ -256,23 +266,23 @@ void MetricsManager::onLogEvent(const LogEvent& event) { long appHookUid = event.GetLong(event.size()-2, &err); if (err != NO_ERROR ) { VLOG("APP_BREADCRUMB_REPORTED had error when parsing the uid"); - return; + return false; } int32_t loggerUid = event.GetUid(); if (loggerUid != appHookUid && loggerUid != AID_STATSD) { VLOG("APP_BREADCRUMB_REPORTED has invalid uid: claimed %ld but caller is %d", appHookUid, loggerUid); - return; + return false; } // The state must be from 0,3. This part of code must be manually updated. long appHookState = event.GetLong(event.size(), &err); if (err != NO_ERROR ) { VLOG("APP_BREADCRUMB_REPORTED had error when parsing the state field"); - return; + return false; } else if (appHookState < 0 || appHookState > 3) { VLOG("APP_BREADCRUMB_REPORTED does not have valid state %ld", appHookState); - return; + return false; } } else if (event.GetTagId() == android::util::DAVEY_OCCURRED) { // Daveys can be logged from any app since they are logged in libs/hwui/JankTracker.cpp. @@ -283,31 +293,42 @@ void MetricsManager::onLogEvent(const LogEvent& event) { long jankUid = event.GetLong(1, &err); if (err != NO_ERROR ) { VLOG("Davey occurred had error when parsing the uid"); - return; + return false; } int32_t loggerUid = event.GetUid(); if (loggerUid != jankUid && loggerUid != AID_STATSD) { VLOG("DAVEY_OCCURRED has invalid uid: claimed %ld but caller is %d", jankUid, loggerUid); - return; + return false; } long duration = event.GetLong(event.size(), &err); if (err != NO_ERROR ) { VLOG("Davey occurred had error when parsing the duration"); - return; + return false; } else if (duration > 100000) { VLOG("Davey duration is unreasonably long: %ld", duration); - return; - } - } else { - std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex); - if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) { - VLOG("log source %d not on the whitelist", event.GetUid()); - return; + return false; } } + return true; +} + +// Consume the stats log if it's interesting to this metric. +void MetricsManager::onLogEvent(const LogEvent& event) { + if (!mConfigValid) { + return; + } + + if (!checkLogCredentials(event)) { + return; + } + + if (!eventSanityCheck(event)) { + return; + } + int tagId = event.GetTagId(); int64_t eventTimeNs = event.GetElapsedTimestampNs(); diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 80982c37dc6a..fdc28ea7f219 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -49,6 +49,10 @@ public: // Return whether the configuration is valid. bool isConfigValid() const; + bool checkLogCredentials(const LogEvent& event); + + bool eventSanityCheck(const LogEvent& event); + void onLogEvent(const LogEvent& event); void onAnomalyAlarmFired( diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index d52c9ef28132..1bd3ef20a578 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -435,6 +435,10 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven } } mHasGlobalBase = true; + + // We can probably flush the bucket. Since we used bucketEndTime when calling + // #onMatchedLogEventInternalLocked, the current bucket will not have been flushed. + flushIfNeededLocked(realEventTime); } else { VLOG("No need to commit data on condition false."); } diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 40cf2e1f3823..0cfefa9e3eb4 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -61,6 +61,7 @@ public: if (!mSplitBucketForAppUpgrade) { return; } + flushIfNeededLocked(eventTimeNs - 1); if (mIsPulled && mCondition) { pullAndMatchEventsLocked(eventTimeNs - 1); } @@ -212,6 +213,7 @@ private: FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition); FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade); FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade); + FRIEND_TEST(ValueMetricProducerTest, TestPartialBucketCreated); FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse); FRIEND_TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled); FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition); diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 29793460e674..91b98ecffa29 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -167,9 +167,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(11, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(8, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); @@ -184,11 +185,12 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(23, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(12, curInterval.value.long_value); EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); - EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); - EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); + EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); + EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); @@ -202,11 +204,80 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(36, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(13, curInterval.value.long_value); EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); - EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size()); - EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); + EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); + EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value); + EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second[2].values[0].long_value); +} + +TEST(ValueMetricProducerTest, TestPartialBucketCreated) { + ValueMetric metric; + metric.set_id(metricId); + metric.set_bucket(ONE_MINUTE); + metric.mutable_value_field()->set_field(tagId); + metric.mutable_value_field()->add_child()->set_field(2); + metric.set_max_pull_delay_sec(INT_MAX); + + UidMap uidMap; + SimpleAtomMatcher atomMatcher; + atomMatcher.set_atom_id(tagId); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); + sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, _)) + // Initialize bucket. + .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + data->clear(); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); + event->write(tagId); + event->write(1); + event->init(); + data->push_back(event); + return true; + })) + // Partial bucket. + .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + data->clear(); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10); + event->write(tagId); + event->write(5); + event->init(); + data->push_back(event); + return true; + })); + + ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, + logEventMatcherIndex, eventMatcherWizard, tagId, + bucketStartTimeNs, bucketStartTimeNs, pullerManager); + + // First bucket ends. + vector<shared_ptr<LogEvent>> allData; + allData.clear(); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10); + event->write(tagId); + event->write(2); + event->init(); + allData.push_back(event); + valueProducer.onDataPulled(allData, /** success */ true); + + // Partial buckets created in 2nd bucket. + valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1); + + // One full bucket and one partial bucket. + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + vector<ValueBucket> buckets = valueProducer.mPastBuckets.begin()->second; + EXPECT_EQ(2UL, buckets.size()); + // Full bucket (2 - 1) + EXPECT_EQ(1, buckets[0].values[0].long_value); + // Full bucket (5 - 3) + EXPECT_EQ(3, buckets[1].values[0].long_value); } /* @@ -264,9 +335,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(11, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(8, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); @@ -275,16 +347,15 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { event->init(); allData.push_back(event); valueProducer.onDataPulled(allData, /** succeed */ true); - // has one slice - EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); - curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; + // No new data seen, so data has been cleared. + EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(11, curInterval.base.long_value); - // no events caused flush of bucket - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(8, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); @@ -363,9 +434,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(10, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(10, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); @@ -378,11 +450,12 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(36, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(26, curInterval.value.long_value); EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); - EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); - EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); + EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size()); + EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); + EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value); } /* @@ -456,9 +529,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) { curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(36, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(26, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); } /* @@ -532,9 +606,10 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) { curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(110, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); + EXPECT_EQ(false, curInterval.hasValue); EXPECT_EQ(10, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1); @@ -651,8 +726,8 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) { event->init(); allData.push_back(event); valueProducer.onDataPulled(allData, /** succeed */ true); - EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); - EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs); + EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs); EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value); } @@ -694,7 +769,7 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) { valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1); EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); - EXPECT_EQ(bucketStartTimeNs, valueProducer.mCurrentBucketStartTimeNs); + EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs); } TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) { @@ -1018,9 +1093,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) { // tartUpdated:false sum:12 EXPECT_EQ(true, curInterval.hasBase); EXPECT_EQ(23, curInterval.base.long_value); - EXPECT_EQ(true, curInterval.hasValue); - EXPECT_EQ(12, curInterval.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(false, curInterval.hasValue); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); // pull 3 come late. // The previous bucket gets closed with error. (Has start value 23, no ending) @@ -1681,7 +1756,7 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval1.hasBase); EXPECT_EQ(11, interval1.base.long_value); - EXPECT_EQ(true, interval1.hasValue); + EXPECT_EQ(false, interval1.hasValue); EXPECT_EQ(8, interval1.value.long_value); auto it = valueProducer.mCurrentSlicedBucket.begin(); @@ -1695,9 +1770,14 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); EXPECT_EQ(true, interval2.hasBase); EXPECT_EQ(4, interval2.base.long_value); - EXPECT_EQ(true, interval2.hasValue); + EXPECT_EQ(false, interval2.hasValue); EXPECT_EQ(4, interval2.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + + EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); + auto iterator = valueProducer.mPastBuckets.begin(); + EXPECT_EQ(8, iterator->second[0].values[0].long_value); + iterator++; + EXPECT_EQ(4, iterator->second[0].values[0].long_value); } /* @@ -1766,7 +1846,7 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval1.hasBase); EXPECT_EQ(11, interval1.base.long_value); - EXPECT_EQ(true, interval1.hasValue); + EXPECT_EQ(false, interval1.hasValue); EXPECT_EQ(8, interval1.value.long_value); auto it = valueProducer.mCurrentSlicedBucket.begin(); @@ -1780,9 +1860,9 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); EXPECT_EQ(true, interval2.hasBase); EXPECT_EQ(4, interval2.base.long_value); - EXPECT_EQ(true, interval2.hasValue); + EXPECT_EQ(false, interval2.hasValue); EXPECT_EQ(4, interval2.value.long_value); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); // next pull somehow did not happen, skip to end of bucket 3 allData.clear(); @@ -1793,11 +1873,11 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { allData.push_back(event1); valueProducer.onDataPulled(allData, /** succeed */ true); - EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); + EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval2.hasBase); - EXPECT_EQ(5, interval2.base.long_value); + EXPECT_EQ(4, interval2.base.long_value); EXPECT_EQ(false, interval2.hasValue); - EXPECT_EQ(false, interval1.hasBase); + EXPECT_EQ(true, interval1.hasBase); EXPECT_EQ(false, interval1.hasValue); EXPECT_EQ(true, valueProducer.mHasGlobalBase); EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); @@ -1817,13 +1897,13 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval2.hasBase); - EXPECT_EQ(13, interval2.base.long_value); - EXPECT_EQ(true, interval2.hasValue); - EXPECT_EQ(8, interval2.value.long_value); + EXPECT_EQ(5, interval2.base.long_value); + EXPECT_EQ(false, interval2.hasValue); + EXPECT_EQ(5, interval2.value.long_value); EXPECT_EQ(true, interval1.hasBase); - EXPECT_EQ(5, interval1.base.long_value); - EXPECT_EQ(true, interval1.hasValue); - EXPECT_EQ(5, interval1.value.long_value); + EXPECT_EQ(13, interval1.base.long_value); + EXPECT_EQ(false, interval1.hasValue); + EXPECT_EQ(8, interval1.value.long_value); EXPECT_EQ(true, valueProducer.mHasGlobalBase); EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); } @@ -1892,9 +1972,11 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); EXPECT_EQ(true, interval1.hasBase); EXPECT_EQ(11, interval1.base.long_value); - EXPECT_EQ(true, interval1.hasValue); + EXPECT_EQ(false, interval1.hasValue); EXPECT_EQ(8, interval1.value.long_value); - EXPECT_TRUE(interval1.seenNewData); + EXPECT_FALSE(interval1.seenNewData); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); auto it = valueProducer.mCurrentSlicedBucket.begin(); for (; it != valueProducer.mCurrentSlicedBucket.end(); it++) { @@ -1908,8 +1990,8 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { EXPECT_EQ(true, interval2.hasBase); EXPECT_EQ(4, interval2.base.long_value); EXPECT_EQ(false, interval2.hasValue); - EXPECT_TRUE(interval2.seenNewData); - EXPECT_EQ(0UL, valueProducer.mPastBuckets.size()); + EXPECT_FALSE(interval2.seenNewData); + EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); // next pull somehow did not happen, skip to end of bucket 3 allData.clear(); @@ -1920,35 +2002,34 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { allData.push_back(event1); valueProducer.onDataPulled(allData, /** succeed */ true); - EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size()); - - EXPECT_EQ(false, interval1.hasBase); - EXPECT_EQ(false, interval1.hasValue); - EXPECT_EQ(8, interval1.value.long_value); - // on probation now - EXPECT_FALSE(interval1.seenNewData); - + // Only one interval left. One was trimmed. + EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); + interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0]; + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); EXPECT_EQ(true, interval2.hasBase); EXPECT_EQ(5, interval2.base.long_value); EXPECT_EQ(false, interval2.hasValue); - // back to good status - EXPECT_TRUE(interval2.seenNewData); + EXPECT_FALSE(interval2.seenNewData); EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); allData.clear(); event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1); event1->write(2); - event1->write(13); + event1->write(14); event1->init(); allData.push_back(event1); valueProducer.onDataPulled(allData, /** succeed */ true); - EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); + interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0]; EXPECT_EQ(true, interval2.hasBase); - EXPECT_EQ(13, interval2.base.long_value); - EXPECT_EQ(true, interval2.hasValue); - EXPECT_EQ(8, interval2.value.long_value); - EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); + EXPECT_EQ(14, interval2.base.long_value); + EXPECT_EQ(false, interval2.hasValue); + EXPECT_FALSE(interval2.seenNewData); + EXPECT_EQ(2UL, valueProducer.mPastBuckets.size()); + auto iterator = valueProducer.mPastBuckets.begin(); + EXPECT_EQ(9, iterator->second[0].values[0].long_value); + iterator++; + EXPECT_EQ(8, iterator->second[0].values[0].long_value); } TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 21d66e567a81..cc419b8d837a 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -4565,16 +4565,25 @@ public final class ActivityThread extends ClientTransactionHandler { } private void onCoreSettingsChange() { - boolean debugViewAttributes = - mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; - if (debugViewAttributes != View.mDebugViewAttributes) { - View.mDebugViewAttributes = debugViewAttributes; - + if (updateDebugViewAttributeState()) { // request all activities to relaunch for the changes to take place relaunchAllActivities(); } } + private boolean updateDebugViewAttributeState() { + boolean previousState = View.sDebugViewAttributes; + + View.sDebugViewAttributesApplicationPackage = mCoreSettings.getString( + Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, ""); + String currentPackage = (mBoundApplication != null && mBoundApplication.appInfo != null) + ? mBoundApplication.appInfo.packageName : ""; + View.sDebugViewAttributes = + mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0 + || View.sDebugViewAttributesApplicationPackage.equals(currentPackage); + return previousState != View.sDebugViewAttributes; + } + private void relaunchAllActivities() { for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) { final Activity activity = entry.getValue().activity; @@ -5950,8 +5959,7 @@ public final class ActivityThread extends ClientTransactionHandler { // true : use 24 hour format. DateFormat.set24HourTimePref(is24Hr); - View.mDebugViewAttributes = - mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; + updateDebugViewAttributeState(); StrictMode.initThreadDefaults(data.appInfo); StrictMode.initVmDefaults(data.appInfo); diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index a3021f371e19..d781a96420c7 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -817,28 +817,6 @@ public class Intent implements Parcelable, Cloneable { = "android.intent.action.SHOW_APP_INFO"; /** - * Activity Action: Start an activity to show the app's detailed usage information for - * permission protected data. - * - * The Intent contains an extra {@link #EXTRA_PERMISSION_USAGE_PERMISSIONS} that is of - * type {@code String[]} and contains the specific permissions to show information for. - * - * Apps should handle this intent if they want to provide more information about permission - * usage to users beyond the information provided in the manifest. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_PERMISSION_USAGE_DETAILS = - "android.intent.action.PERMISSION_USAGE_DETAILS"; - - /** - * The name of the extra used to contain the permissions in - * {@link #ACTION_PERMISSION_USAGE_DETAILS}. - * @see #ACTION_PERMISSION_USAGE_DETAILS - */ - public static final String EXTRA_PERMISSION_USAGE_PERMISSIONS = - "android.intent.extra.PERMISSION_USAGE_PERMISSIONS"; - - /** * Represents a shortcut/live folder icon resource. * * @see Intent#ACTION_CREATE_SHORTCUT diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index 6d22277a5384..27a5b392855e 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -204,10 +204,7 @@ public class PackageInfo implements Parcelable { * {@link PackageManager#GET_PERMISSIONS} was set. This list includes * all permissions requested, even those that were not granted or known * by the system at install time. - * - * @deprecated Use {@link #usesPermissions} */ - @Deprecated public String[] requestedPermissions; /** @@ -217,23 +214,10 @@ public class PackageInfo implements Parcelable { * {@link PackageManager#GET_PERMISSIONS} was set. Each value matches * the corresponding entry in {@link #requestedPermissions}, and will have * the flag {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate. - * - * @deprecated Use {@link #usesPermissions} */ - @Deprecated public int[] requestedPermissionsFlags; /** - * Array of all {@link android.R.styleable#AndroidManifestUsesPermission - * <uses-permission>} tags included under <manifest>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_PERMISSIONS} was set. This list includes - * all permissions requested, even those that were not granted or known - * by the system at install time. - */ - public UsesPermissionInfo[] usesPermissions; - - /** * Flag for {@link #requestedPermissionsFlags}: the requested permission * is required for the application to run; the user can not optionally * disable it. Currently all permissions are required. @@ -480,7 +464,6 @@ public class PackageInfo implements Parcelable { dest.writeTypedArray(permissions, parcelableFlags); dest.writeStringArray(requestedPermissions); dest.writeIntArray(requestedPermissionsFlags); - dest.writeTypedArray(usesPermissions, parcelableFlags); dest.writeTypedArray(signatures, parcelableFlags); dest.writeTypedArray(configPreferences, parcelableFlags); dest.writeTypedArray(reqFeatures, parcelableFlags); @@ -545,7 +528,6 @@ public class PackageInfo implements Parcelable { permissions = source.createTypedArray(PermissionInfo.CREATOR); requestedPermissions = source.createStringArray(); requestedPermissionsFlags = source.createIntArray(); - usesPermissions = source.createTypedArray(UsesPermissionInfo.CREATOR); signatures = source.createTypedArray(Signature.CREATOR); configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR); reqFeatures = source.createTypedArray(FeatureInfo.CREATOR); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 81ed110d15ec..5020a94c3469 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -791,23 +791,18 @@ public class PackageParser { pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags); } } - N = p.usesPermissionInfos.size(); + N = p.requestedPermissions.size(); if (N > 0) { pi.requestedPermissions = new String[N]; pi.requestedPermissionsFlags = new int[N]; - pi.usesPermissions = new UsesPermissionInfo[N]; for (int i=0; i<N; i++) { - UsesPermissionInfo info = p.usesPermissionInfos.get(i); - final String perm = info.getPermission(); + final String perm = p.requestedPermissions.get(i); pi.requestedPermissions[i] = perm; - int permissionFlags = 0; // The notion of required permissions is deprecated but for compatibility. - permissionFlags |= PackageInfo.REQUESTED_PERMISSION_REQUIRED; + pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED; if (grantedPermissions != null && grantedPermissions.contains(perm)) { - permissionFlags |= PackageInfo.REQUESTED_PERMISSION_GRANTED; + pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED; } - pi.requestedPermissionsFlags[i] = permissionFlags; - pi.usesPermissions[i] = new UsesPermissionInfo(info, permissionFlags); } } } @@ -2175,12 +2170,12 @@ public class PackageParser { return null; } } else if (tagName.equals(TAG_USES_PERMISSION)) { - if (!parseUsesPermission(pkg, res, parser, outError)) { + if (!parseUsesPermission(pkg, res, parser)) { return null; } } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M) || tagName.equals(TAG_USES_PERMISSION_SDK_23)) { - if (!parseUsesPermission(pkg, res, parser, outError)) { + if (!parseUsesPermission(pkg, res, parser)) { return null; } } else if (tagName.equals(TAG_USES_CONFIGURATION)) { @@ -2498,7 +2493,7 @@ public class PackageParser { newPermsMsg.append(' '); } newPermsMsg.append(npi.name); - addRequestedPermission(pkg, npi.name); + pkg.requestedPermissions.add(npi.name); pkg.implicitPermissions.add(npi.name); } } @@ -2519,7 +2514,7 @@ public class PackageParser { for (int in = 0; in < newPerms.size(); in++) { final String perm = newPerms.get(in); if (!pkg.requestedPermissions.contains(perm)) { - addRequestedPermission(pkg, perm); + pkg.requestedPermissions.add(perm); pkg.implicitPermissions.add(perm); } } @@ -2599,13 +2594,13 @@ public class PackageParser { } } else { if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) { - addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_AUDIO); + pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO); } if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) { - addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_VIDEO); + pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO); } if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) { - addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_IMAGES); + pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES); } } @@ -2645,12 +2640,6 @@ public class PackageParser { } /** - * Helper method for adding a requested permission to a package outside of a uses-permission. - */ - private void addRequestedPermission(Package pkg, String permission) { - pkg.requestedPermissions.add(permission); - pkg.usesPermissionInfos.add(new UsesPermissionInfo(permission)); - } /** * Matches a given {@code targetCode} against a set of release codeNames. Target codes can @@ -2987,8 +2976,8 @@ public class PackageParser { return certSha256Digests; } - private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser, - String[] outError) throws XmlPullParserException, IOException { + private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser) + throws XmlPullParserException, IOException { TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestUsesPermission); @@ -3012,44 +3001,6 @@ public class PackageParser { final String requiredNotfeature = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0); - int dataSentOffDevice = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSentOffDevice, 0); - - int dataSharedWithThirdParty = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSharedWithThirdParty, 0); - - int dataUsedForMonetization = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataUsedForMonetization, 0); - - int retentionWeeks = -1; - int retention; - - String rawRetention = sa.getString( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime); - - if (rawRetention == null) { - retention = UsesPermissionInfo.RETENTION_UNDEFINED; - } else if ("notRetained".equals(rawRetention)) { - retention = UsesPermissionInfo.RETENTION_NOT_RETAINED; - } else if ("userSelected".equals(rawRetention)) { - retention = UsesPermissionInfo.RETENTION_USER_SELECTED; - } else if ("unlimited".equals(rawRetention)) { - retention = UsesPermissionInfo.RETENTION_UNLIMITED; - } else { - // A number of weeks was specified - retention = UsesPermissionInfo.RETENTION_SPECIFIED; - retentionWeeks = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime, - -1); - - if (retentionWeeks < 0) { - outError[0] = "Bad value provided for dataRetentionTime."; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - XmlUtils.skipCurrentTag(parser); - sa.recycle(); - return false; - } - } sa.recycle(); XmlUtils.skipCurrentTag(parser); @@ -3082,10 +3033,6 @@ public class PackageParser { + parser.getPositionDescription()); } - UsesPermissionInfo info = new UsesPermissionInfo(name, dataSentOffDevice, - dataSharedWithThirdParty, dataUsedForMonetization, retention, retentionWeeks); - pkg.usesPermissionInfos.add(info); - return true; } @@ -3420,10 +3367,6 @@ public class PackageParser { perm.info.flags = sa.getInt( com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0); - perm.info.usageInfoRequired = sa.getInt( - com.android.internal.R.styleable.AndroidManifestPermission_usageInfoRequired, 0) - != 0; - sa.recycle(); if (perm.info.protectionLevel == -1) { @@ -6625,9 +6568,6 @@ public class PackageParser { @UnsupportedAppUsage public final ArrayList<String> requestedPermissions = new ArrayList<String>(); - public final ArrayList<UsesPermissionInfo> usesPermissionInfos = - new ArrayList<>(); - /** Permissions requested but not in the manifest. */ public final ArrayList<String> implicitPermissions = new ArrayList<>(); @@ -7159,7 +7099,6 @@ public class PackageParser { dest.readStringList(requestedPermissions); internStringArrayList(requestedPermissions); - dest.readParcelableList(usesPermissionInfos, boot); dest.readStringList(implicitPermissions); internStringArrayList(implicitPermissions); protectedBroadcasts = dest.createStringArrayList(); @@ -7327,7 +7266,6 @@ public class PackageParser { dest.writeParcelableList(instrumentation, flags); dest.writeStringList(requestedPermissions); - dest.writeParcelableList(usesPermissionInfos, flags); dest.writeStringList(implicitPermissions); dest.writeStringList(protectedBroadcasts); diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index fb63e0dad9b6..e24523406ab8 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -20,7 +20,6 @@ import android.annotation.IntDef; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; -import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -368,12 +367,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { */ public CharSequence nonLocalizedDescription; - /** - * If {@code true} an application targeting {@link Build.VERSION_CODES#Q} <em>must</em> - * include permission data usage information in order to be able to be granted this permission. - */ - public boolean usageInfoRequired; - /** @hide */ public static int fixProtectionLevel(int level) { if (level == PROTECTION_SIGNATURE_OR_SYSTEM) { @@ -475,7 +468,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { descriptionRes = orig.descriptionRes; requestRes = orig.requestRes; nonLocalizedDescription = orig.nonLocalizedDescription; - usageInfoRequired = orig.usageInfoRequired; } /** @@ -540,7 +532,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { dest.writeInt(descriptionRes); dest.writeInt(requestRes); TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); - dest.writeInt(usageInfoRequired ? 1 : 0); } /** @hide */ @@ -581,6 +572,5 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { descriptionRes = source.readInt(); requestRes = source.readInt(); nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - usageInfoRequired = source.readInt() != 0; } } diff --git a/core/java/android/content/pm/UsesPermissionInfo.java b/core/java/android/content/pm/UsesPermissionInfo.java deleted file mode 100644 index d08548fa31a5..000000000000 --- a/core/java/android/content/pm/UsesPermissionInfo.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.pm; - -import android.annotation.IntDef; -import android.os.Parcel; -import android.os.Parcelable; - -import java.lang.annotation.RetentionPolicy; -/** - * Information you can retrive about a particular application requested permission. This - * corresponds to information collected from the AndroidManifest.xml's <uses-permission> - * tags. - */ -public final class UsesPermissionInfo extends PackageItemInfo implements Parcelable { - - /** - * Flag for {@link #getFlags()}: the requested permission is currently granted to the - * application. - */ - public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 1 << 1; - - /** @hide */ - @IntDef(flag = true, prefix = {"FLAG_"}, value = {FLAG_REQUESTED_PERMISSION_GRANTED}) - @java.lang.annotation.Retention(RetentionPolicy.SOURCE) - public @interface Flags {} - - /** An unset value for {@link #getDataSentOffDevice()}, - * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()} - */ - public static final int USAGE_UNDEFINED = 0; - - /** - * A yes value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()}, - * and {@link #getDataUsedForMonetization()} corresponding to the <code>yes</code> value of - * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty}, - * and {@link android.R.attr#dataUsedForMonetization} attributes. - */ - public static final int USAGE_YES = 1; - - /** - * A user triggered only value for {@link #getDataSentOffDevice()}, - * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()} - * corresponding to the <code>userTriggered</code> value of - * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty}, - * and {@link android.R.attr#dataUsedForMonetization} attributes. - */ - public static final int USAGE_USER_TRIGGERED = 2; - - /** - * A no value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()}, - * and {@link #getDataUsedForMonetization()} corresponding to the <code>no</code> value of - * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty}, - * and {@link android.R.attr#dataUsedForMonetization} attributes. - */ - public static final int USAGE_NO = 3; - - /** @hide */ - @IntDef(prefix = {"USAGE_"}, value = { - USAGE_UNDEFINED, - USAGE_YES, - USAGE_USER_TRIGGERED, - USAGE_NO}) - @java.lang.annotation.Retention(RetentionPolicy.SOURCE) - public @interface Usage {} - - /** - * An unset value for {@link #getDataRetention}. - */ - public static final int RETENTION_UNDEFINED = 0; - - /** - * A data not retained value for {@link #getDataRetention()} corresponding to the - * <code>notRetained</code> value of {@link android.R.attr#dataRetentionTime}. - */ - public static final int RETENTION_NOT_RETAINED = 1; - - /** - * A user selected value for {@link #getDataRetention()} corresponding to the - * <code>userSelected</code> value of {@link android.R.attr#dataRetentionTime}. - */ - public static final int RETENTION_USER_SELECTED = 2; - - /** - * An unlimited value for {@link #getDataRetention()} corresponding to the - * <code>unlimited</code> value of {@link android.R.attr#dataRetentionTime}. - */ - public static final int RETENTION_UNLIMITED = 3; - - /** - * A specified value for {@link #getDataRetention()} corresponding to providing the number of - * weeks data is retained in {@link android.R.attr#dataRetentionTime}. The number of weeks - * is available in {@link #getDataRetentionWeeks()}. - */ - public static final int RETENTION_SPECIFIED = 4; - - /** @hide */ - @IntDef(prefix = {"RETENTION_"}, value = { - RETENTION_UNDEFINED, - RETENTION_NOT_RETAINED, - RETENTION_USER_SELECTED, - RETENTION_UNLIMITED, - RETENTION_SPECIFIED}) - @java.lang.annotation.Retention(RetentionPolicy.SOURCE) - public @interface Retention {} - - private final String mPermission; - private final @Flags int mFlags; - private final @Usage int mDataSentOffDevice; - private final @Usage int mDataSharedWithThirdParty; - private final @Usage int mDataUsedForMonetization; - private final @Retention int mDataRetention; - private final int mDataRetentionWeeks; - - /** @hide */ - public UsesPermissionInfo(String permission) { - mPermission = permission; - mDataSentOffDevice = USAGE_UNDEFINED; - mDataSharedWithThirdParty = USAGE_UNDEFINED; - mDataUsedForMonetization = USAGE_UNDEFINED; - mDataRetention = RETENTION_UNDEFINED; - mDataRetentionWeeks = -1; - mFlags = 0; - } - - /** @hide */ - public UsesPermissionInfo(String permission, - @Usage int dataSentOffDevice, @Usage int dataSharedWithThirdParty, - @Usage int dataUsedForMonetization, @Retention int dataRetention, - int dataRetentionWeeks) { - mPermission = permission; - mDataSentOffDevice = dataSentOffDevice; - mDataSharedWithThirdParty = dataSharedWithThirdParty; - mDataUsedForMonetization = dataUsedForMonetization; - mDataRetention = dataRetention; - mDataRetentionWeeks = dataRetentionWeeks; - mFlags = 0; - } - - /** @hide */ - public UsesPermissionInfo(UsesPermissionInfo orig) { - this(orig, orig.mFlags); - } - - /** @hide */ - public UsesPermissionInfo(UsesPermissionInfo orig, int flags) { - super(orig); - mPermission = orig.mPermission; - mFlags = flags; - mDataSentOffDevice = orig.mDataSentOffDevice; - mDataSharedWithThirdParty = orig.mDataSharedWithThirdParty; - mDataUsedForMonetization = orig.mDataUsedForMonetization; - mDataRetention = orig.mDataRetention; - mDataRetentionWeeks = orig.mDataRetentionWeeks; - } - - /** - * The name of the requested permission. - */ - public String getPermission() { - return mPermission; - } - - public @Flags int getFlags() { - return mFlags; - } - - /** - * If the application sends the data guarded by this permission off the device. - * - * See {@link android.R.attr#dataSentOffDevice} - */ - public @Usage int getDataSentOffDevice() { - return mDataSentOffDevice; - } - - /** - * If the application or its services shares the data guarded by this permission with third - * parties. - * - * See {@link android.R.attr#dataSharedWithThirdParty} - */ - public @Usage int getDataSharedWithThirdParty() { - return mDataSharedWithThirdParty; - } - - /** - * If the application or its services use the data guarded by this permission for monetization - * purposes. - * - * See {@link android.R.attr#dataUsedForMonetization} - */ - public @Usage int getDataUsedForMonetization() { - return mDataUsedForMonetization; - } - - /** - * How long the application or its services store the data guarded by this permission. - * If set to {@link #RETENTION_SPECIFIED} {@link #getDataRetentionWeeks()} will contain the - * number of weeks the data is stored. - * - * See {@link android.R.attr#dataRetentionTime} - */ - public @Retention int getDataRetention() { - return mDataRetention; - } - - /** - * If {@link #getDataRetention()} is {@link #RETENTION_SPECIFIED} the number of weeks the - * application or its services store data guarded by this permission. - * - * @throws IllegalStateException if {@link #getDataRetention} is not - * {@link #RETENTION_SPECIFIED}. - */ - public int getDataRetentionWeeks() { - if (mDataRetention != RETENTION_SPECIFIED) { - throw new IllegalStateException("Data retention weeks not specified"); - } - return mDataRetentionWeeks; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeString(mPermission); - dest.writeInt(mFlags); - dest.writeInt(mDataSentOffDevice); - dest.writeInt(mDataSharedWithThirdParty); - dest.writeInt(mDataUsedForMonetization); - dest.writeInt(mDataRetention); - dest.writeInt(mDataRetentionWeeks); - } - - private UsesPermissionInfo(Parcel source) { - super(source); - mPermission = source.readString(); - mFlags = source.readInt(); - mDataSentOffDevice = source.readInt(); - mDataSharedWithThirdParty = source.readInt(); - mDataUsedForMonetization = source.readInt(); - mDataRetention = source.readInt(); - mDataRetentionWeeks = source.readInt(); - } - - public static final Creator<UsesPermissionInfo> CREATOR = - new Creator<UsesPermissionInfo>() { - @Override - public UsesPermissionInfo createFromParcel(Parcel source) { - return new UsesPermissionInfo(source); - } - @Override - public UsesPermissionInfo[] newArray(int size) { - return new UsesPermissionInfo[size]; - } - }; -} diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 9e0a9ba0dc7b..faf17e011b23 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -1051,6 +1051,14 @@ public final class AssetManager implements AutoCloseable { } } + int[] getAttributeResolutionStack(long themePtr, @AttrRes int defStyleAttr, + @StyleRes int defStyleRes, @StyleRes int xmlStyle) { + synchronized (this) { + return nativeAttributeResolutionStack( + mObject, themePtr, xmlStyle, defStyleAttr, defStyleRes); + } + } + @UnsupportedAppUsage boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues, @@ -1419,6 +1427,8 @@ public final class AssetManager implements AutoCloseable { private static native @Nullable String nativeGetLastResourceResolution(long ptr); // Style attribute retrieval native methods. + private static native int[] nativeAttributeResolutionStack(long ptr, long themePtr, + @StyleRes int xmlStyleRes, @AttrRes int defStyleAttr, @StyleRes int defStyleRes); private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs, long outValuesAddress, long outIndicesAddress); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 59db49e0d37e..a2ae994f7b0f 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1725,6 +1725,68 @@ public class Resources { public void rebase() { mThemeImpl.rebase(); } + + /** + * Returns the resource ID for the style specified using {@code style="..."} in the + * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not + * specified or otherwise not applicable. + * <p> + * Each {@link android.view.View} can have an explicit style specified in the layout file. + * This style is used first during the {@link android.view.View} attribute resolution, then + * if an attribute is not defined there the resource system looks at default style and theme + * as fallbacks. + * + * @param set The base set of attribute values. + * + * @return The resource ID for the style specified using {@code style="..."} in the + * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise + * if not specified or otherwise not applicable. + */ + @StyleRes + public int getExplicitStyle(@Nullable AttributeSet set) { + if (set == null) { + return ID_NULL; + } + int styleAttr = set.getStyleAttribute(); + if (styleAttr == ID_NULL) { + return ID_NULL; + } + String styleAttrType = getResources().getResourceTypeName(styleAttr); + if ("attr".equals(styleAttrType)) { + TypedValue explicitStyle = new TypedValue(); + boolean resolved = resolveAttribute(styleAttr, explicitStyle, true); + if (resolved) { + return explicitStyle.resourceId; + } + } else if ("style".equals(styleAttrType)) { + return styleAttr; + } + return ID_NULL; + } + + /** + * Returns the ordered list of resource ID that are considered when resolving attribute + * values when making an equivalent call to + * {@link #obtainStyledAttributes(AttributeSet, int[], int, int)} . The list will include + * a set of explicit styles ({@code explicitStyleRes} and it will include the default styles + * ({@code defStyleAttr} and {@code defStyleRes}). + * + * @param defStyleAttr An attribute in the current theme that contains a + * reference to a style resource that supplies + * defaults values for the TypedArray. Can be + * 0 to not look for defaults. + * @param defStyleRes A resource identifier of a style resource that + * supplies default values for the TypedArray, + * used only if defStyleAttr is 0 or can not be found + * in the theme. Can be 0 to not look for defaults. + * @param explicitStyleRes A resource identifier of an explicit style resource. + * @return ordered list of resource ID that are considered when resolving attribute values. + */ + public int[] getAttributeResolutionStack(@AttrRes int defStyleAttr, + @StyleRes int defStyleRes, @StyleRes int explicitStyleRes) { + return mThemeImpl.getAttributeResolutionStack( + defStyleAttr, defStyleRes, explicitStyleRes); + } } static class ThemeKey implements Cloneable { diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 98980799a365..da064c956fcc 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -1488,6 +1488,32 @@ public class ResourcesImpl { } } } + + /** + * Returns the ordered list of resource ID that are considered when resolving attribute + * values when making an equivalent call to + * {@link #obtainStyledAttributes(Resources.Theme, AttributeSet, int[], int, int)}. The list + * will include a set of explicit styles ({@code explicitStyleRes} and it will include the + * default styles ({@code defStyleAttr} and {@code defStyleRes}). + * + * @param defStyleAttr An attribute in the current theme that contains a + * reference to a style resource that supplies + * defaults values for the TypedArray. Can be + * 0 to not look for defaults. + * @param defStyleRes A resource identifier of a style resource that + * supplies default values for the TypedArray, + * used only if defStyleAttr is 0 or can not be found + * in the theme. Can be 0 to not look for defaults. + * @param explicitStyleRes A resource identifier of an explicit style resource. + * @return ordered list of resource ID that are considered when resolving attribute values. + */ + public int[] getAttributeResolutionStack(@AttrRes int defStyleAttr, + @StyleRes int defStyleRes, @StyleRes int explicitStyleRes) { + synchronized (mKey) { + return mAssets.getAttributeResolutionStack( + mTheme, defStyleAttr, defStyleRes, explicitStyleRes); + } + } } private static class LookupStack { diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 1881a0cd32e8..0e4ff78af1e0 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1159,9 +1159,10 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>Each output JPEG size in android.scaler.availableStreamConfigurations will have at least * one corresponding size that has the same aspect ratio in availableThumbnailSizes, * and vice versa.</li> - * <li>All non-<code>(0, 0)</code> sizes will have non-zero widths and heights. - * This key is available on all devices.</li> + * <li>All non-<code>(0, 0)</code> sizes will have non-zero widths and heights.</li> * </ul> + * <p>This list is also used as supported thumbnail sizes for HEIC image format capture.</p> + * <p>This key is available on all devices.</p> * * @see CaptureRequest#JPEG_THUMBNAIL_SIZE */ @@ -3838,6 +3839,74 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri public static final Key<int[]> DISTORTION_CORRECTION_AVAILABLE_MODES = new Key<int[]>("android.distortionCorrection.availableModes", int[].class); + /** + * <p>The available HEIC (ISO/IEC 23008-12) stream + * configurations that this camera device supports + * (i.e. format, width, height, output/input stream).</p> + * <p>The configurations are listed as <code>(format, width, height, input?)</code> tuples.</p> + * <p>If the camera device supports HEIC image format, it will support identical set of stream + * combinations involving HEIC image format, compared to the combinations involving JPEG + * image format as required by the device's hardware level and capabilities.</p> + * <p>All the static, control, and dynamic metadata tags related to JPEG apply to HEIC formats. + * Configuring JPEG and HEIC streams at the same time is not supported.</p> + * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> + * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + * @hide + */ + public static final Key<android.hardware.camera2.params.StreamConfiguration[]> HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS = + new Key<android.hardware.camera2.params.StreamConfiguration[]>("android.heic.availableHeicStreamConfigurations", android.hardware.camera2.params.StreamConfiguration[].class); + + /** + * <p>This lists the minimum frame duration for each + * format/size combination for HEIC output formats.</p> + * <p>This should correspond to the frame duration when only that + * stream is active, with all processing (typically in android.*.mode) + * set to either OFF or FAST.</p> + * <p>When multiple streams are used in a request, the minimum frame + * duration will be max(individual stream min durations).</p> + * <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} and + * android.scaler.availableStallDurations for more details about + * calculating the max frame rate.</p> + * <p><b>Units</b>: (format, width, height, ns) x n</p> + * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> + * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + * @see CaptureRequest#SENSOR_FRAME_DURATION + * @hide + */ + public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS = + new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.heic.availableHeicMinFrameDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class); + + /** + * <p>This lists the maximum stall duration for each + * output format/size combination for HEIC streams.</p> + * <p>A stall duration is how much extra time would get added + * to the normal minimum frame duration for a repeating request + * that has streams with non-zero stall.</p> + * <p>This functions similarly to + * android.scaler.availableStallDurations for HEIC + * streams.</p> + * <p>All HEIC output stream formats may have a nonzero stall + * duration.</p> + * <p><b>Units</b>: (format, width, height, ns) x n</p> + * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> + * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + * @hide + */ + public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> HEIC_AVAILABLE_HEIC_STALL_DURATIONS = + new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.heic.availableHeicStallDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class); + /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ * End generated code *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/ diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 9c213f2f27a5..20fc53fee2e6 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -356,12 +356,6 @@ public abstract class CameraDevice implements AutoCloseable { * </table><br> * </p> * - * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} - * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices - * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV} - * streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level - * and capabilities.</p> - * * <p>FULL-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL} * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices * support at least the following stream combinations in addition to those for @@ -435,6 +429,18 @@ public abstract class CameraDevice implements AutoCloseable { * </table><br> * </p> * + * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} + * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices + * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV} + * streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level + * and capabilities.</p> + * + * <p>Devices capable of outputting HEIC formats ({@link StreamConfigurationMap#getOutputFormats} + * contains {@link android.graphics.ImageFormat#HEIC}) will support substituting {@code JPEG} + * streams with {@code HEIC} in all guaranteed stream combinations for the device's hardware + * level and capabilities. Calling createCaptureSession with both JPEG and HEIC outputs is not + * supported.</p> + * * <p>Clients can access the above mandatory stream combination tables via * {@link android.hardware.camera2.params.MandatoryStreamCombination}.</p> * diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 3d3a916bae7a..525070103c2c 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -2126,6 +2126,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>Setting a location object in a request will include the GPS coordinates of the location * into any JPEG images captured based on the request. These coordinates can then be * viewed by anyone who receives the JPEG image.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p>This key is available on all devices.</p> */ @PublicKey @@ -2136,6 +2137,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>GPS coordinates to include in output JPEG * EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * (-180 - 180], [-90,90], [-inf, inf]</p> * <p>This key is available on all devices.</p> @@ -2147,6 +2149,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>32 characters describing GPS algorithm to * include in EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p>This key is available on all devices.</p> * @hide */ @@ -2156,6 +2159,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>Time GPS fix was made to include in * EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p><b>Units</b>: UTC in seconds since January 1, 1970</p> * <p>This key is available on all devices.</p> * @hide @@ -2195,6 +2199,10 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * </code></pre> * <p>For EXTERNAL cameras the sensor orientation will always be set to 0 and the facing will * also be set to EXTERNAL. The above code is not relevant in such case.</p> + * <p>This tag is also used to describe the orientation of the HEIC image capture, in which + * case the rotation is reflected by + * {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}, and not by + * rotating the image data itself.</p> * <p><b>Units</b>: Degrees in multiples of 90</p> * <p><b>Range of valid values:</b><br> * 0, 90, 180, 270</p> @@ -2209,7 +2217,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>Compression quality of the final JPEG * image.</p> - * <p>85-95 is typical usage range.</p> + * <p>85-95 is typical usage range. This tag is also used to describe the quality + * of the HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * 1-100; larger is higher quality</p> * <p>This key is available on all devices.</p> @@ -2221,6 +2230,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> /** * <p>Compression quality of JPEG * thumbnail.</p> + * <p>This tag is also used to describe the quality of the HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * 1-100; larger is higher quality</p> * <p>This key is available on all devices.</p> @@ -2253,6 +2263,10 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * orientation is requested. LEGACY device will always report unrotated thumbnail * size.</li> * </ul> + * <p>The tag is also used as thumbnail size for HEIC image format capture, in which case the + * the thumbnail rotation is reflected by + * {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}, and not by + * rotating the thumbnail data itself.</p> * <p><b>Range of valid values:</b><br> * {@link CameraCharacteristics#JPEG_AVAILABLE_THUMBNAIL_SIZES android.jpeg.availableThumbnailSizes}</p> * <p>This key is available on all devices.</p> diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 8982b40be29b..13ad092f6efd 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -2450,6 +2450,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>Setting a location object in a request will include the GPS coordinates of the location * into any JPEG images captured based on the request. These coordinates can then be * viewed by anyone who receives the JPEG image.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p>This key is available on all devices.</p> */ @PublicKey @@ -2460,6 +2461,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>GPS coordinates to include in output JPEG * EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * (-180 - 180], [-90,90], [-inf, inf]</p> * <p>This key is available on all devices.</p> @@ -2471,6 +2473,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>32 characters describing GPS algorithm to * include in EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p>This key is available on all devices.</p> * @hide */ @@ -2480,6 +2483,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>Time GPS fix was made to include in * EXIF.</p> + * <p>This tag is also used for HEIC image capture.</p> * <p><b>Units</b>: UTC in seconds since January 1, 1970</p> * <p>This key is available on all devices.</p> * @hide @@ -2519,6 +2523,10 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </code></pre> * <p>For EXTERNAL cameras the sensor orientation will always be set to 0 and the facing will * also be set to EXTERNAL. The above code is not relevant in such case.</p> + * <p>This tag is also used to describe the orientation of the HEIC image capture, in which + * case the rotation is reflected by + * {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}, and not by + * rotating the image data itself.</p> * <p><b>Units</b>: Degrees in multiples of 90</p> * <p><b>Range of valid values:</b><br> * 0, 90, 180, 270</p> @@ -2533,7 +2541,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>Compression quality of the final JPEG * image.</p> - * <p>85-95 is typical usage range.</p> + * <p>85-95 is typical usage range. This tag is also used to describe the quality + * of the HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * 1-100; larger is higher quality</p> * <p>This key is available on all devices.</p> @@ -2545,6 +2554,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>Compression quality of JPEG * thumbnail.</p> + * <p>This tag is also used to describe the quality of the HEIC image capture.</p> * <p><b>Range of valid values:</b><br> * 1-100; larger is higher quality</p> * <p>This key is available on all devices.</p> @@ -2577,6 +2587,10 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * orientation is requested. LEGACY device will always report unrotated thumbnail * size.</li> * </ul> + * <p>The tag is also used as thumbnail size for HEIC image format capture, in which case the + * the thumbnail rotation is reflected by + * {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}, and not by + * rotating the thumbnail data itself.</p> * <p><b>Range of valid values:</b><br> * {@link CameraCharacteristics#JPEG_AVAILABLE_THUMBNAIL_SIZES android.jpeg.availableThumbnailSizes}</p> * <p>This key is available on all devices.</p> diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 7877a4d51313..65026b6feb9f 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -1133,6 +1133,9 @@ public class CameraMetadataNative implements Parcelable { /*dynamicDepthConfigurations*/ null, /*dynamicDepthMinFrameDurations*/ null, /*dynamicDepthStallDurations*/ null, + /*heicconfiguration*/ null, + /*heicminduration*/ null, + /*heicstallduration*/ null, /*highspeedvideoconfigurations*/ null, /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]); break; @@ -1144,6 +1147,9 @@ public class CameraMetadataNative implements Parcelable { /*dynamicDepthConfigurations*/ null, /*dynamicDepthMinFrameDurations*/ null, /*dynamicDepthStallDurations*/ null, + /*heicconfiguration*/ null, + /*heicminduration*/ null, + /*heicstallduration*/ null, highSpeedVideoConfigurations, /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]); break; @@ -1155,6 +1161,9 @@ public class CameraMetadataNative implements Parcelable { /*dynamicDepthConfigurations*/ null, /*dynamicDepthMinFrameDurations*/ null, /*dynamicDepthStallDurations*/ null, + /*heicconfiguration*/ null, + /*heicminduration*/ null, + /*heicstallduration*/ null, /*highSpeedVideoConfigurations*/ null, inputOutputFormatsMap, listHighResolution, supportsPrivate[i]); break; @@ -1166,6 +1175,9 @@ public class CameraMetadataNative implements Parcelable { /*dynamicDepthConfigurations*/ null, /*dynamicDepthMinFrameDurations*/ null, /*dynamicDepthStallDurations*/ null, + /*heicconfiguration*/ null, + /*heicminduration*/ null, + /*heicstallduration*/ null, /*highSpeedVideoConfigurations*/ null, /*inputOutputFormatsMap*/ null, listHighResolution, supportsPrivate[i]); } @@ -1230,6 +1242,12 @@ public class CameraMetadataNative implements Parcelable { CameraCharacteristics.DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS); StreamConfigurationDuration[] dynamicDepthStallDurations = getBase( CameraCharacteristics.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS); + StreamConfiguration[] heicConfigurations = getBase( + CameraCharacteristics.HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS); + StreamConfigurationDuration[] heicMinFrameDurations = getBase( + CameraCharacteristics.HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS); + StreamConfigurationDuration[] heicStallDurations = getBase( + CameraCharacteristics.HEIC_AVAILABLE_HEIC_STALL_DURATIONS); HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase( CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS); ReprocessFormatsMap inputOutputFormatsMap = getBase( @@ -1239,7 +1257,9 @@ public class CameraMetadataNative implements Parcelable { configurations, minFrameDurations, stallDurations, depthConfigurations, depthMinFrameDurations, depthStallDurations, dynamicDepthConfigurations, dynamicDepthMinFrameDurations, - dynamicDepthStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap, + dynamicDepthStallDurations, heicConfigurations, + heicMinFrameDurations, heicStallDurations, + highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution); } diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java index a22e008a65fd..996f9978a612 100644 --- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java @@ -79,6 +79,22 @@ public final class StreamConfigurationMap { * @param configurations a non-{@code null} array of {@link StreamConfiguration} * @param minFrameDurations a non-{@code null} array of {@link StreamConfigurationDuration} * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration} + * @param depthConfigurations a non-{@code null} array of depth {@link StreamConfiguration} + * @param depthMinFrameDurations a non-{@code null} array of depth + * {@link StreamConfigurationDuration} + * @param depthStallDurations a non-{@code null} array of depth + * {@link StreamConfigurationDuration} + * @param dynamicDepthConfigurations a non-{@code null} array of dynamic depth + * {@link StreamConfiguration} + * @param dynamicDepthMinFrameDurations a non-{@code null} array of dynamic depth + * {@link StreamConfigurationDuration} + * @param dynamicDepthStallDurations a non-{@code null} array of dynamic depth + * {@link StreamConfigurationDuration} + * @param heicConfigurations a non-{@code null} array of heic {@link StreamConfiguration} + * @param heicMinFrameDurations a non-{@code null} array of heic + * {@link StreamConfigurationDuration} + * @param heicStallDurations a non-{@code null} array of heic + * {@link StreamConfigurationDuration} * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if * camera device does not support high speed video recording * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE @@ -98,14 +114,19 @@ public final class StreamConfigurationMap { StreamConfiguration[] dynamicDepthConfigurations, StreamConfigurationDuration[] dynamicDepthMinFrameDurations, StreamConfigurationDuration[] dynamicDepthStallDurations, + StreamConfiguration[] heicConfigurations, + StreamConfigurationDuration[] heicMinFrameDurations, + StreamConfigurationDuration[] heicStallDurations, HighSpeedVideoConfiguration[] highSpeedVideoConfigurations, ReprocessFormatsMap inputOutputFormatsMap, boolean listHighResolution) { this(configurations, minFrameDurations, stallDurations, depthConfigurations, depthMinFrameDurations, depthStallDurations, dynamicDepthConfigurations, dynamicDepthMinFrameDurations, - dynamicDepthStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap, - listHighResolution, /*enforceImplementationDefined*/ true); + dynamicDepthStallDurations, + heicConfigurations, heicMinFrameDurations, heicStallDurations, + highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution, + /*enforceImplementationDefined*/ true); } /** @@ -117,6 +138,22 @@ public final class StreamConfigurationMap { * @param configurations a non-{@code null} array of {@link StreamConfiguration} * @param minFrameDurations a non-{@code null} array of {@link StreamConfigurationDuration} * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration} + * @param depthConfigurations a non-{@code null} array of depth {@link StreamConfiguration} + * @param depthMinFrameDurations a non-{@code null} array of depth + * {@link StreamConfigurationDuration} + * @param depthStallDurations a non-{@code null} array of depth + * {@link StreamConfigurationDuration} + * @param dynamicDepthConfigurations a non-{@code null} array of dynamic depth + * {@link StreamConfiguration} + * @param dynamicDepthMinFrameDurations a non-{@code null} array of dynamic depth + * {@link StreamConfigurationDuration} + * @param dynamicDepthStallDurations a non-{@code null} array of dynamic depth + * {@link StreamConfigurationDuration} + * @param heicConfigurations a non-{@code null} array of heic {@link StreamConfiguration} + * @param heicMinFrameDurations a non-{@code null} array of heic + * {@link StreamConfigurationDuration} + * @param heicStallDurations a non-{@code null} array of heic + * {@link StreamConfigurationDuration} * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if * camera device does not support high speed video recording * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE @@ -138,14 +175,23 @@ public final class StreamConfigurationMap { StreamConfiguration[] dynamicDepthConfigurations, StreamConfigurationDuration[] dynamicDepthMinFrameDurations, StreamConfigurationDuration[] dynamicDepthStallDurations, + StreamConfiguration[] heicConfigurations, + StreamConfigurationDuration[] heicMinFrameDurations, + StreamConfigurationDuration[] heicStallDurations, HighSpeedVideoConfiguration[] highSpeedVideoConfigurations, ReprocessFormatsMap inputOutputFormatsMap, boolean listHighResolution, boolean enforceImplementationDefined) { + if (configurations == null && + depthConfigurations == null && + heicConfigurations == null) { + throw new NullPointerException("At least one of color/depth/heic configurations " + + "must not be null"); + } + if (configurations == null) { // If no color configurations exist, ensure depth ones do - checkArrayElementsNotNull(depthConfigurations, "depthConfigurations"); mConfigurations = new StreamConfiguration[0]; mMinFrameDurations = new StreamConfigurationDuration[0]; mStallDurations = new StreamConfigurationDuration[0]; @@ -183,6 +229,19 @@ public final class StreamConfigurationMap { "dynamicDepthStallDurations"); } + if (heicConfigurations == null) { + mHeicConfigurations = new StreamConfiguration[0]; + mHeicMinFrameDurations = new StreamConfigurationDuration[0]; + mHeicStallDurations = new StreamConfigurationDuration[0]; + } else { + mHeicConfigurations = checkArrayElementsNotNull(heicConfigurations, + "heicConfigurations"); + mHeicMinFrameDurations = checkArrayElementsNotNull(heicMinFrameDurations, + "heicMinFrameDurations"); + mHeicStallDurations = checkArrayElementsNotNull(heicStallDurations, + "heicStallDurations"); + } + if (highSpeedVideoConfigurations == null) { mHighSpeedVideoConfigurations = new HighSpeedVideoConfiguration[0]; } else { @@ -235,6 +294,17 @@ public final class StreamConfigurationMap { mDynamicDepthOutputFormats.get(config.getFormat()) + 1); } + // For each heic format, track how many sizes there are available to configure + for (StreamConfiguration config : mHeicConfigurations) { + if (!config.isOutput()) { + // Ignoring input depth configs + continue; + } + + mHeicOutputFormats.put(config.getFormat(), + mHeicOutputFormats.get(config.getFormat()) + 1); + } + if (configurations != null && enforceImplementationDefined && mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) { throw new AssertionError( @@ -302,7 +372,16 @@ public final class StreamConfigurationMap { if (mInputOutputFormatsMap == null) { return new int[0]; } - return mInputOutputFormatsMap.getOutputs(inputFormat); + + int[] outputs = mInputOutputFormatsMap.getOutputs(inputFormat); + if (mHeicOutputFormats.size() > 0) { + // All reprocessing formats map contain JPEG. + int[] outputsWithHeic = Arrays.copyOf(outputs, outputs.length+1); + outputsWithHeic[outputs.length] = ImageFormat.HEIC; + return outputsWithHeic; + } else { + return outputs; + } } /** @@ -366,6 +445,8 @@ public final class StreamConfigurationMap { return mDepthOutputFormats.indexOfKey(internalFormat) >= 0; } else if (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) { return mDynamicDepthOutputFormats.indexOfKey(internalFormat) >= 0; + } else if (dataspace == HAL_DATASPACE_HEIF) { + return mHeicOutputFormats.indexOfKey(internalFormat) >= 0; } else { return getFormatsMap(/*output*/true).indexOfKey(internalFormat) >= 0; } @@ -479,6 +560,7 @@ public final class StreamConfigurationMap { StreamConfiguration[] configs = surfaceDataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations : surfaceDataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations : + surfaceDataspace == HAL_DATASPACE_HEIF ? mHeicConfigurations : mConfigurations; for (StreamConfiguration config : configs) { if (config.getFormat() == surfaceFormat && config.isOutput()) { @@ -512,9 +594,10 @@ public final class StreamConfigurationMap { int dataspace = imageFormatToDataspace(format); StreamConfiguration[] configs = - dataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations : - dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations : - mConfigurations; + dataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations : + dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations : + dataspace == HAL_DATASPACE_HEIF ? mHeicConfigurations : + mConfigurations; for (StreamConfiguration config : configs) { if ((config.getFormat() == internalFormat) && config.isOutput() && config.getSize().equals(size)) { @@ -1033,6 +1116,9 @@ public final class StreamConfigurationMap { Arrays.equals(mDynamicDepthMinFrameDurations, other.mDynamicDepthMinFrameDurations) && Arrays.equals(mDynamicDepthStallDurations, other.mDynamicDepthStallDurations) && + Arrays.equals(mHeicConfigurations, other.mHeicConfigurations) && + Arrays.equals(mHeicMinFrameDurations, other.mHeicMinFrameDurations) && + Arrays.equals(mHeicStallDurations, other.mHeicStallDurations) && Arrays.equals(mHighSpeedVideoConfigurations, other.mHighSpeedVideoConfigurations); } @@ -1049,7 +1135,9 @@ public final class StreamConfigurationMap { mConfigurations, mMinFrameDurations, mStallDurations, mDepthConfigurations, mDepthMinFrameDurations, mDepthStallDurations, mDynamicDepthConfigurations, mDynamicDepthMinFrameDurations, - mDynamicDepthStallDurations, mHighSpeedVideoConfigurations); + mDynamicDepthStallDurations, mHeicConfigurations, + mHeicMinFrameDurations, mHeicStallDurations, + mHighSpeedVideoConfigurations); } // Check that the argument is supported by #getOutputFormats or #getInputFormats @@ -1068,6 +1156,10 @@ public final class StreamConfigurationMap { if (mDynamicDepthOutputFormats.indexOfKey(internalFormat) >= 0) { return format; } + } else if (internalDataspace == HAL_DATASPACE_HEIF) { + if (mHeicOutputFormats.indexOfKey(internalFormat) >= 0) { + return format; + } } else { if (mAllOutputFormats.indexOfKey(internalFormat) >= 0) { return format; @@ -1108,8 +1200,9 @@ public final class StreamConfigurationMap { case HAL_PIXEL_FORMAT_Y16: return format; case ImageFormat.JPEG: + case ImageFormat.HEIC: throw new IllegalArgumentException( - "ImageFormat.JPEG is an unknown internal format"); + "An unknown internal format: " + format); default: return checkArgumentFormat(format); } @@ -1267,6 +1360,8 @@ public final class StreamConfigurationMap { * <ul> * <li>ImageFormat.JPEG => HAL_PIXEL_FORMAT_BLOB * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_PIXEL_FORMAT_BLOB + * <li>ImageFormat.DEPTH_JPEG => HAL_PIXEL_FORMAT_BLOB + * <li>ImageFormat.HEIC => HAL_PIXEL_FORMAT_BLOB * <li>ImageFormat.DEPTH16 => HAL_PIXEL_FORMAT_Y16 * </ul> * </p> @@ -1292,6 +1387,7 @@ public final class StreamConfigurationMap { case ImageFormat.JPEG: case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: return HAL_PIXEL_FORMAT_BLOB; case ImageFormat.DEPTH16: return HAL_PIXEL_FORMAT_Y16; @@ -1312,6 +1408,7 @@ public final class StreamConfigurationMap { * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH * <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH * <li>ImageFormat.DEPTH_JPEG => HAL_DATASPACE_DYNAMIC_DEPTH + * <li>ImageFormat.HEIC => HAL_DATASPACE_HEIF * <li>others => HAL_DATASPACE_UNKNOWN * </ul> * </p> @@ -1343,6 +1440,8 @@ public final class StreamConfigurationMap { return HAL_DATASPACE_DEPTH; case ImageFormat.DEPTH_JPEG: return HAL_DATASPACE_DYNAMIC_DEPTH; + case ImageFormat.HEIC: + return HAL_DATASPACE_HEIF; default: return HAL_DATASPACE_UNKNOWN; } @@ -1394,14 +1493,17 @@ public final class StreamConfigurationMap { !output ? mInputFormats : dataspace == HAL_DATASPACE_DEPTH ? mDepthOutputFormats : dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthOutputFormats : + dataspace == HAL_DATASPACE_HEIF ? mHeicOutputFormats : highRes ? mHighResOutputFormats : mOutputFormats; int sizesCount = formatsMap.get(format); if ( ((!output || (dataspace == HAL_DATASPACE_DEPTH || - dataspace == HAL_DATASPACE_DYNAMIC_DEPTH)) && sizesCount == 0) || + dataspace == HAL_DATASPACE_DYNAMIC_DEPTH || + dataspace == HAL_DATASPACE_HEIF)) && sizesCount == 0) || (output && (dataspace != HAL_DATASPACE_DEPTH && - dataspace != HAL_DATASPACE_DYNAMIC_DEPTH) && + dataspace != HAL_DATASPACE_DYNAMIC_DEPTH && + dataspace != HAL_DATASPACE_HEIF) && mAllOutputFormats.get(format) == 0)) { // Only throw if this is really not supported at all throw new IllegalArgumentException("format not available"); @@ -1413,10 +1515,12 @@ public final class StreamConfigurationMap { StreamConfiguration[] configurations = (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthConfigurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicConfigurations : mConfigurations; StreamConfigurationDuration[] minFrameDurations = (dataspace == HAL_DATASPACE_DEPTH) ? mDepthMinFrameDurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthMinFrameDurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicMinFrameDurations : mMinFrameDurations; for (StreamConfiguration config : configurations) { @@ -1445,7 +1549,8 @@ public final class StreamConfigurationMap { } // Dynamic depth streams can have both fast and also high res modes. - if ((sizeIndex != sizesCount) && (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH)) { + if ((sizeIndex != sizesCount) && (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH || + dataspace == HAL_DATASPACE_HEIF)) { if (sizeIndex > sizesCount) { throw new AssertionError( @@ -1485,6 +1590,9 @@ public final class StreamConfigurationMap { // Only one publicly dynamic depth format is available. formats[i++] = ImageFormat.DEPTH_JPEG; } + if (mHeicOutputFormats.size() > 0) { + formats[i++] = ImageFormat.HEIC; + } } if (formats.length != i) { throw new AssertionError("Too few formats " + i + ", expected " + formats.length); @@ -1529,10 +1637,14 @@ public final class StreamConfigurationMap { case DURATION_MIN_FRAME: return (dataspace == HAL_DATASPACE_DEPTH) ? mDepthMinFrameDurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? - mDynamicDepthMinFrameDurations : mMinFrameDurations; + mDynamicDepthMinFrameDurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicMinFrameDurations : + mMinFrameDurations; + case DURATION_STALL: return (dataspace == HAL_DATASPACE_DEPTH) ? mDepthStallDurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthStallDurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicStallDurations : mStallDurations; default: throw new IllegalArgumentException("duration was invalid"); @@ -1546,6 +1658,7 @@ public final class StreamConfigurationMap { if (output) { size += mDepthOutputFormats.size(); size += mDynamicDepthOutputFormats.size(); + size += mHeicOutputFormats.size(); } return size; @@ -1569,6 +1682,7 @@ public final class StreamConfigurationMap { StreamConfiguration[] configurations = (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthConfigurations : + (dataspace == HAL_DATASPACE_HEIF) ? mHeicConfigurations : mConfigurations; for (int i = 0; i < configurations.length; i++) { @@ -1767,6 +1881,8 @@ public final class StreamConfigurationMap { return "RAW_DEPTH"; case ImageFormat.PRIVATE: return "PRIVATE"; + case ImageFormat.HEIC: + return "HEIC"; default: return "UNKNOWN"; } @@ -1795,7 +1911,7 @@ public final class StreamConfigurationMap { private static final int HAL_DATASPACE_DEPTH = 0x1000; private static final int HAL_DATASPACE_DYNAMIC_DEPTH = 0x1002; - + private static final int HAL_DATASPACE_HEIF = 0x1003; private static final long DURATION_20FPS_NS = 50000000L; /** * @see #getDurations(int, int) @@ -1815,6 +1931,10 @@ public final class StreamConfigurationMap { private final StreamConfigurationDuration[] mDynamicDepthMinFrameDurations; private final StreamConfigurationDuration[] mDynamicDepthStallDurations; + private final StreamConfiguration[] mHeicConfigurations; + private final StreamConfigurationDuration[] mHeicMinFrameDurations; + private final StreamConfigurationDuration[] mHeicStallDurations; + private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations; private final ReprocessFormatsMap mInputOutputFormatsMap; @@ -1834,6 +1954,9 @@ public final class StreamConfigurationMap { private final SparseIntArray mDepthOutputFormats = new SparseIntArray(); /** internal format -> num dynamic depth output sizes mapping, for HAL_DATASPACE_DYNAMIC_DEPTH */ private final SparseIntArray mDynamicDepthOutputFormats = new SparseIntArray(); + /** internal format -> num heic output sizes mapping, for HAL_DATASPACE_HEIF */ + private final SparseIntArray mHeicOutputFormats = new SparseIntArray(); + /** High speed video Size -> FPS range count mapping*/ private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap = new HashMap<Size, Integer>(); diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 68f9288a93cf..269c781397ad 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -19,6 +19,7 @@ package android.os; 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 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { * 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 @@ public class GraphicsEnvironment { /** * 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 @@ public class GraphicsEnvironment { * 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 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { // 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 @@ public class GraphicsEnvironment { /** * 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 @@ public class GraphicsEnvironment { */ 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 @@ public class GraphicsEnvironment { /** * 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 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { /** * 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 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { } } - 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 @@ public class GraphicsEnvironment { 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 5ac31dc830ce..8e7906eb3c06 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -154,21 +154,6 @@ public final class DeviceConfig { } /** - * 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 a8976aa56241..e95d60465371 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9300,6 +9300,13 @@ public final class Settings { public static final String DEBUG_VIEW_ATTRIBUTES = "debug_view_attributes"; /** + * Which application package is allowed to save View attribute data. + * @hide + */ + public static final String DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE = + "debug_view_attributes_application_package"; + + /** * Whether assisted GPS should be enabled or not. * @hide */ @@ -14022,6 +14029,7 @@ public final class Settings { INSTANT_APP_SETTINGS.add(TRANSITION_ANIMATION_SCALE); INSTANT_APP_SETTINGS.add(ANIMATOR_DURATION_SCALE); INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES); + INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE); INSTANT_APP_SETTINGS.add(WTF_IS_FATAL); INSTANT_APP_SETTINGS.add(SEND_ACTION_APP_ERROR); INSTANT_APP_SETTINGS.add(ZEN_MODE); diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 43de1f89649c..ff4ee9ce7ded 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -27,6 +27,7 @@ import android.annotation.UnsupportedAppUsage; 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 @@ public final class DisplayInfo implements Parcelable { } }; - @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 c1302503134e..6a290b7fe045 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -33,8 +33,6 @@ import android.os.Handler; 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 android.widget.FrameLayout; 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 @@ public abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { } 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 03aed9a53925..5eff848e85aa 100644 --- a/core/java/android/view/RemotableViewMethod.java +++ b/core/java/android/view/RemotableViewMethod.java @@ -16,6 +16,8 @@ package android.view; +import android.annotation.TestApi; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -26,6 +28,7 @@ import java.lang.annotation.Target; * This annotation indicates that a method on a subclass of View * is alllowed to be used with the {@link android.widget.RemoteViews} mechanism. */ +@TestApi @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface RemotableViewMethod { diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index c0a4028c0301..8028715219cc 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -852,12 +852,11 @@ public final class SurfaceControl implements Parcelable { } /** - * Free all server-side state associated with this surface and - * release this object's reference. This method can only be - * called from the process that created the service. + * Release the local resources like {@link #release} but also + * remove the Surface from the screen. * @hide */ - public void destroy() { + public void remove() { if (mNativeObject != 0) { nativeDestroy(mNativeObject); mNativeObject = 0; @@ -2467,5 +2466,23 @@ public final class SurfaceControl implements Parcelable { nativeMergeTransaction(mNativeObject, other.mNativeObject); return this; } + + /** + * Equivalent to reparent with a null parent, in that it removes + * the SurfaceControl from the scene, but it also releases + * the local resources (by calling {@link SurfaceControl#release}) + * after this method returns, {@link SurfaceControl#isValid} will return + * false for the argument. + * + * @param sc The surface to remove and release. + * @return This transaction + * @hide + */ + @NonNull + public Transaction remove(@NonNull SurfaceControl sc) { + reparent(sc, null); + sc.release(); + return this; + } } } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index cd5207c50d1d..9f0800f11721 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -334,7 +334,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb updateSurface(); if (mSurfaceControl != null) { - mSurfaceControl.destroy(); + mSurfaceControl.remove(); } mSurfaceControl = null; @@ -502,11 +502,11 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb private void releaseSurfaces() { if (mSurfaceControl != null) { - mSurfaceControl.destroy(); + mSurfaceControl.remove(); mSurfaceControl = null; } if (mBackgroundControl != null) { - mBackgroundControl.destroy(); + mBackgroundControl.remove(); mBackgroundControl = null; } } @@ -816,7 +816,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb } if (mDeferredDestroySurfaceControl != null) { - mDeferredDestroySurfaceControl.destroy(); + mDeferredDestroySurfaceControl.remove(); mDeferredDestroySurfaceControl = null; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index cb8f70341ff2..3f2795ba1e00 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -35,6 +35,7 @@ import android.annotation.LayoutRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; +import android.annotation.StyleRes; import android.annotation.TestApi; import android.annotation.UiThread; import android.annotation.UnsupportedAppUsage; @@ -91,6 +92,7 @@ import android.util.LongSparseLongArray; import android.util.Pools.SynchronizedPool; import android.util.Property; import android.util.SparseArray; +import android.util.SparseIntArray; import android.util.StateSet; import android.util.SuperNotCalledException; import android.util.TypedValue; @@ -821,7 +823,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @hide */ - public static boolean mDebugViewAttributes = false; + public static boolean sDebugViewAttributes = false; + + /** + * When set to this application package view will save its attribute data. + * + * @hide + */ + public static String sDebugViewAttributesApplicationPackage; /** * Used to mark a View that has no ID. @@ -5079,6 +5088,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @LayoutRes private int mSourceLayoutId = ID_NULL; + @Nullable + private SparseIntArray mAttributeSourceResId; + + @Nullable + private int[] mAttributeResolutionStack; + + @StyleRes + private int mExplicitStyle; + /** * Cached reference to the {@link ContentCaptureSession}, is reset on {@link #invalidate()}. */ @@ -5254,7 +5272,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); - if (mDebugViewAttributes) { + retrieveExplicitStyle(context.getTheme(), attrs); + saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a, + defStyleAttr, defStyleRes); + + if (sDebugViewAttributes) { saveAttributeData(attrs, a); } @@ -5916,6 +5938,84 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Returns the ordered list of resource ID that are considered when resolving attribute values + * for this {@link View}. The list will include layout resource ID if the View is inflated from + * XML. It will also include a set of explicit styles if specified in XML using + * {@code style="..."}. Finally, it will include the default styles resolved from the theme. + * + * <p> + * <b>Note:</b> this method will only return actual values if the view attribute debugging + * is enabled in Android developer options. + * + * @return ordered list of resource ID that are considered when resolving attribute values for + * this {@link View}. + */ + @NonNull + public List<Integer> getAttributeResolutionStack() { + ArrayList<Integer> stack = new ArrayList<>(); + if (!sDebugViewAttributes) { + return stack; + } + if (mSourceLayoutId != ID_NULL) { + stack.add(mSourceLayoutId); + } + for (int i = 0; i < mAttributeResolutionStack.length; i++) { + stack.add(mAttributeResolutionStack[i]); + } + return stack; + } + + /** + * Returns the mapping of attribute resource ID to source resource ID where the attribute value + * was set. Source resource ID can either be a layout resource ID, if the value was set in XML + * within the View tag, or a style resource ID, if the attribute was set in a style. The source + * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}. + * + * <p> + * <b>Note:</b> this method will only return actual values if the view attribute debugging + * is enabled in Android developer options. + * + * @return mapping of attribute resource ID to source resource ID where the attribute value + * was set. + */ + @NonNull + public Map<Integer, Integer> getAttributeSourceResourceMap() { + HashMap<Integer, Integer> map = new HashMap<>(); + if (!sDebugViewAttributes) { + return map; + } + for (int i = 0; i < mAttributeSourceResId.size(); i++) { + map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i)); + } + return map; + } + + /** + * Returns the resource ID for the style specified using {@code style="..."} in the + * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not + * specified or otherwise not applicable. + * <p> + * Each {@link View} can have an explicit style specified in the layout file. + * This style is used first during the {@link View} attribute resolution, then if an attribute + * is not defined there the resource system looks at default style and theme as fallbacks. + * + * <p> + * <b>Note:</b> this method will only return actual values if the view attribute debugging + * is enabled in Android developer options. + * + * @return The resource ID for the style specified using {@code style="..."} in the + * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise + * if not specified or otherwise not applicable. + */ + @StyleRes + public int getExplicitStyle() { + if (!sDebugViewAttributes) { + return ID_NULL; + } + return mExplicitStyle; + } + + /** * An implementation of OnClickListener that attempts to lazily load a * named click handling method from a parent or ancestor context. */ @@ -6001,6 +6101,46 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mAttributeMap; } + private void retrieveExplicitStyle(@NonNull Resources.Theme theme, + @Nullable AttributeSet attrs) { + if (!sDebugViewAttributes) { + return; + } + mExplicitStyle = theme.getExplicitStyle(attrs); + } + + /** + * Stores debugging information about attributes. This should be called in a constructor by + * every custom {@link View} that uses a custom styleable. + * @param context Context under which this view is created. + * @param styleable A reference to styleable array R.styleable.Foo + * @param attrs AttributeSet used to construct this view. + * @param t Resolved {@link TypedArray} returned by a call to + * {@link Resources#obtainAttributes(AttributeSet, int[])}. + * @param defStyleAttr Default style attribute passed into the view constructor. + * @param defStyleRes Default style resource passed into the view constructor. + */ + public final void saveAttributeDataForStyleable(@NonNull Context context, + @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t, + int defStyleAttr, int defStyleRes) { + if (!sDebugViewAttributes) { + return; + } + + mAttributeResolutionStack = context.getTheme().getAttributeResolutionStack( + defStyleAttr, defStyleRes, mExplicitStyle); + + if (mAttributeSourceResId == null) { + mAttributeSourceResId = new SparseIntArray(); + } + + final int indexCount = t.getIndexCount(); + for (int j = 0; j < indexCount; ++j) { + final int index = t.getIndex(j); + mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0)); + } + } + private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) { final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount(); final int indexCount = t.getIndexCount(); @@ -23289,7 +23429,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * @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 67cca56bbb8a..156972f6ecbb 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1603,7 +1603,7 @@ public final class ViewRootImpl implements ViewParent, 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 f1c7b695ce05..5608bb372701 100644 --- a/core/java/android/view/autofill/AutofillId.java +++ b/core/java/android/view/autofill/AutofillId.java @@ -52,11 +52,13 @@ public final class AutofillId implements Parcelable { } /** @hide */ + @TestApi public AutofillId(int parentId, int virtualChildId) { this(FLAG_IS_VIRTUAL_INT, parentId, virtualChildId, NO_SESSION); } /** @hide */ + @TestApi public AutofillId(@NonNull AutofillId parent, long virtualChildId, int sessionId) { this(FLAG_IS_VIRTUAL_LONG | FLAG_HAS_SESSION, parent.mViewId, virtualChildId, sessionId); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 1c96b87394b6..83fc017373a6 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -346,9 +346,6 @@ public final class AutofillManager { @TestApi public static final int FLAG_SMART_SUGGESTION_SYSTEM = 0x1; - /** @hide */ // TODO(b/123233342): remove when not used anymore - public static final int FLAG_SMART_SUGGESTION_LEGACY = 0x2; - /** @hide */ @IntDef(flag = true, prefix = { "FLAG_SMART_SUGGESTION_" }, value = { FLAG_SMART_SUGGESTION_SYSTEM diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java index 924bb9a7d853..8d6245458d62 100644 --- a/core/java/android/view/contentcapture/ViewNode.java +++ b/core/java/android/view/contentcapture/ViewNode.java @@ -34,7 +34,6 @@ import android.view.ViewStructure.HtmlInfo.Builder; import android.view.autofill.AutofillId; import android.view.autofill.AutofillValue; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; //TODO(b/122484602): add javadocs / implement Parcelable / implement @@ -589,6 +588,7 @@ public final class ViewNode extends AssistStructure.ViewNode { } /** @hide */ + @TestApi public static void writeToParcel(@NonNull Parcel parcel, @Nullable ViewNode node, int flags) { if (node == null) { parcel.writeLong(0); @@ -598,18 +598,20 @@ public final class ViewNode extends AssistStructure.ViewNode { } /** @hide */ + @TestApi public static @Nullable ViewNode readFromParcel(@NonNull Parcel parcel) { final long nodeFlags = parcel.readLong(); return nodeFlags == 0 ? null : new ViewNode(nodeFlags, parcel); } /** @hide */ - @VisibleForTesting // Must be public to be accessed from FrameworkCoreTests' apk. + @TestApi public static final class ViewStructureImpl extends ViewStructure { final ViewNode mNode = new ViewNode(); - @VisibleForTesting // Must be public to be accessed from FrameworkCoreTests' apk. + /** @hide */ + @TestApi public ViewStructureImpl(@NonNull View view) { mNode.mAutofillId = Preconditions.checkNotNull(view).getAutofillId(); final ViewParent parent = view.getParent(); @@ -618,13 +620,15 @@ public final class ViewNode extends AssistStructure.ViewNode { } } - @VisibleForTesting // Must be public to be accessed from FrameworkCoreTests' apk. + /** @hide */ + @TestApi public ViewStructureImpl(@NonNull AutofillId parentId, long virtualId, int sessionId) { mNode.mParentAutofillId = Preconditions.checkNotNull(parentId); mNode.mAutofillId = new AutofillId(parentId, virtualId, sessionId); } - @VisibleForTesting // Must be public to be accessed from FrameworkCoreTests' apk. + /** @hide */ + @TestApi public ViewNode getNode() { return mNode; } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 542df4562908..1f8a9086ccb6 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -708,15 +708,23 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te /** * 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 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te 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 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } private void invalidateTopGlow() { - if (mEdgeGlowTop == null) { + if (!shouldDisplayEdgeEffects()) { return; } final boolean clipToPadding = getClipToPadding(); @@ -3783,7 +3776,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } private void invalidateBottomGlow() { - if (mEdgeGlowBottom == null) { + if (!shouldDisplayEdgeEffects()) { return; } final boolean clipToPadding = getClipToPadding(); @@ -4208,7 +4201,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te setPressed(false); - if (mEdgeGlowTop != null) { + if (shouldDisplayEdgeEffects()) { mEdgeGlowTop.onRelease(); mEdgeGlowBottom.onRelease(); } @@ -4233,6 +4226,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } + private boolean shouldDisplayEdgeEffects() { + return getOverScrollMode() != OVER_SCROLL_NEVER; + } + private void onTouchCancel() { switch (mTouchMode) { case TOUCH_MODE_OVERSCROLL: @@ -4258,7 +4255,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te recycleVelocityTracker(); } - if (mEdgeGlowTop != null) { + if (shouldDisplayEdgeEffects()) { mEdgeGlowTop.onRelease(); mEdgeGlowBottom.onRelease(); } @@ -4379,7 +4376,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te @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 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } private void finishGlows() { - if (mEdgeGlowTop != null) { + if (shouldDisplayEdgeEffects()) { mEdgeGlowTop.finish(); mEdgeGlowBottom.finish(); } @@ -6478,6 +6475,76 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } /** + * 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 7e42862558e4..fa0af78694ab 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 @@ import android.view.animation.Interpolator; * {@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 @@ public class EdgeEffect { 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 @@ public class EdgeEffect { 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 @@ public class EdgeEffect { } /** + * 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 @@ public class EdgeEffect { 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 d5b1a3d69dfe..249f49956256 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -1013,7 +1013,7 @@ public final class Magnifier { } synchronized (mLock) { mRenderer.destroy(); - mSurfaceControl.destroy(); + mSurfaceControl.remove(); mSurfaceSession.kill(); mHandler.removeCallbacks(mMagnifierUpdater); if (mBitmap != null) { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 0f4e23d87e0e..d87600125a54 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -1055,6 +1055,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int inputType = EditorInfo.TYPE_NULL; a = theme.obtainStyledAttributes( attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes); + saveAttributeDataForStyleable(context, com.android.internal.R.styleable.TextView, attrs, a, + defStyleAttr, defStyleRes); int firstBaselineToTopHeight = -1; int lastBaselineToBottomHeight = -1; int lineHeight = -1; diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index 06625b36f162..e2e66ceb6fbe 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -32,6 +32,17 @@ void setDriverPath(JNIEnv* env, jobject clazz, jstring path) { 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 @@ void setDebugLayersGLES_native(JNIEnv* env, jobject clazz, jstring layers) { 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 4101c04162af..d493ddfaae13 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -1105,6 +1105,46 @@ static jobjectArray NativeGetSizeConfigurations(JNIEnv* env, jclass /*clazz*/, j return array; } +static jintArray NativeAttributeResolutionStack( + JNIEnv* env, jclass /*clazz*/, jlong ptr, + jlong theme_ptr, jint xml_style_res, + jint def_style_attr, jint def_style_resid) { + + ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + Theme* theme = reinterpret_cast<Theme*>(theme_ptr); + CHECK(theme->GetAssetManager() == &(*assetmanager)); + (void) assetmanager; + + // Load default style from attribute, if specified... + uint32_t def_style_flags = 0u; + if (def_style_attr != 0) { + Res_value value; + if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) { + if (value.dataType == Res_value::TYPE_REFERENCE) { + def_style_resid = value.data; + } + } + } + + auto style_stack = assetmanager->GetBagResIdStack(xml_style_res); + auto def_style_stack = assetmanager->GetBagResIdStack(def_style_resid); + + jintArray array = env->NewIntArray(style_stack.size() + def_style_stack.size()); + if (env->ExceptionCheck()) { + return nullptr; + } + + for (uint32_t i = 0; i < style_stack.size(); i++) { + jint attr_resid = style_stack[i]; + env->SetIntArrayRegion(array, i, 1, &attr_resid); + } + for (uint32_t i = 0; i < def_style_stack.size(); i++) { + jint attr_resid = def_style_stack[i]; + env->SetIntArrayRegion(array, style_stack.size() + i, 1, &attr_resid); + } + return array; +} + static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr, jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) { @@ -1456,6 +1496,7 @@ static const JNINativeMethod gAssetManagerMethods[] = { (void*)NativeGetSizeConfigurations}, // Style attribute related methods. + {"nativeAttributeResolutionStack", "(JJIII)[I", (void*)NativeAttributeResolutionStack}, {"nativeApplyStyle", "(JJIIJ[IJJ)V", (void*)NativeApplyStyle}, {"nativeResolveAttrs", "(JJII[I[I[I[I)Z", (void*)NativeResolveAttrs}, {"nativeRetrieveAttributes", "(JJ[I[I[I)Z", (void*)NativeRetrieveAttributes}, diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 67a56ae2b52d..464f24901eb1 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -58,6 +58,8 @@ namespace android { +using ui::Dataspace; + static const char* const OutOfResourcesException = "android/view/Surface$OutOfResourcesException"; @@ -132,6 +134,7 @@ int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) { case PublicFormat::JPEG: case PublicFormat::DEPTH_POINT_CLOUD: case PublicFormat::DEPTH_JPEG: + case PublicFormat::HEIC: return HAL_PIXEL_FORMAT_BLOB; case PublicFormat::DEPTH16: return HAL_PIXEL_FORMAT_Y16; @@ -146,32 +149,44 @@ int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) { android_dataspace android_view_Surface_mapPublicFormatToHalDataspace( PublicFormat f) { + Dataspace dataspace; switch(f) { case PublicFormat::JPEG: - return HAL_DATASPACE_V0_JFIF; + dataspace = Dataspace::V0_JFIF; + break; case PublicFormat::DEPTH_POINT_CLOUD: case PublicFormat::DEPTH16: case PublicFormat::RAW_DEPTH: - return HAL_DATASPACE_DEPTH; + dataspace = Dataspace::DEPTH; + break; case PublicFormat::RAW_SENSOR: case PublicFormat::RAW_PRIVATE: case PublicFormat::RAW10: case PublicFormat::RAW12: - return HAL_DATASPACE_ARBITRARY; + dataspace = Dataspace::ARBITRARY; + break; case PublicFormat::YUV_420_888: case PublicFormat::NV21: case PublicFormat::YV12: - return HAL_DATASPACE_V0_JFIF; + dataspace = Dataspace::V0_JFIF; + break; case PublicFormat::DEPTH_JPEG: - return static_cast<android_dataspace> (HAL_DATASPACE_DYNAMIC_DEPTH); + dataspace = Dataspace::DYNAMIC_DEPTH; + break; + case PublicFormat::HEIC: + dataspace = Dataspace::HEIF; + break; default: // Most formats map to UNKNOWN - return HAL_DATASPACE_UNKNOWN; + dataspace = Dataspace::UNKNOWN; + break; } + return static_cast<android_dataspace>(dataspace); } PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( int format, android_dataspace dataSpace) { + Dataspace ds = static_cast<Dataspace>(dataSpace); switch(format) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: @@ -187,8 +202,8 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( // Enums overlap in both name and value return static_cast<PublicFormat>(format); case HAL_PIXEL_FORMAT_RAW16: - switch (dataSpace) { - case HAL_DATASPACE_DEPTH: + switch (ds) { + case Dataspace::DEPTH: return PublicFormat::RAW_DEPTH; default: return PublicFormat::RAW_SENSOR; @@ -210,8 +225,8 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( return PublicFormat::PRIVATE; case HAL_PIXEL_FORMAT_Y16: // Dataspace-dependent - switch (dataSpace) { - case HAL_DATASPACE_DEPTH: + switch (ds) { + case Dataspace::DEPTH: return PublicFormat::DEPTH16; default: // Assume non-depth Y16 is just Y16. @@ -220,11 +235,13 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( break; case HAL_PIXEL_FORMAT_BLOB: // Dataspace-dependent - switch (dataSpace) { - case HAL_DATASPACE_DEPTH: + switch (ds) { + case Dataspace::DEPTH: return PublicFormat::DEPTH_POINT_CLOUD; - case HAL_DATASPACE_V0_JFIF: + case Dataspace::V0_JFIF: return PublicFormat::JPEG; + case Dataspace::HEIF: + return PublicFormat::HEIC; default: if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) { return PublicFormat::DEPTH_JPEG; diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 68be0054ae45..6b8d8b1bb91f 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -178,12 +178,13 @@ static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) { sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); + ctrl->release(); ctrl->decStrong((void *)nativeCreate); } static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) { sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); - ctrl->clear(); + ctrl->destroy(); ctrl->decStrong((void *)nativeCreate); } diff --git a/core/jni/include/android_runtime/android_view_Surface.h b/core/jni/include/android_runtime/android_view_Surface.h index 984e942207c1..3f7c00c9ff01 100644 --- a/core/jni/include/android_runtime/android_view_Surface.h +++ b/core/jni/include/android_runtime/android_view_Surface.h @@ -55,10 +55,11 @@ enum class PublicFormat { DEPTH_POINT_CLOUD = 0x101, RAW_DEPTH = 0x1002, // @hide YV12 = 0x32315659, - Y8 = 0x20203859, // @hide + Y8 = 0x20203859, Y16 = 0x20363159, // @hide DEPTH16 = 0x44363159, DEPTH_JPEG = 0x69656963, + HEIC = 0x48454946, }; /* Gets the underlying ANativeWindow for a Surface. */ diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index a160451ecfed..d5776534bb90 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -259,6 +259,8 @@ message GlobalSettingsProto { optional SettingProto app = 1; // Whether views are allowed to save their attribute data. optional SettingProto view_attributes = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Which application package is allowed to save view attribute data. + optional SettingProto view_attributes_application_package = 3 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Debug debug = 37; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 60b04cf6c77b..07dd26e4969b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -662,8 +662,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readContacts" android:description="@string/permdesc_readContacts" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to write the user's contacts data. <p>Protection level: dangerous @@ -694,8 +693,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCalendar" android:description="@string/permdesc_readCalendar" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to write the user's calendar data. <p>Protection level: dangerous @@ -736,8 +734,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveSms" android:description="@string/permdesc_receiveSms" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to read SMS messages. <p>Protection level: dangerous @@ -746,8 +743,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readSms" android:description="@string/permdesc_readSms" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to receive WAP push messages. <p>Protection level: dangerous @@ -756,8 +752,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveWapPush" android:description="@string/permdesc_receiveWapPush" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to monitor incoming MMS messages. <p>Protection level: dangerous @@ -766,8 +761,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveMms" android:description="@string/permdesc_receiveMms" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast messages and to register a content observer to get notifications when @@ -785,8 +779,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCellBroadcasts" android:description="@string/permdesc_readCellBroadcasts" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- ====================================================================== --> <!-- Permissions for accessing external storage --> @@ -867,8 +860,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_audioRead" android:description="@string/permdesc_audioRead" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Runtime permission controlling access to the user's shared visual media collection, including images and videos. --> @@ -884,16 +876,14 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_imagesRead" android:description="@string/permdesc_imagesRead" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to read the user's shared video collection. --> <permission android:name="android.permission.READ_MEDIA_VIDEO" android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_videoRead" android:description="@string/permdesc_videoRead" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to access any geographic locations persisted in the user's shared collection. --> @@ -901,8 +891,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_mediaLocation" android:description="@string/permdesc_mediaLocation" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- @hide @SystemApi @TestApi Allows an application to modify OBB files visible to other apps. --> @@ -934,8 +923,7 @@ android:label="@string/permlab_accessFineLocation" android:description="@string/permdesc_accessFineLocation" android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- Allows an app to access approximate location. Alternatively, you might want {@link #ACCESS_FINE_LOCATION}. @@ -946,8 +934,7 @@ android:label="@string/permlab_accessCoarseLocation" android:description="@string/permdesc_accessCoarseLocation" android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- Allows an app to access location in the background. If you are requesting this, you should also request {@link #ACCESS_FINE_LOCATION}. @@ -959,8 +946,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_accessBackgroundLocation" android:description="@string/permdesc_accessBackgroundLocation" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> <!-- Permissions for accessing the call log --> @@ -1001,8 +987,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCallLog" android:description="@string/permdesc_readCallLog" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an application to write (but not read) the user's call log data. @@ -1032,8 +1017,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_processOutgoingCalls" android:description="@string/permdesc_processOutgoingCalls" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- ====================================================================== --> <!-- Permissions for accessing the device telephony --> @@ -1065,8 +1049,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readPhoneState" android:description="@string/permdesc_readPhoneState" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities granted by {@link #READ_PHONE_STATE} but is exposed to instant applications. @@ -1075,8 +1058,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readPhoneNumbers" android:description="@string/permdesc_readPhoneNumbers" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call. @@ -1178,8 +1160,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_recordAudio" android:description="@string/permdesc_recordAudio" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> <!-- Permissions for activity recognition --> @@ -1202,8 +1183,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_activityRecognition" android:description="@string/permdesc_activityRecognition" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> <!-- Permissions for accessing the UCE Service --> @@ -1252,8 +1232,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_camera" android:description="@string/permdesc_camera" - android:protectionLevel="dangerous|instant" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> @@ -1277,8 +1256,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_bodySensors" android:description="@string/permdesc_bodySensors" - android:protectionLevel="dangerous" - android:usageInfoRequired="true" /> + android:protectionLevel="dangerous" /> <!-- Allows an app to use fingerprint hardware. <p>Protection level: normal @@ -1780,8 +1758,7 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:protectionLevel="dangerous" android:description="@string/permdesc_getAccounts" - android:label="@string/permlab_getAccounts" - android:usageInfoRequired="true" /> + android:label="@string/permlab_getAccounts" /> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> <!-- Allows applications to call into AccountAuthenticators. diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index fa3a549463f5..46e14b41960c 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2426,6 +2426,8 @@ </attr> <attr name="__removed3" /> + <attr name="__removed4" /> + <attr name="__removed5" /> <!-- Describes the content of a view so that a autofill service can fill in the appropriate data. Multiple hints can be combined in a comma separated list or an array of strings diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 881688bd00c0..53cae638db80 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1689,10 +1689,6 @@ <attr name="request" /> <attr name="protectionLevel" /> <attr name="permissionFlags" /> - <!-- If {@code true} applications that target Q <em>must</em> specify the permission usage - attributes in their {@code uses-permission} elements or the permission will not be - granted. --> - <attr name="usageInfoRequired" format="boolean" /> </declare-styleable> <!-- The <code>permission-group</code> tag declares a logical grouping of @@ -1792,81 +1788,6 @@ requested. If it does support the feature, it will be as if the manifest didn't request it at all. --> <attr name="requiredNotFeature" format="string" /> - - <!-- Specify if the app uploads data, or derived data, guarded by this permission. - - If the permission is defined with {@link android.R.attr#usageInfoRequired} - {@code true} this <em>must</em> be specified by apps that target Android Q or the - permission will not be granted, it will be as if the manifest didn't request it at all. - --> - <attr name="dataSentOffDevice"> - <!-- The application may send data, or derived data, guarded by this permission off of the - device. --> - <enum name="yes" value="1" /> - <!-- The application may send data, or derived data, guarded by this permission off of the - device, however it will only do so when explicitly triggered by a user action. --> - <enum name="userTriggered" value="2" /> - <!-- The application does not send data, or derived data, guarded by this permission off - of the device. --> - <enum name="no" value="3" /> - </attr> - - <!-- Specify if the application or its related off-device services provide data, - or derived data, guarded by this permission to third parties outside of the developer's - organization that do not qualify as data processors. - - If the permission is defined with {@link android.R.attr#usageInfoRequired} - {@code true} this <em>must</em> be specified by apps that target Android Q or the - permission will not be granted, it will be as if the manifest didn't request it at all. - --> - <attr name="dataSharedWithThirdParty"> - <!-- The application or its services may provide data, or derived data, guarded by this - permission to third party organizations. --> - <enum name="yes" value="1" /> - <!-- The application or its services may provide data, or derived data, guarded by this - permission to third party organizations, however it will only do so when explicitly - triggered by a user action. --> - <enum name="userTriggered" value="2" /> - <!-- The application or its services does not provide data, or derived data, guarded by - this permission to third party organizations. --> - <enum name="no" value="3" /> - </attr> - - <!-- Specify if the application or its related off-device services use data, - or derived data, guarded by this permission for monetization purposes. - - For example, if the data is sold to another party or used for targeting advertisements - this must be set to {@code yes}. - - If the permission is defined with {@link android.R.attr#usageInfoRequired} - {@code true} this <em>must</em> be specified by apps that target Android Q or the - permission will not be granted, it will be as if the manifest didn't request it at all. - --> - <attr name="dataUsedForMonetization"> - <!-- The application or its services may use data, or derived data, guarded by this - permission for monetization purposes. --> - <enum name="yes" value="1" /> - <!-- The application or its services may use data, or derived data, guarded by this - permission for monetization purposes, however it will only do so when explicity - triggered by a user action. --> - <enum name="userTriggered" value="2" /> - <!-- The application or its services does not use data, or derived data, guarded by - this permission for monetization purposes. --> - <enum name="no" value="3" /> - </attr> - - <!-- Specify how long the application or its related off-device services store - data, or derived data, guarded by this permission. - - This can be one of "notRetained", "userSelected", "unlimited", or a number - representing the number of weeks the data is retained. - - If the permission is defined with {@link android.R.attr#usageInfoRequired} - {@code true} this <em>must</em> be specified by apps that target Android Q or the - permission will not be granted, it will be as if the manifest didn't request it at all. - --> - <attr name="dataRetentionTime" format="string" /> - </declare-styleable> <!-- The <code>uses-configuration</code> tag specifies diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index f84f1f1bdb4f..e6d478aadae0 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2925,11 +2925,11 @@ <public name="importantForContentCapture" /> <public name="supportsMultipleDisplays" /> <public name="useAppZygote" /> - <public name="usageInfoRequired" /> - <public name="dataSentOffDevice" /> - <public name="dataSharedWithThirdParty" /> - <public name="dataUsedForMonetization" /> - <public name="dataRetentionTime" /> + <public name="__removed1" /> + <public name="__removed2" /> + <public name="__removed3" /> + <public name="__removed4" /> + <public name="__removed5" /> <public name="selectionDividerHeight" /> <public name="foregroundServiceType" /> <public name="hasFragileUserData" /> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 2cb925aa9549..ec57f793f15f 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -210,6 +210,7 @@ public class SettingsBackupTest { Settings.Global.DATA_STALL_VALID_DNS_TIME_THRESHOLD, Settings.Global.DEBUG_APP, Settings.Global.DEBUG_VIEW_ATTRIBUTES, + Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, Settings.Global.DEFAULT_DNS_SERVER, Settings.Global.DEFAULT_INSTALL_LOCATION, Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA, diff --git a/core/tests/coretests/src/android/view/contentcapture/UserDataRemovalRequestTest.java b/core/tests/coretests/src/android/view/contentcapture/UserDataRemovalRequestTest.java deleted file mode 100644 index bebb2a89f480..000000000000 --- a/core/tests/coretests/src/android/view/contentcapture/UserDataRemovalRequestTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.view.contentcapture; - -import static com.google.common.truth.Truth.assertThat; - -import static org.testng.Assert.assertThrows; - -import android.net.Uri; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -/** - * Unit test for {@link UserDataRemovalRequest}. - * - * <p>To run it: - * {@code atest FrameworksCoreTests:android.view.contentcapture.UserDataRemovalRequestTest} - */ -@RunWith(MockitoJUnitRunner.class) -public class UserDataRemovalRequestTest { - - @Mock - private final Uri mUri = Uri.parse("content://com.example/"); - - private UserDataRemovalRequest.Builder mBuilder = new UserDataRemovalRequest.Builder(); - - @Test - public void testBuilder_addUri_invalid() { - assertThrows(NullPointerException.class, () -> mBuilder.addUri(null, false)); - } - - @Test - public void testBuilder_addUri_valid() { - assertThat(mBuilder.addUri(mUri, false)).isNotNull(); - assertThat(mBuilder.addUri(Uri.parse("content://com.example2"), true)).isNotNull(); - } - - @Test - public void testBuilder_addUriAfterForEverything() { - assertThat(mBuilder.forEverything()).isNotNull(); - assertThrows(IllegalStateException.class, () -> mBuilder.addUri(mUri, false)); - } - - @Test - public void testBuilder_forEverythingAfterAddingUri() { - assertThat(mBuilder.addUri(mUri, false)).isNotNull(); - assertThrows(IllegalStateException.class, () -> mBuilder.forEverything()); - } - - @Test - public void testBuild_invalid() { - assertThrows(IllegalStateException.class, () -> mBuilder.build()); - } - - @Test - public void testBuild_valid() { - assertThat(new UserDataRemovalRequest.Builder().forEverything().build()) - .isNotNull(); - assertThat(new UserDataRemovalRequest.Builder().addUri(mUri, false).build()) - .isNotNull(); - } - - @Test - public void testNoMoreInteractionsAfterBuild() { - assertThat(mBuilder.forEverything().build()).isNotNull(); - - assertThrows(IllegalStateException.class, () -> mBuilder.addUri(mUri, false)); - assertThrows(IllegalStateException.class, () -> mBuilder.forEverything()); - assertThrows(IllegalStateException.class, () -> mBuilder.build()); - - } -} diff --git a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java index b84a098574c2..213cd405e903 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java @@ -18,29 +18,18 @@ package android.view.contentcapture; import static com.google.common.truth.Truth.assertThat; -import static org.testng.Assert.assertThrows; - import android.content.Context; import android.graphics.Matrix; -import android.os.Bundle; -import android.os.LocaleList; -import android.os.Parcel; +import android.support.test.InstrumentationRegistry; import android.view.View; import android.view.ViewStructure.HtmlInfo; -import android.view.autofill.AutofillId; -import android.view.autofill.AutofillValue; import android.view.contentcapture.ViewNode.ViewStructureImpl; -import android.widget.FrameLayout; - -import androidx.test.InstrumentationRegistry; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import java.util.Locale; - /** * Unit tests for {@link ViewNode}. * @@ -55,100 +44,6 @@ public class ViewNodeTest { private HtmlInfo mHtmlInfoMock; @Test - public void testAutofillIdMethods_orphanView() { - View view = new View(mContext); - AutofillId initialId = new AutofillId(42); - view.setAutofillId(initialId); - - ViewStructureImpl structure = new ViewStructureImpl(view); - ViewNode node = structure.getNode(); - - assertThat(node.getAutofillId()).isEqualTo(initialId); - assertThat(node.getParentAutofillId()).isNull(); - - AutofillId newId = new AutofillId(108); - structure.setAutofillId(newId); - assertThat(node.getAutofillId()).isEqualTo(newId); - assertThat(node.getParentAutofillId()).isNull(); - - structure.setAutofillId(new AutofillId(66), 6); - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6)); - assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66)); - } - - @Test - public void testAutofillIdMethods_parentedView() { - FrameLayout parent = new FrameLayout(mContext); - AutofillId initialParentId = new AutofillId(48); - parent.setAutofillId(initialParentId); - - View child = new View(mContext); - AutofillId initialChildId = new AutofillId(42); - child.setAutofillId(initialChildId); - - parent.addView(child); - - ViewStructureImpl structure = new ViewStructureImpl(child); - ViewNode node = structure.getNode(); - - assertThat(node.getAutofillId()).isEqualTo(initialChildId); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - AutofillId newChildId = new AutofillId(108); - structure.setAutofillId(newChildId); - assertThat(node.getAutofillId()).isEqualTo(newChildId); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - AutofillId newParentId = new AutofillId(15162342); - parent.setAutofillId(newParentId); - assertThat(node.getAutofillId()).isEqualTo(newChildId); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - structure.setAutofillId(new AutofillId(66), 6); - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6)); - assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66)); - } - - @Test - public void testAutofillIdMethods_explicitIdsConstructor() { - AutofillId initialParentId = new AutofillId(42); - ViewStructureImpl structure = new ViewStructureImpl(initialParentId, 108, 666); - ViewNode node = structure.getNode(); - - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(initialParentId, 108, 666)); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - AutofillId newChildId = new AutofillId(108); - structure.setAutofillId(newChildId); - assertThat(node.getAutofillId()).isEqualTo(newChildId); - assertThat(node.getParentAutofillId()).isEqualTo(initialParentId); - - structure.setAutofillId(new AutofillId(66), 6); - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6)); - assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66)); - } - - @Test - public void testInvalidSetters() { - View view = new View(mContext); - AutofillId initialId = new AutofillId(42); - view.setAutofillId(initialId); - - ViewStructureImpl structure = new ViewStructureImpl(view); - ViewNode node = structure.getNode(); - assertThat(node.getAutofillId()).isEqualTo(initialId); // sanity check - - assertThrows(NullPointerException.class, () -> structure.setAutofillId(null)); - assertThat(node.getAutofillId()).isEqualTo(initialId); // invariant - - assertThrows(NullPointerException.class, () -> structure.setAutofillId(null, 666)); - assertThat(node.getAutofillId()).isEqualTo(initialId); // invariant - - assertThrows(NullPointerException.class, () -> structure.setTextIdEntry(null)); - assertThat(node.getTextIdEntry()).isNull(); - } - - @Test public void testUnsupportedProperties() { View view = new View(mContext); @@ -190,273 +85,4 @@ public class ViewNodeTest { structure.setTransformation(Matrix.IDENTITY_MATRIX); assertThat(node.getTransformation()).isNull(); } - - @Test - public void testValidProperties_directly() { - ViewStructureImpl structure = newSimpleStructure(); - assertSimpleStructure(structure); - assertSimpleNode(structure.getNode()); - } - - @Test - public void testValidProperties_throughParcel() { - ViewStructureImpl structure = newSimpleStructure(); - final ViewNode node = structure.getNode(); - assertSimpleNode(node); // sanity check - - final ViewNode clone = cloneThroughParcel(node); - assertSimpleNode(clone); - } - - @Test - public void testComplexText_directly() { - ViewStructureImpl structure = newStructureWithComplexText(); - assertStructureWithComplexText(structure); - assertNodeWithComplexText(structure.getNode()); - } - - @Test - public void testComplexText_throughParcel() { - ViewStructureImpl structure = newStructureWithComplexText(); - final ViewNode node = structure.getNode(); - assertNodeWithComplexText(node); // sanity check - - ViewNode clone = cloneThroughParcel(node); - assertNodeWithComplexText(clone); - } - - @Test - public void testVisibility() { - // Visibility is a special case becase it use flag masks, so we want to make sure it works - // fine - View view = new View(mContext); - ViewStructureImpl structure = new ViewStructureImpl(view); - ViewNode node = structure.getNode(); - - structure.setVisibility(View.VISIBLE); - assertThat(node.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE); - - structure.setVisibility(View.GONE); - assertThat(node.getVisibility()).isEqualTo(View.GONE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.GONE); - - structure.setVisibility(View.VISIBLE); - assertThat(node.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE); - - structure.setVisibility(View.INVISIBLE); - assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.INVISIBLE); - - structure.setVisibility(View.INVISIBLE | View.GONE); - assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE | View.GONE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.INVISIBLE | View.GONE); - - - final int invalidValue = Math.max(Math.max(View.VISIBLE, View.INVISIBLE), View.GONE) * 2; - structure.setVisibility(View.VISIBLE); - structure.setVisibility(invalidValue); // should be ignored - assertThat(node.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE); - - structure.setVisibility(View.GONE | invalidValue); - assertThat(node.getVisibility()).isEqualTo(View.GONE); - assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.GONE); - } - - /** - * Creates a {@link ViewStructureImpl} that can be asserted through - * {@link #assertSimpleNode(ViewNode)}. - */ - private ViewStructureImpl newSimpleStructure() { - View view = new View(mContext); - view.setAutofillId(new AutofillId(42)); - - ViewStructureImpl structure = new ViewStructureImpl(view); - - // Basic properties - structure.setText("Text is set!"); - structure.setClassName("Classy!"); - structure.setContentDescription("Described I am!"); - structure.setVisibility(View.INVISIBLE); - - // Autofill properties - structure.setAutofillType(View.AUTOFILL_TYPE_TEXT); - structure.setAutofillHints(new String[] { "Auto", "Man" }); - structure.setAutofillOptions(new String[] { "Maybe" }); - structure.setAutofillValue(AutofillValue.forText("Malkovich")); - - // Extra text properties - structure.setMinTextEms(6); - structure.setMaxTextLength(66); - structure.setMaxTextEms(666); - structure.setInputType(42); - structure.setTextIdEntry("TEXT, Y U NO ENTRY?"); - structure.setLocaleList(new LocaleList(Locale.US, Locale.ENGLISH)); - - // Resource id - structure.setId(16, "package.name", "type.name", "entry.name"); - - // Dimensions - structure.setDimens(4, 8, 15, 16, 23, 42); - - // Boolean properties - structure.setAssistBlocked(true); - structure.setEnabled(true); - structure.setClickable(true); - structure.setLongClickable(true); - structure.setContextClickable(true); - structure.setFocusable(true); - structure.setFocused(true); - structure.setAccessibilityFocused(true); - structure.setChecked(true); - structure.setActivated(true); - structure.setOpaque(true); - - // Bundle - assertThat(structure.hasExtras()).isFalse(); - final Bundle bundle = structure.getExtras(); - assertThat(bundle).isNotNull(); - bundle.putString("Marlon", "Bundle"); - assertThat(structure.hasExtras()).isTrue(); - return structure; - } - - /** - * Asserts the properties of a {@link ViewNode} that was created by - * {@link #newSimpleStructure()}. - */ - private void assertSimpleNode(ViewNode node) { - - // Basic properties - assertThat(node.getAutofillId()).isEqualTo(new AutofillId(42)); - assertThat(node.getParentAutofillId()).isNull(); - assertThat(node.getText()).isEqualTo("Text is set!"); - assertThat(node.getClassName()).isEqualTo("Classy!"); - assertThat(node.getContentDescription().toString()).isEqualTo("Described I am!"); - assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE); - - // Autofill properties - assertThat(node.getAutofillType()).isEqualTo(View.AUTOFILL_TYPE_TEXT); - assertThat(node.getAutofillHints()).asList().containsExactly("Auto", "Man").inOrder(); - assertThat(node.getAutofillOptions()).asList().containsExactly("Maybe").inOrder(); - assertThat(node.getAutofillValue().getTextValue()).isEqualTo("Malkovich"); - - // Extra text properties - assertThat(node.getMinTextEms()).isEqualTo(6); - assertThat(node.getMaxTextLength()).isEqualTo(66); - assertThat(node.getMaxTextEms()).isEqualTo(666); - assertThat(node.getInputType()).isEqualTo(42); - assertThat(node.getTextIdEntry()).isEqualTo("TEXT, Y U NO ENTRY?"); - assertThat(node.getLocaleList()).isEqualTo(new LocaleList(Locale.US, Locale.ENGLISH)); - - // Resource id - assertThat(node.getId()).isEqualTo(16); - assertThat(node.getIdPackage()).isEqualTo("package.name"); - assertThat(node.getIdType()).isEqualTo("type.name"); - assertThat(node.getIdEntry()).isEqualTo("entry.name"); - - // Dimensions - assertThat(node.getLeft()).isEqualTo(4); - assertThat(node.getTop()).isEqualTo(8); - assertThat(node.getScrollX()).isEqualTo(15); - assertThat(node.getScrollY()).isEqualTo(16); - assertThat(node.getWidth()).isEqualTo(23); - assertThat(node.getHeight()).isEqualTo(42); - - // Boolean properties - assertThat(node.isAssistBlocked()).isTrue(); - assertThat(node.isEnabled()).isTrue(); - assertThat(node.isClickable()).isTrue(); - assertThat(node.isLongClickable()).isTrue(); - assertThat(node.isContextClickable()).isTrue(); - assertThat(node.isFocusable()).isTrue(); - assertThat(node.isFocused()).isTrue(); - assertThat(node.isAccessibilityFocused()).isTrue(); - assertThat(node.isChecked()).isTrue(); - assertThat(node.isActivated()).isTrue(); - assertThat(node.isOpaque()).isTrue(); - - // Bundle - final Bundle bundle = node.getExtras(); - assertThat(bundle).isNotNull(); - assertThat(bundle.size()).isEqualTo(1); - assertThat(bundle.getString("Marlon")).isEqualTo("Bundle"); - } - - /** - * Asserts the properties of a {@link ViewStructureImpl} that was created by - * {@link #newSimpleStructure()}. - */ - private void assertSimpleStructure(ViewStructureImpl structure) { - assertThat(structure.getAutofillId()).isEqualTo(new AutofillId(42)); - assertThat(structure.getText()).isEqualTo("Text is set!"); - - // Bundle - final Bundle bundle = structure.getExtras(); - assertThat(bundle.size()).isEqualTo(1); - assertThat(bundle.getString("Marlon")).isEqualTo("Bundle"); - } - - /** - * Creates a {@link ViewStructureImpl} with "complex" text properties (such as selection); it - * can be asserted through {@link #assertNodeWithComplexText(ViewNode)}. - */ - private ViewStructureImpl newStructureWithComplexText() { - View view = new View(mContext); - ViewStructureImpl structure = new ViewStructureImpl(view); - structure.setText("IGNORE ME!"); - structure.setText("Now we're talking!", 4, 8); - structure.setHint("Soylent Green is SPOILER ALERT"); - structure.setTextStyle(15.0f, 16, 23, 42); - structure.setTextLines(new int[] {4, 8, 15} , new int[] {16, 23, 42}); - return structure; - } - - /** - * Asserts the properties of a {@link ViewNode} that was created by - * {@link #newStructureWithComplexText()}. - */ - private void assertNodeWithComplexText(ViewNode node) { - assertThat(node.getText()).isEqualTo("Now we're talking!"); - assertThat(node.getTextSelectionStart()).isEqualTo(4); - assertThat(node.getTextSelectionEnd()).isEqualTo(8); - assertThat(node.getHint()).isEqualTo("Soylent Green is SPOILER ALERT"); - assertThat(node.getTextSize()).isWithin(1.0e-10f).of(15.0f); - assertThat(node.getTextColor()).isEqualTo(16); - assertThat(node.getTextBackgroundColor()).isEqualTo(23); - assertThat(node.getTextStyle()).isEqualTo(42); - assertThat(node.getTextLineCharOffsets()).asList().containsExactly(4, 8, 15).inOrder(); - assertThat(node.getTextLineBaselines()).asList().containsExactly(16, 23, 42).inOrder(); - } - - /** - * Asserts the properties of a {@link ViewStructureImpl} that was created by - * {@link #newStructureWithComplexText()}. - */ - private void assertStructureWithComplexText(ViewStructureImpl structure) { - assertThat(structure.getText()).isEqualTo("Now we're talking!"); - assertThat(structure.getTextSelectionStart()).isEqualTo(4); - assertThat(structure.getTextSelectionEnd()).isEqualTo(8); - assertThat(structure.getHint()).isEqualTo("Soylent Green is SPOILER ALERT"); - } - - private ViewNode cloneThroughParcel(ViewNode node) { - Parcel parcel = Parcel.obtain(); - - try { - // Write to parcel - parcel.setDataPosition(0); // Sanity / paranoid check - ViewNode.writeToParcel(parcel, node, 0); - - // Read from parcel - parcel.setDataPosition(0); - ViewNode clone = ViewNode.readFromParcel(parcel); - assertThat(clone).isNotNull(); - return clone; - } finally { - parcel.recycle(); - } - } } diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java index 0787d8518fa5..62647741dcfa 100644 --- a/graphics/java/android/graphics/ImageFormat.java +++ b/graphics/java/android/graphics/ImageFormat.java @@ -716,6 +716,14 @@ public class ImageFormat { public static final int PRIVATE = 0x22; /** + * Compressed HEIC format. + * + * <p>This format defines the HEIC brand of High Efficiency Image File + * Format as described in ISO/IEC 23008-12.</p> + */ + public static final int HEIC = 0x48454946; + + /** * Use this function to retrieve the number of bits per pixel of an * ImageFormat. * @@ -796,6 +804,7 @@ public class ImageFormat { case RAW_DEPTH: case Y8: case DEPTH_JPEG: + case HEIC: return true; } diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 73442db1c143..e617c42cc70d 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1279,7 +1279,6 @@ public class Paint { * (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 20303eba6667..81afd937d85e 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -704,9 +704,29 @@ ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_valu return cookie; } +const std::vector<uint32_t> AssetManager2::GetBagResIdStack(uint32_t resid) { + auto cached_iter = cached_bag_resid_stacks_.find(resid); + if (cached_iter != cached_bag_resid_stacks_.end()) { + return cached_iter->second; + } else { + auto found_resids = std::vector<uint32_t>(); + GetBag(resid, found_resids); + // Cache style stacks if they are not already cached. + cached_bag_resid_stacks_[resid] = found_resids; + return found_resids; + } +} + const ResolvedBag* AssetManager2::GetBag(uint32_t resid) { auto found_resids = std::vector<uint32_t>(); - return GetBag(resid, found_resids); + auto bag = GetBag(resid, found_resids); + + // Cache style stacks if they are not already cached. + auto cached_iter = cached_bag_resid_stacks_.find(resid); + if (cached_iter == cached_bag_resid_stacks_.end()) { + cached_bag_resid_stacks_[resid] = found_resids; + } + return bag; } const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>& child_resids) { diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index f29769b834d1..d862182d8960 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -237,6 +237,8 @@ class AssetManager2 { // resource has been resolved yet. std::string GetLastResourceResolution() const; + const std::vector<uint32_t> GetBagResIdStack(uint32_t resid); + // Retrieves the best matching bag/map resource with ID `resid`. // This method will resolve all parent references for this bag and merge keys with the child. // To iterate over the keys, use the following idiom: @@ -355,6 +357,10 @@ class AssetManager2 { // which involves some calculation. std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_; + // Cached set of bag resid stacks for each bag. These are cached because they might be requested + // a number of times for each view during View inspection. + std::unordered_map<uint32_t, std::vector<uint32_t>> cached_bag_resid_stacks_; + // Whether or not to save resource resolution steps bool resource_resolution_logging_enabled_ = false; diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java index 602cc3e6d0fd..59eff6401deb 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -17,6 +17,7 @@ package android.location; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -49,6 +50,7 @@ public final class GnssMeasurement implements Parcelable { private double mSnrInDb; private double mAutomaticGainControlLevelInDb; private int mCodeType; + private String mOtherCodeTypeName; // The following enumerations must be in sync with the values declared in gps.h @@ -209,8 +211,8 @@ public final class GnssMeasurement implements Parcelable { */ @IntDef(prefix = { "CODE_TYPE_" }, value = { CODE_TYPE_UNKNOWN, CODE_TYPE_A, CODE_TYPE_B, CODE_TYPE_C, CODE_TYPE_I, CODE_TYPE_L, - CODE_TYPE_M, CODE_TYPE_P, CODE_TYPE_Q, CODE_TYPE_S, CODE_TYPE_W, CODE_TYPE_X, - CODE_TYPE_Y, CODE_TYPE_Z, CODE_TYPE_CODELESS + CODE_TYPE_M, CODE_TYPE_N, CODE_TYPE_P, CODE_TYPE_Q, CODE_TYPE_S, CODE_TYPE_W, + CODE_TYPE_X, CODE_TYPE_Y, CODE_TYPE_Z, CODE_TYPE_OTHER }) @Retention(RetentionPolicy.SOURCE) public @interface CodeType {} @@ -299,7 +301,16 @@ public final class GnssMeasurement implements Parcelable { /** * The GNSS Measurement's code type is one of the following: GPS L1 codeless, GPS L2 codeless. */ - public static final int CODE_TYPE_CODELESS = 13; + public static final int CODE_TYPE_N = 13; + + /** + * Other code type that does not belong to any of the above code types. + * + * This code type is used in the case that the code type being tracked in this measurement, as + * classified by RINEX standards, does not fit into one of the existing enumerated values. When + * this code type is set, the field otherCodeTypeName must specify the new code type. + */ + public static final int CODE_TYPE_OTHER = 255; /** * All the 'Accumulated Delta Range' flags. @@ -349,6 +360,7 @@ public final class GnssMeasurement implements Parcelable { mSnrInDb = measurement.mSnrInDb; mAutomaticGainControlLevelInDb = measurement.mAutomaticGainControlLevelInDb; mCodeType = measurement.mCodeType; + mOtherCodeTypeName = measurement.mOtherCodeTypeName; } /** @@ -1175,8 +1187,8 @@ public final class GnssMeasurement implements Parcelable { /** * Gets the GNSS measurement's code type. * - * <p>Similar to the Attribute field described in Rinex 3.03, e.g., in Tables 4-10, and Table - * A2 at the Rinex 3.03 Update 1 Document. + * <p>Similar to the Attribute field described in RINEX 3.03, e.g., in Tables 4-10, and Table + * A2 at the RINEX 3.03 Update 1 Document. */ @CodeType public int getCodeType() { @@ -1206,6 +1218,29 @@ public final class GnssMeasurement implements Parcelable { } /** + * Gets the GNSS measurement's code type name when the code type is {@link #CODE_TYPE_OTHER}. + * + * <p>This is used to specify the observation descriptor defined in GNSS Observation Data File + * Header Section Description in the RINEX standard (Version 3.XX), in cases where the code type + * does not align with an existing Android enumerated value. For example, if a code type "G" is + * added, this string shall be set to "G". + */ + @NonNull + public String getOtherCodeTypeName() { + return mOtherCodeTypeName; + } + + /** + * Sets the GNSS measurement's code type name when the code type is {@link #CODE_TYPE_OTHER}. + * + * @hide + */ + @TestApi + public void setOtherCodeTypeName(@NonNull String otherCodeTypeName) { + mOtherCodeTypeName = otherCodeTypeName; + } + + /** * Gets a string representation of the 'code type'. * * <p>For internal and logging use only. @@ -1226,6 +1261,8 @@ public final class GnssMeasurement implements Parcelable { return "CODE_TYPE_L"; case CODE_TYPE_M: return "CODE_TYPE_M"; + case CODE_TYPE_N: + return "CODE_TYPE_N"; case CODE_TYPE_P: return "CODE_TYPE_P"; case CODE_TYPE_Q: @@ -1240,8 +1277,8 @@ public final class GnssMeasurement implements Parcelable { return "CODE_TYPE_Y"; case CODE_TYPE_Z: return "CODE_TYPE_Z"; - case CODE_TYPE_CODELESS: - return "CODE_TYPE_CODELESS"; + case CODE_TYPE_OTHER: + return "CODE_TYPE_OTHER"; default: return "<Invalid: " + mCodeType + ">"; } @@ -1273,6 +1310,7 @@ public final class GnssMeasurement implements Parcelable { gnssMeasurement.mSnrInDb = parcel.readDouble(); gnssMeasurement.mAutomaticGainControlLevelInDb = parcel.readDouble(); gnssMeasurement.mCodeType = parcel.readInt(); + gnssMeasurement.mOtherCodeTypeName = parcel.readString(); return gnssMeasurement; } @@ -1306,6 +1344,7 @@ public final class GnssMeasurement implements Parcelable { parcel.writeDouble(mSnrInDb); parcel.writeDouble(mAutomaticGainControlLevelInDb); parcel.writeInt(mCodeType); + parcel.writeString(mOtherCodeTypeName); } @Override @@ -1384,6 +1423,9 @@ public final class GnssMeasurement implements Parcelable { format, "CodeType", hasCodeType() ? getCodeTypeString() : null)); + builder.append(String.format( + format, + "OtherCodeTypeName", mOtherCodeTypeName)); return builder.toString(); } @@ -1409,6 +1451,7 @@ public final class GnssMeasurement implements Parcelable { resetSnrInDb(); resetAutomaticGainControlLevel(); resetCodeType(); + setOtherCodeTypeName(""); } private void setFlag(int flag) { diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java index 26b9b8cf85a7..70a343f4de01 100644 --- a/media/java/android/media/Image.java +++ b/media/java/android/media/Image.java @@ -155,6 +155,13 @@ public abstract class Image implements AutoCloseable { * UnSupportedOperationException being thrown. * </td> * </tr> + * <tr> + * <td>{@link android.graphics.ImageFormat#HEIC HEIC}</td> + * <td>1</td> + * <td>Compressed data, so row and pixel strides are 0. To uncompress, use + * {@link android.graphics.BitmapFactory#decodeByteArray BitmapFactory#decodeByteArray}. + * </td> + * </tr> * </table> * * @see android.graphics.ImageFormat diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index 60ef1d93191a..6116429ae561 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -821,6 +821,7 @@ public class ImageReader implements AutoCloseable { case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.RAW_PRIVATE: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: width = ImageReader.this.getWidth(); break; default: @@ -838,6 +839,7 @@ public class ImageReader implements AutoCloseable { case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.RAW_PRIVATE: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: height = ImageReader.this.getHeight(); break; default: diff --git a/media/java/android/media/ImageUtils.java b/media/java/android/media/ImageUtils.java index b77a884d3412..d8a0bb334c53 100644 --- a/media/java/android/media/ImageUtils.java +++ b/media/java/android/media/ImageUtils.java @@ -36,8 +36,8 @@ class ImageUtils { * {@link android.graphics.PixelFormat PixelFormat} are supported by * ImageReader. When reading RGB data from a surface, the formats defined in * {@link android.graphics.PixelFormat PixelFormat} can be used; when - * reading YUV, JPEG or raw sensor data (for example, from the camera or video - * decoder), formats from {@link android.graphics.ImageFormat ImageFormat} + * reading YUV, JPEG, HEIC or raw sensor data (for example, from the camera + * or video decoder), formats from {@link android.graphics.ImageFormat ImageFormat} * are used. */ public static int getNumPlanesForFormat(int format) { @@ -64,6 +64,7 @@ class ImageUtils { case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.RAW_DEPTH: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: return 1; case ImageFormat.PRIVATE: return 0; @@ -194,6 +195,7 @@ class ImageUtils { case ImageFormat.JPEG: case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.DEPTH_JPEG: + case ImageFormat.HEIC: estimatedBytePerPixel = 0.3; break; case ImageFormat.Y8: @@ -262,6 +264,7 @@ class ImageUtils { case ImageFormat.RAW10: case ImageFormat.RAW12: case ImageFormat.RAW_DEPTH: + case ImageFormat.HEIC: return new Size(image.getWidth(), image.getHeight()); case ImageFormat.PRIVATE: return new Size(0, 0); diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp index 458d8471dafd..01baadb2f024 100644 --- a/media/jni/android_media_Utils.cpp +++ b/media/jni/android_media_Utils.cpp @@ -29,6 +29,9 @@ #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) +// Must be in sync with the value in HeicCompositeStream.cpp +#define CAMERA3_HEIC_BLOB_ID 0x00FE + namespace android { AssetStream::AssetStream(SkStream* stream) @@ -609,34 +612,35 @@ bool isPossiblyYUV(PixelFormat format) { } } -uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride) { +uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) { ALOGV("%s", __FUNCTION__); LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!"); uint32_t size = 0; uint32_t width = buffer->width; - uint8_t* jpegBuffer = buffer->data; + uint8_t* blobBuffer = buffer->data; if (usingRGBAOverride) { width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4; } - // First check for JPEG transport header at the end of the buffer - uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob)); + // First check for BLOB transport header at the end of the buffer + uint8_t* header = blobBuffer + (width - sizeof(struct camera3_jpeg_blob)); struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header); - if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) { + if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID || + blob->jpeg_blob_id == CAMERA3_HEIC_BLOB_ID) { size = blob->jpeg_size; - ALOGV("%s: Jpeg size = %d", __FUNCTION__, size); + ALOGV("%s: Jpeg/Heic size = %d", __FUNCTION__, size); } // failed to find size, default to whole buffer if (size == 0) { /* - * This is a problem because not including the JPEG header - * means that in certain rare situations a regular JPEG blob + * This is a problem because not including the JPEG/BLOB header + * means that in certain rare situations a regular JPEG/HEIC blob * will be mis-identified as having a header, in which case * we will get a garbage size value. */ - ALOGW("%s: No JPEG header detected, defaulting to size=width=%d", + ALOGW("%s: No JPEG/HEIC header detected, defaulting to size=width=%d", __FUNCTION__, width); size = width; } @@ -760,7 +764,7 @@ status_t getLockedImageInfo(LockedImage* buffer, int idx, pData = buffer->data; - dataSize = Image_getJpegSize(buffer, usingRGBAOverride); + dataSize = Image_getBlobSize(buffer, usingRGBAOverride); pStride = 0; rStride = 0; break; diff --git a/media/jni/android_media_Utils.h b/media/jni/android_media_Utils.h index 821c6b25c333..19c1b88f78e8 100644 --- a/media/jni/android_media_Utils.h +++ b/media/jni/android_media_Utils.h @@ -119,7 +119,7 @@ bool usingRGBAToJpegOverride(int32_t imageFormat, int32_t containerFormat); int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat); -uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride); +uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride); bool isFormatOpaque(int format); diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml index 478ee54b40e5..cd6abb267e44 100644 --- a/packages/PrintSpooler/AndroidManifest.xml +++ b/packages/PrintSpooler/AndroidManifest.xml @@ -37,16 +37,8 @@ <uses-permission android:name="android.permission.READ_PRINT_SERVICES" /> <uses-permission android:name="android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" - android:dataSentOffDevice="no" - android:dataSharedWithThirdParty="no" - android:dataUsedForMonetization="no" - android:dataRetentionTime="unlimited"/> - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" - android:dataSentOffDevice="no" - android:dataSharedWithThirdParty="no" - android:dataUsedForMonetization="no" - android:dataRetentionTime="unlimited"/> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowClearUserData="true" diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index fad93cbf83da..6152b8cbd562 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -457,6 +457,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.DEBUG_VIEW_ATTRIBUTES, GlobalSettingsProto.Debug.VIEW_ATTRIBUTES); + dumpSetting(s, p, + Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, + GlobalSettingsProto.Debug.VIEW_ATTRIBUTES_APPLICATION_PACKAGE); p.end(debugToken); final long defaultToken = p.start(GlobalSettingsProto.DEFAULT); diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 194332ab8451..04fc2588134e 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -2595,8 +2595,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final int mode; if ((supportedModes & FLAG_SMART_SUGGESTION_SYSTEM) != 0) { mode = FLAG_SMART_SUGGESTION_SYSTEM; - } else if ((supportedModes & AutofillManager.FLAG_SMART_SUGGESTION_LEGACY) != 0) { - mode = AutofillManager.FLAG_SMART_SUGGESTION_LEGACY; } else { Slog.w(TAG, "Unsupported Smart Suggestion mode: " + supportedModes); return null; diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 360d2960f61a..01946247bd12 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -56,6 +56,8 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class); sGlobalSettingToTypeMap.put( + Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, String.class); + sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, String.class); sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class); diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java index 2f277e4f2ff5..31b497d001eb 100644 --- a/services/core/java/com/android/server/display/ColorFade.java +++ b/services/core/java/com/android/server/display/ColorFade.java @@ -636,7 +636,7 @@ final class ColorFade { mSurfaceLayout = null; SurfaceControl.openTransaction(); try { - mSurfaceControl.destroy(); + mSurfaceControl.remove(); mSurface.release(); } finally { SurfaceControl.closeTransaction(); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 32dc98837854..eaedec597359 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -195,7 +195,6 @@ import android.content.pm.SharedLibraryInfo; import android.content.pm.Signature; import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; -import android.content.pm.UsesPermissionInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; import android.content.pm.VersionedPackage; @@ -11313,26 +11312,6 @@ public class PackageManagerService extends IPackageManager.Stub } } } - - // Check permission usage info requirements. - if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) { - for (UsesPermissionInfo upi : pkg.usesPermissionInfos) { - if (!mPermissionManager.isPermissionUsageInfoRequired(upi.getPermission())) { - continue; - } - if (upi.getDataSentOffDevice() == UsesPermissionInfo.USAGE_UNDEFINED - || upi.getDataSharedWithThirdParty() - == UsesPermissionInfo.USAGE_UNDEFINED - || upi.getDataUsedForMonetization() - == UsesPermissionInfo.USAGE_UNDEFINED - || upi.getDataRetention() == UsesPermissionInfo.RETENTION_UNDEFINED) { - // STOPSHIP: Make this throw - Slog.e(TAG, "Package " + pkg.packageName + " does not provide usage " - + "information for permission " + upi.getPermission() - + ". This will be a fatal error in Q."); - } - } - } } } diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 173d9a0551df..1957eb89fd0c 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -105,8 +105,6 @@ public final class BasePermission { */ private boolean perUser; - boolean usageInfoRequired; - public BasePermission(String _name, String _sourcePackageName, @PermissionType int _type) { name = _name; sourcePackageName = _sourcePackageName; @@ -375,7 +373,6 @@ public final class BasePermission { } if (bp.perm == p) { bp.protectionLevel = p.info.protectionLevel; - bp.usageInfoRequired = p.info.usageInfoRequired; } if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) { Log.d(TAG, " Permissions: " + r); @@ -455,7 +452,6 @@ public final class BasePermission { permissionInfo.packageName = sourcePackageName; permissionInfo.nonLocalizedLabel = name; permissionInfo.protectionLevel = protectionLevel; - permissionInfo.usageInfoRequired = usageInfoRequired; return permissionInfo; } @@ -484,7 +480,6 @@ public final class BasePermission { bp.protectionLevel = readInt(parser, null, "protection", PermissionInfo.PROTECTION_NORMAL); bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel); - bp.usageInfoRequired = readInt(parser, null, "usageInfoRequired", 0) != 0; if (dynamic) { final PermissionInfo pi = new PermissionInfo(); pi.packageName = sourcePackage.intern(); @@ -492,7 +487,6 @@ public final class BasePermission { pi.icon = readInt(parser, null, "icon", 0); pi.nonLocalizedLabel = parser.getAttributeValue(null, "label"); pi.protectionLevel = bp.protectionLevel; - pi.usageInfoRequired = bp.usageInfoRequired; bp.pendingPermissionInfo = pi; } out.put(bp.name, bp); @@ -525,7 +519,6 @@ public final class BasePermission { if (protectionLevel != PermissionInfo.PROTECTION_NORMAL) { serializer.attribute(null, "protection", Integer.toString(protectionLevel)); } - serializer.attribute(null, "usageInfoRequired", usageInfoRequired ? "1" : "0"); if (type == BasePermission.TYPE_DYNAMIC) { final PermissionInfo pi = perm != null ? perm.info : pendingPermissionInfo; if (pi != null) { @@ -562,7 +555,6 @@ public final class BasePermission { if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false; // We'll take care of setting this one. if (!compareStrings(pi1.packageName, pi2.packageName)) return false; - if (pi1.usageInfoRequired != pi2.usageInfoRequired) return false; // These are not currently stored in settings. //if (!compareStrings(pi1.group, pi2.group)) return false; //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false; @@ -610,8 +602,6 @@ public final class BasePermission { pw.print(" enforced="); pw.println(readEnforced); } - pw.print(" usageInfoRequired="); - pw.println(usageInfoRequired); return true; } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java index 189d0f476a8c..f4979746bae3 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java @@ -181,9 +181,4 @@ public abstract class PermissionManagerInternal { /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */ public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName); - - /** - * Returns {@code true} if {@code permName} has {@code usageInfoRequired} set. - */ - public abstract boolean isPermissionUsageInfoRequired(@NonNull String permName); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index a4413f963642..38940d6241a6 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -2737,12 +2737,5 @@ public class PermissionManagerService { return mSettings.getPermissionLocked(permName); } } - @Override - public boolean isPermissionUsageInfoRequired(String permName) { - synchronized (PermissionManagerService.this.mLock) { - BasePermission bp = mSettings.getPermissionLocked(permName); - return bp != null && bp.usageInfoRequired; - } - } } } diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java index 6fcc331bf62f..0e14e46e77de 100644 --- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java +++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java @@ -143,7 +143,7 @@ class AppWindowThumbnail implements Animatable { void destroy() { mSurfaceAnimator.cancelAnimation(); - mSurfaceControl.destroy(); + mSurfaceControl.remove(); } /** diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 3246a8702cd1..2cc85e2076e0 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -2504,7 +2504,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree public void onAnimationLeashDestroyed(Transaction t) { super.onAnimationLeashDestroyed(t); if (mAnimationBoundsLayer != null) { - t.reparent(mAnimationBoundsLayer, null); + t.remove(mAnimationBoundsLayer); mAnimationBoundsLayer = null; } diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java index c90f5bfb7ee0..497e4121f12e 100644 --- a/services/core/java/com/android/server/wm/BlackFrame.java +++ b/services/core/java/com/android/server/wm/BlackFrame.java @@ -153,7 +153,7 @@ public class BlackFrame { if (mBlackSurfaces[i] != null) { if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM, " BLACK " + mBlackSurfaces[i].surface + ": DESTROY"); - mBlackSurfaces[i].surface.destroy(); + mBlackSurfaces[i].surface.remove(); mBlackSurfaces[i] = null; } } diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java index c39060ee1922..1373e1879d14 100644 --- a/services/core/java/com/android/server/wm/Dimmer.java +++ b/services/core/java/com/android/server/wm/Dimmer.java @@ -129,7 +129,7 @@ class Dimmer { final DimAnimatable dimAnimatable = new DimAnimatable(dimLayer); mSurfaceAnimator = new SurfaceAnimator(dimAnimatable, () -> { if (!mDimming) { - dimAnimatable.getPendingTransaction().reparent(mDimLayer, null); + dimAnimatable.getPendingTransaction().remove(mDimLayer); } }, mHost.mWmService); } @@ -300,7 +300,7 @@ class Dimmer { if (!mDimState.mDimming) { if (!mDimState.mAnimateExit) { - t.reparent(mDimState.mDimLayer, null); + t.remove(mDimState.mDimLayer); } else { startDimExit(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 7a8fd49361b6..928b57cf050b 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4418,13 +4418,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo .show(mSplitScreenDividerAnchor); scheduleAnimation(); } else { - mAppAnimationLayer.destroy(); + mAppAnimationLayer.remove(); mAppAnimationLayer = null; - mBoostedAppAnimationLayer.destroy(); + mBoostedAppAnimationLayer.remove(); mBoostedAppAnimationLayer = null; - mHomeAppAnimationLayer.destroy(); + mHomeAppAnimationLayer.remove(); mHomeAppAnimationLayer = null; - mSplitScreenDividerAnchor.destroy(); + mSplitScreenDividerAnchor.remove(); mSplitScreenDividerAnchor = null; } } diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java index 434084cc1f3d..987492024546 100644 --- a/services/core/java/com/android/server/wm/Letterbox.java +++ b/services/core/java/com/android/server/wm/Letterbox.java @@ -107,10 +107,10 @@ public class Letterbox { mOuter.setEmpty(); mInner.setEmpty(); - mTop.destroy(); - mLeft.destroy(); - mBottom.destroy(); - mRight.destroy(); + mTop.remove(); + mLeft.remove(); + mBottom.remove(); + mRight.remove(); } /** Returns whether a call to {@link #applySurfaceChanges} would change the surface. */ @@ -154,9 +154,9 @@ public class Letterbox { mSurface.setColor(new float[]{0, 0, 0}); } - public void destroy() { + public void remove() { if (mSurface != null) { - mSurface.destroy(); + mSurface.remove(); mSurface = null; } } diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 3947bd47b588..84cd8d1632cf 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -626,7 +626,7 @@ class ScreenRotationAnimation { if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM, " FREEZE " + mSurfaceControl + ": DESTROY"); - mSurfaceControl.destroy(); + mSurfaceControl.remove(); mSurfaceControl = null; } if (mCustomBlackFrame != null) { diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index c600e0f4a657..5ea24518370b 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -280,7 +280,7 @@ class SurfaceAnimator { } mService.mAnimationTransferMap.remove(mAnimation); if (mLeash != null && destroyLeash) { - t.reparent(mLeash, null); + t.remove(mLeash); scheduleAnim = true; } mLeash = null; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 53cd5ea8bf16..7b742fd2e0f3 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -1006,7 +1006,7 @@ public class TaskStack extends WindowContainer<Task> implements EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId); if (mAnimationBackgroundSurface != null) { - mAnimationBackgroundSurface.destroy(); + mAnimationBackgroundSurface.remove(); mAnimationBackgroundSurface = null; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index a054148e26b9..76f080b233a8 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -320,7 +320,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } if (mSurfaceControl != null) { - mPendingTransaction.reparent(mSurfaceControl, null); + mPendingTransaction.remove(mSurfaceControl); // Merge to parent transaction to ensure the transactions on this WindowContainer are // applied in native even if WindowContainer is removed. diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index dea3597989be..e796b99f3989 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -161,7 +161,7 @@ class WindowSurfaceController { } try { if (mSurfaceControl != null) { - mSurfaceControl.destroy(); + mSurfaceControl.remove(); } } catch (RuntimeException e) { Slog.w(TAG, "Error destroying surface in: " + this, e); diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index 85909d564a7b..72357ceee099 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -31,7 +31,6 @@ import android.content.pm.ProviderInfo; import android.content.pm.ServiceInfo; import android.content.pm.SharedLibraryInfo; import android.content.pm.Signature; -import android.content.pm.UsesPermissionInfo; import android.os.Bundle; import android.os.Parcel; import android.platform.test.annotations.Presubmit; @@ -466,7 +465,6 @@ public class PackageParserTest { pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo())); pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo())); pkg.requestedPermissions.add("foo7"); - pkg.usesPermissionInfos.add(new UsesPermissionInfo("foo7")); pkg.implicitPermissions.add("foo25"); pkg.protectedBroadcasts = new ArrayList<>(); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java index ea5ab7bf0621..dd5f32d248b7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java @@ -87,8 +87,8 @@ public class AppWindowTokenAnimationTests extends WindowTestsBase { verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture()); callbackCaptor.getValue().onAnimationFinished(mSpec); - verify(mTransaction).reparent(eq(leash), eq(null)); - verify(mTransaction).reparent(eq(animationBoundsLayer), eq(null)); + verify(mTransaction).remove(eq(leash)); + verify(mTransaction).remove(eq(animationBoundsLayer)); assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse(); } @@ -100,8 +100,8 @@ public class AppWindowTokenAnimationTests extends WindowTestsBase { final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer; mToken.mSurfaceAnimator.cancelAnimation(); - verify(mTransaction).reparent(eq(leash), eq(null)); - verify(mTransaction).reparent(eq(animationBoundsLayer), eq(null)); + verify(mTransaction).remove(eq(leash)); + verify(mTransaction).remove(eq(animationBoundsLayer)); assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java index f99cd4b18647..5b32fe68feae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java @@ -166,7 +166,7 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mTransaction).show(getDimLayer()); - verify(dimLayer, never()).destroy(); + verify(dimLayer, never()).remove(); } @Test @@ -212,7 +212,7 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any( SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean()); - verify(mHost.getPendingTransaction()).reparent(dimLayer, null); + verify(mHost.getPendingTransaction()).remove(dimLayer); } @Test @@ -228,7 +228,7 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mTransaction).show(dimLayer); - verify(dimLayer, never()).destroy(); + verify(dimLayer, never()).remove(); } @Test @@ -269,7 +269,7 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mSurfaceAnimatorStarter, never()).startAnimation(any(SurfaceAnimator.class), any( SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean()); - verify(mTransaction).reparent(dimLayer, null); + verify(mTransaction).remove(dimLayer); } private SurfaceControl getDimLayer() { diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java index edb395a17abb..8c32e8cea93c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java @@ -96,7 +96,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { callbackCaptor.getValue().onAnimationFinished(mSpec); assertNotAnimating(mAnimatable); assertTrue(mAnimatable.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(mAnimatable.mLeash), eq(null)); + verify(mTransaction).remove(eq(mAnimatable.mLeash)); // TODO: Verify reparenting once we use mPendingTransaction to reparent it back } @@ -106,7 +106,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { final SurfaceControl firstLeash = mAnimatable.mLeash; mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec2, true /* hidden */); - verify(mTransaction).reparent(eq(firstLeash), eq(null)); + verify(mTransaction).remove(eq(firstLeash)); assertFalse(mAnimatable.mFinishedCallbackCalled); final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( @@ -133,7 +133,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { assertNotAnimating(mAnimatable); verify(mSpec).onAnimationCancelled(any()); assertTrue(mAnimatable.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(mAnimatable.mLeash), eq(null)); + verify(mTransaction).remove(eq(mAnimatable.mLeash)); } @Test @@ -155,7 +155,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { verifyZeroInteractions(mSpec); assertNotAnimating(mAnimatable); assertTrue(mAnimatable.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(mAnimatable.mLeash), eq(null)); + verify(mTransaction).remove(eq(mAnimatable.mLeash)); } @Test @@ -171,11 +171,11 @@ public class SurfaceAnimatorTest extends WindowTestsBase { assertNotAnimating(mAnimatable); assertAnimating(mAnimatable2); assertEquals(leash, mAnimatable2.mSurfaceAnimator.mLeash); - verify(mTransaction, never()).reparent(eq(leash), eq(null)); + verify(mTransaction, never()).remove(eq(leash)); callbackCaptor.getValue().onAnimationFinished(mSpec); assertNotAnimating(mAnimatable2); assertTrue(mAnimatable2.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(leash), eq(null)); + verify(mTransaction).remove(eq(leash)); } @Test @@ -197,7 +197,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { mDeferFinishAnimatable.mEndDeferFinishCallback.run(); assertNotAnimating(mAnimatable2); assertTrue(mDeferFinishAnimatable.mFinishedCallbackCalled); - verify(mTransaction).reparent(eq(mDeferFinishAnimatable.mLeash), eq(null)); + verify(mTransaction).remove(eq(mDeferFinishAnimatable.mLeash)); } private void assertAnimating(MyAnimatable animatable) { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index be47153bf0ad..8876214b9636 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90; import static android.view.InsetsState.TYPE_TOP_BAR; import static android.view.Surface.ROTATION_0; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; @@ -61,13 +62,15 @@ import android.util.Size; import android.view.DisplayCutout; import android.view.InsetsSource; import android.view.SurfaceControl; +import android.view.ViewRootImpl; import android.view.WindowManager; -import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.server.wm.utils.WmDisplayCutout; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import java.util.LinkedList; @@ -78,10 +81,23 @@ import java.util.LinkedList; * Build/Install/Run: * atest FrameworksServicesTests:WindowStateTests */ -@FlakyTest(bugId = 74078662) @SmallTest @Presubmit public class WindowStateTests extends WindowTestsBase { + private static int sPreviousNewInsetsMode; + + @BeforeClass + public static void setUpOnce() { + sPreviousNewInsetsMode = ViewRootImpl.sNewInsetsMode; + // To let the insets provider control the insets visibility, the insets mode has to be + // NEW_INSETS_MODE_FULL. + ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL; + } + + @AfterClass + public static void tearDownOnce() { + ViewRootImpl.sNewInsetsMode = sPreviousNewInsetsMode; + } @Test public void testIsParentWindowHidden() { diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp index 257043b30704..a8d970edaa85 100644 --- a/tools/stats_log_api_gen/Collation.cpp +++ b/tools/stats_log_api_gen/Collation.cpp @@ -48,6 +48,7 @@ AtomDecl::AtomDecl(const AtomDecl& that) primaryFields(that.primaryFields), exclusiveField(that.exclusiveField), uidField(that.uidField), + whitelisted(that.whitelisted), binaryFields(that.binaryFields) {} AtomDecl::AtomDecl(int c, const string& n, const string& m) @@ -162,6 +163,7 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> *signature) { int errorCount = 0; + // Build a sorted list of the fields. Descriptor has them in source file // order. map<int, const FieldDescriptor *> fields; @@ -387,6 +389,11 @@ int collate_atoms(const Descriptor *descriptor, Atoms *atoms) { const Descriptor *atom = atomField->message_type(); AtomDecl atomDecl(atomField->number(), atomField->name(), atom->name()); + + if (atomField->options().GetExtension(os::statsd::allow_from_any_uid) == true) { + atomDecl.whitelisted = true; + } + vector<java_type_t> signature; errorCount += collate_atom(atom, &atomDecl, &signature); if (atomDecl.primaryFields.size() != 0 && atomDecl.exclusiveField == 0) { diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h index 450b30547c21..6b86b862dfad 100644 --- a/tools/stats_log_api_gen/Collation.h +++ b/tools/stats_log_api_gen/Collation.h @@ -89,6 +89,8 @@ struct AtomDecl { int uidField = 0; + bool whitelisted = false; + vector<int> binaryFields; AtomDecl(); diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp index 4491a8567441..55440d2261d3 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -158,6 +158,20 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, } } } + + fprintf(out, "};\n"); + fprintf(out, "\n"); + + fprintf(out, + "const std::set<int> AtomsInfo::kWhitelistedAtoms = {\n"); + for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); + atom != atoms.decls.end(); atom++) { + if (atom->whitelisted) { + string constant = make_constant_name(atom->name); + fprintf(out, " %s,\n", constant.c_str()); + } + } + fprintf(out, "};\n"); fprintf(out, "\n"); @@ -728,6 +742,8 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio fprintf(out, " const static std::map<int, std::vector<int>> " "kBytesFieldAtoms;"); + fprintf(out, + " const static std::set<int> kWhitelistedAtoms;\n"); fprintf(out, "};\n"); fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n", diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto index 3be87d95df15..24ebf4de031a 100644 --- a/tools/stats_log_api_gen/test.proto +++ b/tools/stats_log_api_gen/test.proto @@ -195,4 +195,22 @@ message GoodStateAtom3 { [(android.os.statsd.state_field_option).option = PRIMARY]; optional int32 state = 3 [(android.os.statsd.state_field_option).option = EXCLUSIVE]; +} + +message WhitelistedAtom { + optional int32 field = 1; +} + +message NonWhitelistedAtom { + optional int32 field = 1; +} + +message ListedAtoms { + oneof event { + // Atoms can be whitelisted i.e. they can be triggered by any source + WhitelistedAtom whitelisted_atom = 1 [(android.os.statsd.allow_from_any_uid) = true]; + // Atoms are not whitelisted by default, so they can only be triggered + // by whitelisted sources + NonWhitelistedAtom non_whitelisted_atom = 2; + } }
\ No newline at end of file diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp index ad3bffacd442..dc585c1c5dd1 100644 --- a/tools/stats_log_api_gen/test_collation.cpp +++ b/tools/stats_log_api_gen/test_collation.cpp @@ -226,5 +226,25 @@ TEST(CollationTest, FailOnBadBinaryFieldAtom) { EXPECT_TRUE(errorCount > 0); } +TEST(CollationTest, PassOnWhitelistedAtom) { + Atoms atoms; + int errorCount = + collate_atoms(ListedAtoms::descriptor(), &atoms); + EXPECT_EQ(errorCount, 0); + EXPECT_EQ(atoms.decls.size(), 2ul); +} + +TEST(CollationTest, RecogniseWhitelistedAtom) { + Atoms atoms; + collate_atoms(ListedAtoms::descriptor(), &atoms); + for (const auto& atomDecl : atoms.decls) { + if (atomDecl.code == 1) { + EXPECT_TRUE(atomDecl.whitelisted); + } else { + EXPECT_FALSE(atomDecl.whitelisted); + } + } +} + } // namespace stats_log_api_gen } // namespace android
\ No newline at end of file |