diff options
205 files changed, 3134 insertions, 1904 deletions
diff --git a/api/current.txt b/api/current.txt index 675223362197..1e6bf2c91711 100644 --- a/api/current.txt +++ b/api/current.txt @@ -14100,8 +14100,9 @@ package android.graphics { } public class ComposeShader extends android.graphics.Shader { - ctor public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.Xfermode); - ctor public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.PorterDuff.Mode); + ctor @Deprecated public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.Xfermode); + ctor @Deprecated public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.PorterDuff.Mode); + ctor public ComposeShader(@NonNull android.graphics.Shader, @NonNull android.graphics.Shader, @NonNull android.graphics.BlendMode); } public class CornerPathEffect extends android.graphics.PathEffect { @@ -14795,37 +14796,37 @@ package android.graphics { field public float y; } - public class PorterDuff { - ctor public PorterDuff(); + @Deprecated public class PorterDuff { + ctor @Deprecated public PorterDuff(); } - public enum PorterDuff.Mode { - enum_constant public static final android.graphics.PorterDuff.Mode ADD; - enum_constant public static final android.graphics.PorterDuff.Mode CLEAR; - enum_constant public static final android.graphics.PorterDuff.Mode DARKEN; - enum_constant public static final android.graphics.PorterDuff.Mode DST; - enum_constant public static final android.graphics.PorterDuff.Mode DST_ATOP; - enum_constant public static final android.graphics.PorterDuff.Mode DST_IN; - enum_constant public static final android.graphics.PorterDuff.Mode DST_OUT; - enum_constant public static final android.graphics.PorterDuff.Mode DST_OVER; - enum_constant public static final android.graphics.PorterDuff.Mode LIGHTEN; - enum_constant public static final android.graphics.PorterDuff.Mode MULTIPLY; - enum_constant public static final android.graphics.PorterDuff.Mode OVERLAY; - enum_constant public static final android.graphics.PorterDuff.Mode SCREEN; - enum_constant public static final android.graphics.PorterDuff.Mode SRC; - enum_constant public static final android.graphics.PorterDuff.Mode SRC_ATOP; - enum_constant public static final android.graphics.PorterDuff.Mode SRC_IN; - enum_constant public static final android.graphics.PorterDuff.Mode SRC_OUT; - enum_constant public static final android.graphics.PorterDuff.Mode SRC_OVER; - enum_constant public static final android.graphics.PorterDuff.Mode XOR; + @Deprecated public enum PorterDuff.Mode { + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode ADD; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode CLEAR; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DARKEN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST_ATOP; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST_IN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST_OUT; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode DST_OVER; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode LIGHTEN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode MULTIPLY; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode OVERLAY; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SCREEN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC_ATOP; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC_IN; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC_OUT; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode SRC_OVER; + enum_constant @Deprecated public static final android.graphics.PorterDuff.Mode XOR; } @Deprecated public class PorterDuffColorFilter extends android.graphics.ColorFilter { ctor @Deprecated public PorterDuffColorFilter(@ColorInt int, @NonNull android.graphics.PorterDuff.Mode); } - public class PorterDuffXfermode extends android.graphics.Xfermode { - ctor public PorterDuffXfermode(android.graphics.PorterDuff.Mode); + @Deprecated public class PorterDuffXfermode extends android.graphics.Xfermode { + ctor @Deprecated public PorterDuffXfermode(android.graphics.PorterDuff.Mode); } public interface PostProcessor { @@ -15387,7 +15388,8 @@ package android.graphics.drawable { method public boolean setState(@NonNull int[]); method public void setTint(@ColorInt int); method public void setTintList(@Nullable android.content.res.ColorStateList); - method public void setTintMode(@NonNull android.graphics.PorterDuff.Mode); + method @Deprecated public void setTintMode(@NonNull android.graphics.PorterDuff.Mode); + method public void setTintMode(@NonNull android.graphics.BlendMode); method public boolean setVisible(boolean, boolean); method public void unscheduleSelf(@NonNull Runnable); } @@ -15545,7 +15547,8 @@ package android.graphics.drawable { method public void loadDrawableAsync(android.content.Context, android.graphics.drawable.Icon.OnDrawableLoadedListener, android.os.Handler); method public android.graphics.drawable.Icon setTint(@ColorInt int); method public android.graphics.drawable.Icon setTintList(android.content.res.ColorStateList); - method public android.graphics.drawable.Icon setTintMode(android.graphics.PorterDuff.Mode); + method @Deprecated @NonNull public android.graphics.drawable.Icon setTintMode(@NonNull android.graphics.PorterDuff.Mode); + method @NonNull public android.graphics.drawable.Icon setTintMode(@NonNull android.graphics.BlendMode); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.graphics.drawable.Icon> CREATOR; field public static final int TYPE_ADAPTIVE_BITMAP = 5; // 0x5 @@ -23041,6 +23044,9 @@ package android.media { method public int getUsage(); method public int getVolumeControlStream(); method public void writeToParcel(android.os.Parcel, int); + field public static final int ALLOW_CAPTURE_BY_ALL = 1; // 0x1 + field public static final int ALLOW_CAPTURE_BY_NONE = 3; // 0x3 + field public static final int ALLOW_CAPTURE_BY_SYSTEM = 2; // 0x2 field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3 field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2 field public static final int CONTENT_TYPE_SONIFICATION = 4; // 0x4 @@ -23072,7 +23078,7 @@ package android.media { ctor public AudioAttributes.Builder(); ctor public AudioAttributes.Builder(android.media.AudioAttributes); method public android.media.AudioAttributes build(); - method @NonNull public android.media.AudioAttributes.Builder setAllowCapture(boolean); + method @NonNull public android.media.AudioAttributes.Builder setAllowedCapturePolicy(int); method public android.media.AudioAttributes.Builder setContentType(int); method public android.media.AudioAttributes.Builder setFlags(int); method public android.media.AudioAttributes.Builder setLegacyStreamType(int); @@ -25069,7 +25075,7 @@ package android.media { field public static final String KEY_LANGUAGE = "language"; field public static final String KEY_LATENCY = "latency"; field public static final String KEY_LEVEL = "level"; - field public static final String KEY_MAX_BFRAMES = "max-bframes"; + field public static final String KEY_MAX_B_FRAMES = "max-bframes"; field public static final String KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder"; field public static final String KEY_MAX_HEIGHT = "max-height"; field public static final String KEY_MAX_INPUT_SIZE = "max-input-size"; @@ -38851,6 +38857,7 @@ package android.provider { field public static final String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS"; field public static final String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS"; field public static final String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS"; + field public static final String ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS = "android.settings.APP_NOTIFICATION_BUBBLE_SETTINGS"; field public static final String ACTION_APP_NOTIFICATION_SETTINGS = "android.settings.APP_NOTIFICATION_SETTINGS"; field public static final String ACTION_APP_SEARCH_SETTINGS = "android.settings.APP_SEARCH_SETTINGS"; field public static final String ACTION_APP_USAGE_SETTINGS = "android.settings.action.APP_USAGE_SETTINGS"; @@ -49718,8 +49725,9 @@ package android.view { method public default CharSequence getContentDescription(); method public int getGroupId(); method public android.graphics.drawable.Drawable getIcon(); + method @Nullable public default android.graphics.BlendMode getIconTintBlendMode(); method @Nullable public default android.content.res.ColorStateList getIconTintList(); - method @Nullable public default android.graphics.PorterDuff.Mode getIconTintMode(); + method @Deprecated @Nullable public default android.graphics.PorterDuff.Mode getIconTintMode(); method public android.content.Intent getIntent(); method public int getItemId(); method public android.view.ContextMenu.ContextMenuInfo getMenuInfo(); @@ -49748,7 +49756,8 @@ package android.view { method public android.view.MenuItem setIcon(android.graphics.drawable.Drawable); method public android.view.MenuItem setIcon(@DrawableRes int); method public default android.view.MenuItem setIconTintList(@Nullable android.content.res.ColorStateList); - method public default android.view.MenuItem setIconTintMode(@Nullable android.graphics.PorterDuff.Mode); + method @Deprecated @NonNull public default android.view.MenuItem setIconTintMode(@Nullable android.graphics.PorterDuff.Mode); + method @NonNull public default android.view.MenuItem setIconTintMode(@Nullable android.graphics.BlendMode); method public android.view.MenuItem setIntent(android.content.Intent); method public android.view.MenuItem setNumericShortcut(char); method public default android.view.MenuItem setNumericShortcut(char, int); @@ -50401,8 +50410,9 @@ package android.view { method public int getAutofillType(); method @Nullable public android.view.autofill.AutofillValue getAutofillValue(); method public android.graphics.drawable.Drawable getBackground(); + method @Nullable public android.graphics.BlendMode getBackgroundBlendMode(); method @Nullable public android.content.res.ColorStateList getBackgroundTintList(); - method @Nullable public android.graphics.PorterDuff.Mode getBackgroundTintMode(); + method @Deprecated @Nullable public android.graphics.PorterDuff.Mode getBackgroundTintMode(); method @android.view.ViewDebug.ExportedProperty(category="layout") public int getBaseline(); method @android.view.ViewDebug.CapturedViewProperty public final int getBottom(); method protected float getBottomFadingEdgeStrength(); @@ -50433,9 +50443,10 @@ package android.view { method public java.util.ArrayList<android.view.View> getFocusables(int); method public void getFocusedRect(android.graphics.Rect); method public android.graphics.drawable.Drawable getForeground(); + method @Nullable public android.graphics.BlendMode getForegroundBlendMode(); method public int getForegroundGravity(); method @Nullable public android.content.res.ColorStateList getForegroundTintList(); - method @Nullable public android.graphics.PorterDuff.Mode getForegroundTintMode(); + method @Deprecated @Nullable public android.graphics.PorterDuff.Mode getForegroundTintMode(); method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point); method public final boolean getGlobalVisibleRect(android.graphics.Rect); method public android.os.Handler getHandler(); @@ -50751,7 +50762,8 @@ package android.view { method @Deprecated public void setBackgroundDrawable(android.graphics.drawable.Drawable); method public void setBackgroundResource(@DrawableRes int); method public void setBackgroundTintList(@Nullable android.content.res.ColorStateList); - method public void setBackgroundTintMode(@Nullable android.graphics.PorterDuff.Mode); + method @Deprecated public void setBackgroundTintMode(@Nullable android.graphics.PorterDuff.Mode); + method public void setBackgroundTintMode(@Nullable android.graphics.BlendMode); method public final void setBottom(int); method public void setCameraDistance(float); method public void setClickable(boolean); @@ -50778,7 +50790,8 @@ package android.view { method public void setForeground(android.graphics.drawable.Drawable); method public void setForegroundGravity(int); method public void setForegroundTintList(@Nullable android.content.res.ColorStateList); - method public void setForegroundTintMode(@Nullable android.graphics.PorterDuff.Mode); + method @Deprecated public void setForegroundTintMode(@Nullable android.graphics.PorterDuff.Mode); + method public void setForegroundTintMode(@Nullable android.graphics.BlendMode); method public void setHapticFeedbackEnabled(boolean); method public void setHasTransientState(boolean); method public void setHorizontalFadingEdgeEnabled(boolean); diff --git a/api/system-current.txt b/api/system-current.txt index d2c5844db0b7..48b1385a872f 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -49,6 +49,7 @@ package android { field @Deprecated public static final String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED"; field public static final String CAMERA_DISABLE_TRANSMIT_LED = "android.permission.CAMERA_DISABLE_TRANSMIT_LED"; field public static final String CAPTURE_AUDIO_HOTWORD = "android.permission.CAPTURE_AUDIO_HOTWORD"; + field public static final String CAPTURE_MEDIA_OUTPUT = "android.permission.CAPTURE_MEDIA_OUTPUT"; field public static final String CAPTURE_TV_INPUT = "android.permission.CAPTURE_TV_INPUT"; field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE"; field public static final String CHANGE_DEVICE_IDLE_TEMP_WHITELIST = "android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"; @@ -564,7 +565,7 @@ package android.app { method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException; method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException; method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long); - method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException; + method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException; method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException; method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent); method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent); @@ -3377,19 +3378,19 @@ package android.location { public class LocationManager { method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch(); + method @Nullable public String getExtraLocationControllerPackage(); method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize(); method @Nullable public android.location.GnssCapabilities getGnssCapabilities(); - method @Nullable public String getLocationControllerExtraPackage(); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections); - method public boolean isLocationControllerExtraPackageEnabled(); + method public boolean isExtraLocationControllerPackageEnabled(); method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle); method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle); method public boolean isProviderPackage(@NonNull String); method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(@NonNull String); - method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String); + method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle); method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle); method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback); @@ -3602,6 +3603,7 @@ package android.media.audiopolicy { ctor public AudioMixingRule.Builder(); method public android.media.audiopolicy.AudioMixingRule.Builder addMixRule(int, Object) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMixingRule.Builder addRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException; + method @NonNull public android.media.audiopolicy.AudioMixingRule.Builder allowPrivilegedPlaybackCapture(boolean); method public android.media.audiopolicy.AudioMixingRule build(); method public android.media.audiopolicy.AudioMixingRule.Builder excludeMixRule(int, Object) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMixingRule.Builder excludeRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException; diff --git a/api/system-removed.txt b/api/system-removed.txt index 9780d43624fa..162f212a787e 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -67,6 +67,8 @@ package android.location { method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener); method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); + method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(String); + method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean); } } diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp index 8ac11df5e5ad..8f9a5f848668 100644 --- a/cmds/incidentd/Android.bp +++ b/cmds/incidentd/Android.bp @@ -66,6 +66,13 @@ cc_binary { "libplatformprotos", ], + product_variables: { + debuggable: { + cflags: ["-DALLOW_RESTRICTED_SECTIONS=1"], + }, + }, + + init_rc: ["incidentd.rc"], } diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp index 7a08dd654d9e..e773e74bbf15 100644 --- a/cmds/incidentd/src/Reporter.cpp +++ b/cmds/incidentd/src/Reporter.cpp @@ -26,7 +26,6 @@ #include "section_list.h" #include <android-base/file.h> -#include <android-base/properties.h> #include <android/os/DropBoxManager.h> #include <android/util/protobuf.h> #include <android/util/ProtoOutputStream.h> @@ -467,8 +466,6 @@ void Reporter::runReport(size_t* reportByteSize) { IncidentMetadata metadata; int persistedPrivacyPolicy = PRIVACY_POLICY_UNSET; - std::string buildType = android::base::GetProperty("ro.build.type", ""); - const bool isUserdebugOrEng = buildType == "userdebug" || buildType == "eng"; (*reportByteSize) = 0; @@ -567,13 +564,6 @@ void Reporter::runReport(size_t* reportByteSize) { for (const Section** section = SECTION_LIST; *section; section++) { const int sectionId = (*section)->id; - // If this section is too private for user builds, skip it. - if ((*section)->userdebugAndEngOnly && !isUserdebugOrEng) { - VLOG("Skipping incident report section %d '%s' because it's limited to userdebug/eng", - sectionId, (*section)->name.string()); - continue; - } - // If nobody wants this section, skip it. if (!mBatch->containsSection(sectionId)) { continue; diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp index 1e8261ee1832..935a7c43fe90 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -25,6 +25,7 @@ #include <set> #include <android-base/file.h> +#include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android/util/protobuf.h> #include <android/util/ProtoOutputStream.h> @@ -63,10 +64,10 @@ static pid_t fork_execute_incident_helper(const int id, Fpipe* p2cPipe, Fpipe* c } // ================================================================================ -Section::Section(int i, int64_t timeoutMs, bool userdebugAndEngOnly) +Section::Section(int i, int64_t timeoutMs) : id(i), - timeoutMs(timeoutMs), - userdebugAndEngOnly(userdebugAndEngOnly) {} + timeoutMs(timeoutMs) { +} Section::~Section() {} @@ -74,7 +75,7 @@ Section::~Section() {} static inline bool isSysfs(const char* filename) { return strncmp(filename, "/sys/", 5) == 0; } FileSection::FileSection(int id, const char* filename, const int64_t timeoutMs) - : Section(id, timeoutMs, false), mFilename(filename) { + : Section(id, timeoutMs), mFilename(filename) { name = "file "; name += filename; mIsSysfs = isSysfs(filename); @@ -236,8 +237,8 @@ WorkerThreadData::WorkerThreadData(const WorkerThreadSection* sec) WorkerThreadData::~WorkerThreadData() {} // ================================================================================ -WorkerThreadSection::WorkerThreadSection(int id, const int64_t timeoutMs, bool userdebugAndEngOnly) - : Section(id, timeoutMs, userdebugAndEngOnly) {} +WorkerThreadSection::WorkerThreadSection(int id, const int64_t timeoutMs) + : Section(id, timeoutMs) {} WorkerThreadSection::~WorkerThreadSection() {} @@ -425,8 +426,8 @@ status_t CommandSection::Execute(ReportWriter* writer) const { } // ================================================================================ -DumpsysSection::DumpsysSection(int id, bool userdebugAndEngOnly, const char* service, ...) - : WorkerThreadSection(id, REMOTE_CALL_TIMEOUT_MS, userdebugAndEngOnly), mService(service) { +DumpsysSection::DumpsysSection(int id, const char* service, ...) + : WorkerThreadSection(id, REMOTE_CALL_TIMEOUT_MS), mService(service) { name = "dumpsys "; name += service; diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h index f89824c07b87..cfe7e1648ad8 100644 --- a/cmds/incidentd/src/Section.h +++ b/cmds/incidentd/src/Section.h @@ -40,10 +40,9 @@ class Section { public: const int id; const int64_t timeoutMs; // each section must have a timeout - const bool userdebugAndEngOnly; String8 name; - Section(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS, bool userdebugAndEngOnly = false); + Section(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS); virtual ~Section(); virtual status_t Execute(ReportWriter* writer) const = 0; @@ -85,8 +84,7 @@ private: */ class WorkerThreadSection : public Section { public: - WorkerThreadSection(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS, - bool userdebugAndEngOnly = false); + WorkerThreadSection(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS); virtual ~WorkerThreadSection(); virtual status_t Execute(ReportWriter* writer) const; @@ -116,7 +114,7 @@ private: */ class DumpsysSection : public WorkerThreadSection { public: - DumpsysSection(int id, bool userdebugAndEngOnly, const char* service, ...); + DumpsysSection(int id, const char* service, ...); virtual ~DumpsysSection(); virtual status_t BlockingCall(int pipeWriteFd) const; @@ -127,6 +125,21 @@ private: }; /** + * Section that calls dumpsys on a system service. + */ +class SystemPropertyDumpsysSection : public WorkerThreadSection { +public: + SystemPropertyDumpsysSection(int id, const char* service, ...); + virtual ~SystemPropertyDumpsysSection(); + + virtual status_t BlockingCall(int pipeWriteFd) const; + +private: + String16 mService; + Vector<String16> mArgs; +}; + +/** * Section that reads from logd. */ class LogSection : public WorkerThreadSection { diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index ecf36a89a769..5528c33ff158 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -257,7 +257,7 @@ message Atom { } // Pulled events will start at field 10000. - // Next: 10057 + // Next: 10058 oneof pulled { WifiBytesTransfer wifi_bytes_transfer = 10000; WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001; @@ -316,6 +316,7 @@ message Atom { GpuStatsGlobalInfo gpu_stats_global_info = 10054; GpuStatsAppInfo gpu_stats_app_info = 10055; SystemIonHeapSize system_ion_heap_size = 10056; + AppsOnExternalStorageInfo apps_on_external_storage_info = 10057; } // DO NOT USE field numbers above 100,000 in AOSP. @@ -5869,3 +5870,15 @@ message NetworkStackReported { optional int32 eventId = 1; optional android.stats.connectivity.NetworkStackEventData network_stack_event = 2 [(log_mode) = MODE_BYTES]; } + +/** + * Logs the apps that are installed on the external storage. + * Pulled from: + * StatsCompanionService + */ +message AppsOnExternalStorageInfo { + // The type of the external storage. + optional android.stats.storage.ExternalStorageType external_storage_type = 1; + // The name of the package that is installed on the external storage. + optional string package_name = 2; +} diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 2abfc2450a00..13eee5da52cf 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -251,6 +251,9 @@ std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { // GpuStatsAppInfo {android::util::GPU_STATS_APP_INFO, {.puller = new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)}}, + // AppsOnExternalStorageInfo + {android::util::APPS_ON_EXTERNAL_STORAGE_INFO, + {.puller = new StatsCompanionServicePuller(android::util::APPS_ON_EXTERNAL_STORAGE_INFO)}}, }; StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) { diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index 24408fc8fc0b..29100aad81aa 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -60,6 +60,9 @@ const int FIELD_ID_PERIODIC_ALARMS_REGISTERED = 1; const int FIELD_ID_LOG_LOSS_STATS_TIME = 1; const int FIELD_ID_LOG_LOSS_STATS_COUNT = 2; const int FIELD_ID_LOG_LOSS_STATS_ERROR = 3; +const int FIELD_ID_LOG_LOSS_STATS_TAG = 4; +const int FIELD_ID_LOG_LOSS_STATS_UID = 5; +const int FIELD_ID_LOG_LOSS_STATS_PID = 6; const int FIELD_ID_CONFIG_STATS_UID = 1; const int FIELD_ID_CONFIG_STATS_ID = 2; @@ -183,12 +186,13 @@ void StatsdStats::noteConfigReset(const ConfigKey& key) { noteConfigResetInternalLocked(key); } -void StatsdStats::noteLogLost(int32_t wallClockTimeSec, int32_t count, int32_t lastError) { +void StatsdStats::noteLogLost(int32_t wallClockTimeSec, int32_t count, int32_t lastError, + int32_t lastTag, int32_t uid, int32_t pid) { lock_guard<std::mutex> lock(mLock); if (mLogLossStats.size() == kMaxLoggerErrors) { mLogLossStats.pop_front(); } - mLogLossStats.emplace_back(wallClockTimeSec, count, lastError); + mLogLossStats.emplace_back(wallClockTimeSec, count, lastError, lastTag, uid, pid); } void StatsdStats::noteBroadcastSent(const ConfigKey& key) { @@ -716,8 +720,11 @@ void StatsdStats::dumpStats(int out) const { } for (const auto& loss : mLogLossStats) { - dprintf(out, "Log loss: %lld (wall clock sec) - %d (count) %d (last error)\n", - (long long)loss.mWallClockSec, loss.mCount, loss.mLastError); + dprintf(out, + "Log loss: %lld (wall clock sec) - %d (count), %d (last error), %d (last tag), %d " + "(uid), %d (pid)\n", + (long long)loss.mWallClockSec, loss.mCount, loss.mLastError, loss.mLastTag, + loss.mUid, loss.mPid); } } @@ -891,6 +898,9 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) { proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_TIME, error.mWallClockSec); proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_COUNT, error.mCount); proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_ERROR, error.mLastError); + proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_TAG, error.mLastTag); + proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_UID, error.mUid); + proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_PID, error.mPid); proto.end(token); } diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h index 7c2d8462c4e4..434920ebe8c7 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.h +++ b/cmds/statsd/src/guardrail/StatsdStats.h @@ -336,7 +336,8 @@ public: /** * Records statsd skipped an event. */ - void noteLogLost(int32_t wallClockTimeSec, int32_t count, int lastError); + void noteLogLost(int32_t wallClockTimeSec, int32_t count, int32_t lastError, + int32_t lastAtomTag, int32_t uid, int32_t pid); /** * Records that the pull of an atom has failed @@ -503,13 +504,22 @@ private: std::map<int64_t, AtomMetricStats> mAtomMetricStats; struct LogLossStats { - LogLossStats(int32_t sec, int32_t count, int32_t error) - : mWallClockSec(sec), mCount(count), mLastError(error) { + LogLossStats(int32_t sec, int32_t count, int32_t error, int32_t tag, int32_t uid, + int32_t pid) + : mWallClockSec(sec), + mCount(count), + mLastError(error), + mLastTag(tag), + mUid(uid), + mPid(pid) { } int32_t mWallClockSec; int32_t mCount; // error code defined in linux/errno.h int32_t mLastError; + int32_t mLastTag; + int32_t mUid; + int32_t mPid; }; // Timestamps when we detect log loss, and the number of logs lost. diff --git a/cmds/statsd/src/socket/StatsSocketListener.cpp b/cmds/statsd/src/socket/StatsSocketListener.cpp index 6bb8cda07281..aed926d74b26 100755 --- a/cmds/statsd/src/socket/StatsSocketListener.cpp +++ b/cmds/statsd/src/socket/StatsSocketListener.cpp @@ -106,13 +106,21 @@ bool StatsSocketListener::onDataAvailable(SocketClient* cli) { // Note that all normal stats logs are in the format of event_list, so there won't be confusion. // // TODO(b/80538532): In addition to log it in StatsdStats, we should properly reset the config. - if (n == sizeof(android_log_event_int_t)) { - android_log_event_int_t* int_event = reinterpret_cast<android_log_event_int_t*>(ptr); - if (int_event->payload.type == EVENT_TYPE_INT) { - ALOGE("Found dropped events: %d error %d", int_event->payload.data, - int_event->header.tag); - StatsdStats::getInstance().noteLogLost((int32_t)getWallClockSec(), - int_event->payload.data, int_event->header.tag); + if (n == sizeof(android_log_event_long_t)) { + android_log_event_long_t* long_event = reinterpret_cast<android_log_event_long_t*>(ptr); + if (long_event->payload.type == EVENT_TYPE_LONG) { + int64_t composed_long = long_event->payload.data; + + // format: + // |last_tag|dropped_count| + int32_t dropped_count = (int32_t)(0xffffffff & composed_long); + int32_t last_atom_tag = (int32_t)((0xffffffff00000000 & (uint64_t)composed_long) >> 32); + + ALOGE("Found dropped events: %d error %d last atom tag %d from uid %d", dropped_count, + long_event->header.tag, last_atom_tag, cred->uid); + StatsdStats::getInstance().noteLogLost((int32_t)getWallClockSec(), dropped_count, + long_event->header.tag, last_atom_tag, cred->uid, + cred->pid); return true; } } diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index 166e087b69dc..967c352562f7 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -455,6 +455,9 @@ message StatsdStatsReport { optional int32 detected_time_sec = 1; optional int32 count = 2; optional int32 last_error = 3; + optional int32 last_tag = 4; + optional int32 uid = 5; + optional int32 pid = 6; } repeated LogLossStats detected_log_loss = 16; } diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java index 9ef24c6c2aeb..faa30f3a98b8 100644 --- a/core/java/android/app/ApplicationLoaders.java +++ b/core/java/android/app/ApplicationLoaders.java @@ -17,20 +17,27 @@ package android.app; import android.annotation.UnsupportedAppUsage; +import android.content.pm.SharedLibraryInfo; import android.os.Build; import android.os.GraphicsEnvironment; import android.os.Trace; import android.util.ArrayMap; +import android.util.Log; import com.android.internal.os.ClassLoaderFactory; import dalvik.system.PathClassLoader; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** @hide */ public class ApplicationLoaders { + private static final String TAG = "ApplicationLoaders"; + @UnsupportedAppUsage public static ApplicationLoaders getDefault() { return gApplicationLoaders; @@ -54,6 +61,26 @@ public class ApplicationLoaders { libraryPermittedPath, parent, zip, classLoaderName, sharedLibraries); } + /** + * Gets a class loader for a shared library. Additional dependent shared libraries are allowed + * to be specified (sharedLibraries). + * + * Additionally, as an optimization, this will return a pre-created ClassLoader if one has + * been cached by createAndCacheNonBootclasspathSystemClassLoaders. + */ + ClassLoader getSharedLibraryClassLoaderWithSharedLibraries(String zip, int targetSdkVersion, + boolean isBundled, String librarySearchPath, String libraryPermittedPath, + ClassLoader parent, String classLoaderName, List<ClassLoader> sharedLibraries) { + ClassLoader loader = getCachedNonBootclasspathSystemLib(zip, parent, classLoaderName, + sharedLibraries); + if (loader != null) { + return loader; + } + + return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled, + librarySearchPath, libraryPermittedPath, parent, classLoaderName, sharedLibraries); + } + private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled, String librarySearchPath, String libraryPermittedPath, ClassLoader parent, String cacheKey, @@ -95,7 +122,9 @@ public class ApplicationLoaders { classloader, librarySearchPath, libraryPermittedPath); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - mLoaders.put(cacheKey, classloader); + if (cacheKey != null) { + mLoaders.put(cacheKey, classloader); + } return classloader; } @@ -108,6 +137,112 @@ public class ApplicationLoaders { } /** + * Caches system library class loaders which are not on the bootclasspath but are still used + * by many system apps. + * + * All libraries in the closure of libraries to be loaded must be in libs. A library can + * only depend on libraries that come before it in the list. + */ + public void createAndCacheNonBootclasspathSystemClassLoaders(SharedLibraryInfo[] libs) { + if (mSystemLibsCacheMap != null) { + Log.wtf(TAG, "Already cached."); + return; + } + + mSystemLibsCacheMap = new HashMap<String, CachedClassLoader>(); + + for (SharedLibraryInfo lib : libs) { + createAndCacheNonBootclasspathSystemClassLoader(lib); + } + } + + /** + * Caches a single non-bootclasspath class loader. + * + * All of this library's dependencies must have previously been cached. + */ + private void createAndCacheNonBootclasspathSystemClassLoader(SharedLibraryInfo lib) { + String path = lib.getPath(); + List<SharedLibraryInfo> dependencies = lib.getDependencies(); + + // get cached classloaders for dependencies + ArrayList<ClassLoader> sharedLibraries = null; + if (dependencies != null) { + sharedLibraries = new ArrayList<ClassLoader>(dependencies.size()); + for (SharedLibraryInfo dependency : dependencies) { + String dependencyPath = dependency.getPath(); + CachedClassLoader cached = mSystemLibsCacheMap.get(dependencyPath); + + if (cached == null) { + Log.e(TAG, "Failed to find dependency " + dependencyPath + + " of cached library " + path); + return; + } + + sharedLibraries.add(cached.loader); + } + } + + // assume cached libraries work with current sdk since they are built-in + ClassLoader classLoader = getClassLoader(path, Build.VERSION.SDK_INT, true /*isBundled*/, + null /*librarySearchPath*/, null /*libraryPermittedPath*/, null /*parent*/, + null /*cacheKey*/, null /*classLoaderName*/, sharedLibraries /*sharedLibraries*/); + + if (classLoader == null) { + Log.e(TAG, "Failed to cache " + path); + return; + } + + CachedClassLoader cached = new CachedClassLoader(); + cached.loader = classLoader; + cached.sharedLibraries = sharedLibraries; + + Log.d(TAG, "Created zygote-cached class loader: " + path); + mSystemLibsCacheMap.put(path, cached); + } + + private static boolean sharedLibrariesEquals(List<ClassLoader> lhs, List<ClassLoader> rhs) { + if (lhs == null) { + return rhs == null; + } + + return lhs.equals(rhs); + } + + /** + * Returns lib cached with createAndCacheNonBootclasspathSystemClassLoader. This is called by + * the zygote during caching. + * + * If there is an error or the cache is not available, this returns null. + */ + private ClassLoader getCachedNonBootclasspathSystemLib(String zip, ClassLoader parent, + String classLoaderName, List<ClassLoader> sharedLibraries) { + if (mSystemLibsCacheMap == null) { + return null; + } + + // we only cache top-level libs with the default class loader + if (parent != null || classLoaderName != null) { + return null; + } + + CachedClassLoader cached = mSystemLibsCacheMap.get(zip); + if (cached == null) { + return null; + } + + // cached must be built and loaded in the same environment + if (!sharedLibrariesEquals(sharedLibraries, cached.sharedLibraries)) { + Log.w(TAG, "Unexpected environment for cached library: (" + sharedLibraries + "|" + + cached.sharedLibraries + ")"); + return null; + } + + Log.d(TAG, "Returning zygote-cached class loader: " + zip); + return cached.loader; + } + + /** * Creates a classloader for the WebView APK and places it in the cache of loaders maintained * by this class. This is used in the WebView zygote, where its presence in the cache speeds up * startup and enables memory sharing. @@ -151,4 +286,18 @@ public class ApplicationLoaders { private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<>(); private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders(); + + private static class CachedClassLoader { + ClassLoader loader; + + /** + * The shared libraries used when constructing loader for verification. + */ + List<ClassLoader> sharedLibraries; + } + + /** + * This is a map of zip to associated class loader. + */ + private Map<String, CachedClassLoader> mSystemLibsCacheMap = null; } diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 41a992139111..25e35734202e 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -676,7 +676,7 @@ public final class LoadedApk { // Shared libraries get a null parent: this has the side effect of having canonicalized // shared libraries using ApplicationLoaders cache, which is the behavior we want. - return ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(jars, + return ApplicationLoaders.getDefault().getSharedLibraryClassLoaderWithSharedLibraries(jars, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, libraryPermittedPath, /* parent */ null, /* classLoaderName */ null, sharedLibraries); diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java index 7746148d325a..7aca2f209a5d 100644 --- a/core/java/android/app/StatsManager.java +++ b/core/java/android/app/StatsManager.java @@ -18,6 +18,7 @@ package android.app; import static android.Manifest.permission.DUMP; import static android.Manifest.permission.PACKAGE_USAGE_STATS; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; @@ -295,7 +296,7 @@ public final class StatsManager { * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service */ @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public long[] setActiveConfigsChangedOperation(@Nullable PendingIntent pendingIntent) + public @NonNull long[] setActiveConfigsChangedOperation(@Nullable PendingIntent pendingIntent) throws StatsUnavailableException { synchronized (this) { try { diff --git a/core/java/android/app/usage/EventList.java b/core/java/android/app/usage/EventList.java index aaae57e526a0..8c0340585573 100644 --- a/core/java/android/app/usage/EventList.java +++ b/core/java/android/app/usage/EventList.java @@ -103,4 +103,18 @@ public class EventList { } return result; } + + /** + * Merge the {@link UsageEvents.Event events} in the given {@link EventList list} into this + * list while keeping the list sorted based on the event {@link + * UsageEvents.Event#mTimeStamp timestamps}. + * + * @param events The event list to merge + */ + public void merge(EventList events) { + final int size = events.size(); + for (int i = 0; i < size; i++) { + insert(events.get(i)); + } + } } diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index da0899be8cfa..690df1acc7e7 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -333,6 +333,16 @@ public class RequestThreadManager { startPreview(); } + private void disconnectCallbackSurfaces() { + for (Surface s : mCallbackOutputs) { + try { + LegacyCameraDevice.disconnectSurface(s); + } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { + Log.d(TAG, "Surface abandoned, skipping...", e); + } + } + } + private void configureOutputs(Collection<Pair<Surface, Size>> outputs) { if (DEBUG) { String outputsStr = outputs == null ? "null" : (outputs.size() + " surfaces"); @@ -370,14 +380,8 @@ public class RequestThreadManager { mGLThreadManager.waitUntilIdle(); } resetJpegSurfaceFormats(mCallbackOutputs); + disconnectCallbackSurfaces(); - for (Surface s : mCallbackOutputs) { - try { - LegacyCameraDevice.disconnectSurface(s); - } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { - Log.w(TAG, "Surface abandoned, skipping...", e); - } - } mPreviewOutputs.clear(); mCallbackOutputs.clear(); mJpegSurfaceIds.clear(); @@ -972,11 +976,11 @@ public class RequestThreadManager { mGLThreadManager.quit(); mGLThreadManager = null; } + disconnectCallbackSurfaces(); if (mCamera != null) { mCamera.release(); mCamera = null; } - resetJpegSurfaceFormats(mCallbackOutputs); break; case RequestHandlerThread.MSG_POKE_IDLE_HANDLER: // OK: Ignore message. diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index ae93cf019776..4a64128f146b 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1934,6 +1934,8 @@ public class ConnectivityManager { @NonNull Callback callback) { ParcelFileDescriptor dup; try { + // Dup is needed here as the pfd inside the socket is owned by the IpSecService, + // which cannot be obtained by the app process. dup = ParcelFileDescriptor.dup(socket.getFileDescriptor()); } catch (IOException ignored) { // Construct an invalid fd, so that if the user later calls start(), it will fail with @@ -1975,6 +1977,7 @@ public class ConnectivityManager { @NonNull Callback callback) { ParcelFileDescriptor dup; try { + // TODO: Consider remove unnecessary dup. dup = pfd.dup(); } catch (IOException ignored) { // Construct an invalid fd, so that if the user later calls start(), it will fail with diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 8970c625caa7..1be6c4bce36a 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -373,7 +373,8 @@ public final class NfcAdapter { * A callback to be invoked when the system successfully delivers your {@link NdefMessage} * to another device. * @see #setOnNdefPushCompleteCallback - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public interface OnNdefPushCompleteCallback { @@ -398,7 +399,8 @@ public final class NfcAdapter { * content currently visible to the user. Alternatively, you can call {@link * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the * same data. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public interface CreateNdefMessageCallback { @@ -427,7 +429,8 @@ public final class NfcAdapter { /** - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public interface CreateBeamUrisCallback { @@ -981,7 +984,8 @@ public final class NfcAdapter { * @param uris an array of Uri(s) to push over Android Beam * @param activity activity for which the Uri(s) will be pushed * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setBeamPushUris(Uri[] uris, Activity activity) { @@ -1068,7 +1072,8 @@ public final class NfcAdapter { * @param callback callback, or null to disable * @param activity activity for which the Uri(s) will be pushed * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { @@ -1157,7 +1162,8 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setNdefPushMessage(NdefMessage message, Activity activity, @@ -1275,7 +1281,8 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, @@ -1361,7 +1368,8 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, @@ -1577,7 +1585,8 @@ public final class NfcAdapter { * @param activity the current foreground Activity that has registered data to share * @return whether the Beam animation was successfully invoked * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated public boolean invokeBeam(Activity activity) { @@ -1822,7 +1831,8 @@ public final class NfcAdapter { * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS * @return true if NDEF Push feature is enabled * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @deprecated this feature is deprecated. + * @deprecated this feature is deprecated. File sharing can work using other technology like + * Bluetooth. */ @java.lang.Deprecated diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java index b92e71357503..b7cccc66294a 100644 --- a/core/java/android/os/DropBoxManager.java +++ b/core/java/android/os/DropBoxManager.java @@ -69,7 +69,8 @@ public class DropBoxManager { /** * Broadcast Action: This is broadcast when a new entry is added in the dropbox. * You must hold the {@link android.Manifest.permission#READ_LOGS} permission - * in order to receive this broadcast. + * in order to receive this broadcast. This broadcast can be rate limited for low priority + * entries * * <p class="note">This is a protected intent that can only be sent * by the system. diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index f6fcdb0fcc76..56c2f4ce9425 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -135,6 +135,7 @@ import java.util.concurrent.atomic.AtomicInteger; @SystemService(Context.STORAGE_SERVICE) public class StorageManager { private static final String TAG = "StorageManager"; + private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE); /** {@hide} */ public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical"; @@ -1652,13 +1653,11 @@ public class StorageManager { /** * Check that given app holds both permission and appop. - * - * @return {@code null} if the permission and appop are held, otherwise - * returns a string indicating why access was denied. + * @hide */ - private boolean checkPermissionAndAppOp(boolean enforce, int pid, int uid, String packageName, - String permission, int op) { - if (mContext.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) { + public static boolean checkPermissionAndAppOp(Context context, boolean enforce, + int pid, int uid, String packageName, String permission, int op) { + if (context.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) { if (enforce) { throw new SecurityException( "Permission " + permission + " denied for package " + packageName); @@ -1667,7 +1666,7 @@ public class StorageManager { } } - final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); + final AppOpsManager appOps = context.getSystemService(AppOpsManager.class); final int mode = appOps.noteOpNoThrow(op, uid, packageName); switch (mode) { case AppOpsManager.MODE_ALLOWED: @@ -1688,6 +1687,11 @@ public class StorageManager { } } + private boolean checkPermissionAndAppOp(boolean enforce, + int pid, int uid, String packageName, String permission, int op) { + return checkPermissionAndAppOp(mContext, enforce, pid, uid, packageName, permission, op); + } + // Callers must hold both the old and new permissions, so that we can // handle obscure cases like when an app targets Q but was installed on // a device that was originally running on P before being upgraded to Q. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 3beb8841acc8..1cab250b7d91 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1542,6 +1542,18 @@ public final class Settings { = "android.settings.CHANNEL_NOTIFICATION_SETTINGS"; /** + * Activity Action: Show notification bubble settings for a single app. + * See {@link NotificationManager#areBubblesAllowed()}. + * <p> + * Input: {@link #EXTRA_APP_PACKAGE}, the package to display. + * <p> + * Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS + = "android.settings.APP_NOTIFICATION_BUBBLE_SETTINGS"; + + /** * Activity Extra: The package owner of the notification channel settings to display. * <p> * This must be passed as an extra field to the {@link #ACTION_CHANNEL_NOTIFICATION_SETTINGS}. @@ -13477,24 +13489,6 @@ public final class Settings { "hidden_api_blacklist_exemptions"; /** - * Sampling rate for hidden API access event logs with libmetricslogger, as an integer in - * the range 0 to 0x10000 inclusive. - * - * @hide - */ - public static final String HIDDEN_API_ACCESS_LOG_SAMPLING_RATE = - "hidden_api_access_log_sampling_rate"; - - /** - * Sampling rate for hidden API access event logging with statslog, as an integer in the - * range 0 to 0x10000 inclusive. - * - * @hide - */ - public static final String HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE = - "hidden_api_access_statslog_sampling_rate"; - - /** * Hidden API enforcement policy for apps. * * Values correspond to @{@link diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index c35423fb09c6..d32bdad4d0a9 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -87,6 +87,10 @@ public class TileService extends Service { * This intent may also define a {@link Intent#EXTRA_COMPONENT_NAME} value * to indicate the {@link ComponentName} that caused the preferences to be * opened. + * <p> + * To ensure that the activity can only be launched through quick settings + * UI provided by this service, apps can protect it with the + * BIND_QUICK_SETTINGS_TILE permission. */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String ACTION_QS_TILE_PREFERENCES diff --git a/core/java/android/service/wallpaper/IWallpaperService.aidl b/core/java/android/service/wallpaper/IWallpaperService.aidl index 99a81f503a95..56e2486dd626 100644 --- a/core/java/android/service/wallpaper/IWallpaperService.aidl +++ b/core/java/android/service/wallpaper/IWallpaperService.aidl @@ -26,4 +26,5 @@ oneway interface IWallpaperService { void attach(IWallpaperConnection connection, IBinder windowToken, int windowType, boolean isPreview, int reqWidth, int reqHeight, in Rect padding, int displayId); + void detach(); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index e1762dffeef5..d645e3f746d7 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -72,6 +72,7 @@ import com.android.internal.view.BaseSurfaceHolder; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; /** @@ -1309,6 +1310,7 @@ public abstract class WallpaperService extends Service { final int mDisplayId; final DisplayManager mDisplayManager; final Display mDisplay; + private final AtomicBoolean mDetached = new AtomicBoolean(); Engine mEngine; @@ -1399,8 +1401,23 @@ public abstract class WallpaperService extends Service { mCaller.sendMessage(msg); } + public void detach() { + mDetached.set(true); + } + + private void doDetachEngine() { + mActiveEngines.remove(mEngine); + mEngine.detach(); + } + @Override public void executeMessage(Message message) { + if (mDetached.get()) { + if (mActiveEngines.contains(mEngine)) { + doDetachEngine(); + } + return; + } switch (message.what) { case DO_ATTACH: { try { @@ -1416,8 +1433,7 @@ public abstract class WallpaperService extends Service { return; } case DO_DETACH: { - mActiveEngines.remove(mEngine); - mEngine.detach(); + doDetachEngine(); return; } case DO_SET_DESIRED_SIZE: { @@ -1497,6 +1513,7 @@ public abstract class WallpaperService extends Service { */ class IWallpaperServiceWrapper extends IWallpaperService.Stub { private final WallpaperService mTarget; + private IWallpaperEngineWrapper mEngineWrapper; public IWallpaperServiceWrapper(WallpaperService context) { mTarget = context; @@ -1506,9 +1523,14 @@ public abstract class WallpaperService extends Service { public void attach(IWallpaperConnection conn, IBinder windowToken, int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding, int displayId) { - new IWallpaperEngineWrapper(mTarget, conn, windowToken, + mEngineWrapper = new IWallpaperEngineWrapper(mTarget, conn, windowToken, windowType, isPreview, reqWidth, reqHeight, padding, displayId); } + + @Override + public void detach() { + mEngineWrapper.detach(); + } } @Override diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java index a3cd0ba4b823..8b3b10f48a4a 100644 --- a/core/java/android/view/MenuInflater.java +++ b/core/java/android/view/MenuInflater.java @@ -23,7 +23,7 @@ import android.content.ContextWrapper; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.graphics.PorterDuff; +import android.graphics.BlendMode; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; @@ -308,7 +308,7 @@ public class MenuInflater { private CharSequence itemTitleCondensed; private int itemIconResId; private ColorStateList itemIconTintList = null; - private PorterDuff.Mode itemIconTintMode = null; + private BlendMode mItemIconBlendMode = null; private char itemAlphabeticShortcut; private int itemAlphabeticModifiers; private char itemNumericShortcut; @@ -401,12 +401,12 @@ public class MenuInflater { itemTitleCondensed = a.getText(com.android.internal.R.styleable.MenuItem_titleCondensed); itemIconResId = a.getResourceId(com.android.internal.R.styleable.MenuItem_icon, 0); if (a.hasValue(com.android.internal.R.styleable.MenuItem_iconTintMode)) { - itemIconTintMode = Drawable.parseTintMode(a.getInt( + mItemIconBlendMode = Drawable.parseBlendMode(a.getInt( com.android.internal.R.styleable.MenuItem_iconTintMode, -1), - itemIconTintMode); + mItemIconBlendMode); } else { // Reset to null so that it's not carried over to the next item - itemIconTintMode = null; + mItemIconBlendMode = null; } if (a.hasValue(com.android.internal.R.styleable.MenuItem_iconTint)) { itemIconTintList = a.getColorStateList( @@ -487,8 +487,8 @@ public class MenuInflater { item.setShowAsAction(itemShowAsAction); } - if (itemIconTintMode != null) { - item.setIconTintMode(itemIconTintMode); + if (mItemIconBlendMode != null) { + item.setIconTintMode(mItemIconBlendMode); } if (itemIconTintList != null) { diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java index ad160cbf41eb..37853103ce02 100644 --- a/core/java/android/view/MenuItem.java +++ b/core/java/android/view/MenuItem.java @@ -18,11 +18,13 @@ package android.view; import android.annotation.DrawableRes; import android.annotation.LayoutRes; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringRes; import android.app.Activity; import android.content.Intent; import android.content.res.ColorStateList; +import android.graphics.BlendMode; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.view.ContextMenu.ContextMenuInfo; @@ -268,8 +270,33 @@ public interface MenuItem { * @attr ref android.R.styleable#MenuItem_iconTintMode * @see #setIconTintList(ColorStateList) * @see Drawable#setTintMode(PorterDuff.Mode) + * @see Drawable#setTintMode(BlendMode) + * + * @deprecated use {@link #setIconTintMode(BlendMode)} instead */ - public default MenuItem setIconTintMode(@Nullable PorterDuff.Mode tintMode) { return this; } + @Deprecated + default @NonNull MenuItem setIconTintMode(@Nullable PorterDuff.Mode tintMode) { + return this; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setIconTintList(ColorStateList)} to this item's icon. The default mode is + * {@link BlendMode#SRC_IN}. + * + * @param blendMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#MenuItem_iconTintMode + * @see #setIconTintList(ColorStateList) + */ + default @NonNull MenuItem setIconTintMode(@Nullable BlendMode blendMode) { + PorterDuff.Mode mode = BlendMode.blendModeToPorterDuffMode(blendMode); + if (mode != null) { + return setIconTintMode(mode); + } else { + return this; + } + } /** * Returns the blending mode used to apply the tint to this item's icon, if specified. @@ -277,9 +304,31 @@ public interface MenuItem { * @return the blending mode used to apply the tint to this item's icon * @attr ref android.R.styleable#MenuItem_iconTintMode * @see #setIconTintMode(PorterDuff.Mode) + * @see #setIconTintMode(BlendMode) + * + * @deprecated Use {@link #getIconTintBlendMode()} instead */ + @Deprecated @Nullable public default PorterDuff.Mode getIconTintMode() { return null; } + + /** + * Returns the blending mode used to apply the tint to this item's icon, if specified. + * + * @return the blending mode used to apply the tint to this item's icon + * @attr ref android.R.styleable#MenuItem_iconTintMode + * @see #setIconTintMode(BlendMode) + * + */ + @Nullable + default BlendMode getIconTintBlendMode() { + PorterDuff.Mode mode = getIconTintMode(); + if (mode != null) { + return BlendMode.fromValue(mode.nativeInt); + } else { + return null; + } + } /** * Change the Intent associated with this item. By default there is no diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 2357db46771a..c34613ea2828 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -50,6 +50,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Insets; @@ -4506,7 +4507,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, static class TintInfo { ColorStateList mTintList; - PorterDuff.Mode mTintMode; + BlendMode mBlendMode; boolean mHasTintMode; boolean mHasTintList; } @@ -5687,7 +5688,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mBackgroundTint == null) { mBackgroundTint = new TintInfo(); } - mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt( + mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt( R.styleable.View_backgroundTintMode, -1), null); mBackgroundTint.mHasTintMode = true; break; @@ -5707,7 +5708,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, break; case R.styleable.View_foregroundTintMode: if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) { - setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null)); + setForegroundTintMode(Drawable.parseBlendMode(a.getInt(attr, -1), null)); } break; case R.styleable.View_foregroundTint: @@ -23266,7 +23267,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Applies a tint to the background drawable. Does not modify the current tint - * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. + * mode, which is {@link BlendMode#SRC_IN} by default. * <p> * Subsequent calls to {@link #setBackground(Drawable)} will automatically * mutate the drawable and apply the specified tint and tint mode using @@ -23311,12 +23312,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_backgroundTintMode * @see #getBackgroundTintMode() * @see Drawable#setTintMode(PorterDuff.Mode) + * + * @deprecated use @setBackgroundTintMode(BlendMode) instead */ + @Deprecated public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) { + BlendMode mode = null; + if (tintMode != null) { + mode = BlendMode.fromValue(tintMode.nativeInt); + } + + setBackgroundTintMode(mode); + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setBackgroundTintList(ColorStateList)}} to the background + * drawable. The default mode is {@link BlendMode#SRC_IN}. + * + * @param blendMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#View_backgroundTintMode + * @see #getBackgroundTintMode() + * @see Drawable#setTintMode(BlendMode) + */ + public void setBackgroundTintMode(@Nullable BlendMode blendMode) { if (mBackgroundTint == null) { mBackgroundTint = new TintInfo(); } - mBackgroundTint.mTintMode = tintMode; + + mBackgroundTint.mBlendMode = blendMode; mBackgroundTint.mHasTintMode = true; applyBackgroundTint(); @@ -23329,12 +23354,34 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return the blending mode used to apply the tint to the background * drawable * @attr ref android.R.styleable#View_backgroundTintMode - * @see #setBackgroundTintMode(PorterDuff.Mode) + * @see #setBackgroundTintMode(BlendMode) + * + * @deprecated use #getBackgroundBlendMode() instead */ @Nullable @InspectableProperty + @Deprecated public PorterDuff.Mode getBackgroundTintMode() { - return mBackgroundTint != null ? mBackgroundTint.mTintMode : null; + PorterDuff.Mode porterDuffMode; + if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) { + porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode); + } else { + porterDuffMode = null; + } + return porterDuffMode; + } + + /** + * Return the blending mode used to apply the tint to the background + * drawable, if specified. + * + * @return the blending mode used to apply the tint to the background + * drawable, null if no blend has previously been configured + * @attr ref android.R.styleable#View_backgroundTintMode + * @see #setBackgroundTintMode(BlendMode) + */ + public @Nullable BlendMode getBackgroundBlendMode() { + return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null; } private void applyBackgroundTint() { @@ -23348,7 +23395,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (tintInfo.mHasTintMode) { - mBackground.setTintMode(tintInfo.mTintMode); + mBackground.setTintMode(tintInfo.mBlendMode); } // The drawable (or one of its children) may not have been @@ -23532,15 +23579,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @attr ref android.R.styleable#View_foregroundTintMode * @see #getForegroundTintMode() * @see Drawable#setTintMode(PorterDuff.Mode) + * + * @deprecated use #setForegroundTintMode(BlendMode) */ + @Deprecated public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { + BlendMode mode = null; + if (tintMode != null) { + mode = BlendMode.fromValue(tintMode.nativeInt); + } + setForegroundTintMode(mode); + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setForegroundTintList(ColorStateList)}} to the background + * drawable. The default mode is {@link BlendMode#SRC_IN}. + * + * @param blendMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#View_foregroundTintMode + * @see #getForegroundTintMode() + * @see Drawable#setTintMode(BlendMode) + */ + public void setForegroundTintMode(@Nullable BlendMode blendMode) { if (mForegroundInfo == null) { mForegroundInfo = new ForegroundInfo(); } if (mForegroundInfo.mTintInfo == null) { mForegroundInfo.mTintInfo = new TintInfo(); } - mForegroundInfo.mTintInfo.mTintMode = tintMode; + mForegroundInfo.mTintInfo.mBlendMode = blendMode; mForegroundInfo.mTintInfo.mHasTintMode = true; applyForegroundTint(); @@ -23554,12 +23623,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * drawable * @attr ref android.R.styleable#View_foregroundTintMode * @see #setForegroundTintMode(PorterDuff.Mode) + * + * @deprecated use #getForegroundBlendMode() instead */ @InspectableProperty @Nullable + @Deprecated public PorterDuff.Mode getForegroundTintMode() { + BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null + ? mForegroundInfo.mTintInfo.mBlendMode : null; + if (blendMode != null) { + return BlendMode.blendModeToPorterDuffMode(blendMode); + } else { + return null; + } + } + + /** + * Return the blending mode used to apply the tint to the foreground + * drawable, if specified. + * + * @return the blending mode used to apply the tint to the foreground + * drawable + * @attr ref android.R.styleable#View_foregroundTintMode + * @see #setForegroundTintMode(BlendMode) + * + */ + public @Nullable BlendMode getForegroundBlendMode() { return mForegroundInfo != null && mForegroundInfo.mTintInfo != null - ? mForegroundInfo.mTintInfo.mTintMode : null; + ? mForegroundInfo.mTintInfo.mBlendMode : null; } private void applyForegroundTint() { @@ -23574,7 +23666,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (tintInfo.mHasTintMode) { - mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode); + mForegroundInfo.mDrawable.setTintMode(tintInfo.mBlendMode); } // The drawable (or one of its children) may not have been diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 4f5678a5ff24..f29174b54383 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -163,6 +163,8 @@ public class ChooserActivity extends ResolverActivity { */ private static final int NO_DIRECT_SHARE_ANIM_IN_MILLIS = 200; + private static final float DIRECT_SHARE_EXPANSION_RATE = 0.7f; + // TODO(b/121287224): Re-evaluate this limit private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20; @@ -435,9 +437,13 @@ public class ChooserActivity extends ResolverActivity { mChooserRowServiceSpacing = getResources() .getDimensionPixelSize(R.dimen.chooser_service_spacing); - // expand/shrink direct share 4 -> 8 viewgroup - if (mResolverDrawerLayout != null && isSendAction(target)) { - mResolverDrawerLayout.setOnScrollChangeListener(this::handleScroll); + if (mResolverDrawerLayout != null) { + mResolverDrawerLayout.addOnLayoutChangeListener(this::handleLayoutChange); + + // expand/shrink direct share 4 -> 8 viewgroup + if (isSendAction(target)) { + mResolverDrawerLayout.setOnScrollChangeListener(this::handleScroll); + } } if (DEBUG) { @@ -878,18 +884,9 @@ public class ChooserActivity extends ResolverActivity { mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets)); } mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter); - mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView)); if (listView != null) { listView.setItemsCanFocus(true); - listView.addOnLayoutChangeListener( - (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { - if (mChooserRowAdapter.calculateMaxTargetsPerRow(right - left)) { - adapterView.setAdapter(mChooserRowAdapter); - } - }); } - - adapterView.setAdapter(mChooserRowAdapter); } @Override @@ -1728,6 +1725,66 @@ public class ChooserActivity extends ResolverActivity { } } + /* + * Need to dynamically adjust how many icons can fit per row before we add them, + * which also means setting the correct offset to initially show the content + * preview area + 2 rows of targets + */ + private void handleLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, + int oldTop, int oldRight, int oldBottom) { + if (mChooserRowAdapter == null || mAdapterView == null) { + return; + } + + if (mChooserRowAdapter.calculateMaxTargetsPerRow(right - left) + || mAdapterView.getAdapter() == null) { + mAdapterView.setAdapter(mChooserRowAdapter); + + getMainThreadHandler().post(() -> { + if (mResolverDrawerLayout == null || mChooserRowAdapter == null) { + return; + } + + int offset = 0; + int rowsToShow = mChooserRowAdapter.getContentPreviewRowCount() + + mChooserRowAdapter.getServiceTargetRowCount() + + mChooserRowAdapter.getCallerTargetRowCount(); + + // then this is most likely not a SEND_* action, so check + // the app target count + if (rowsToShow == 0) { + rowsToShow = mChooserRowAdapter.getCount(); + } + + // still zero? then use a default height and leave, which + // can happen when there are no targets to show + if (rowsToShow == 0) { + offset = getResources().getDimensionPixelSize( + R.dimen.chooser_max_collapsed_height); + mResolverDrawerLayout.setCollapsibleHeightReserved(offset); + return; + } + + int lastHeight = 0; + rowsToShow = Math.max(3, rowsToShow); + for (int i = 0; i < Math.min(rowsToShow, mAdapterView.getChildCount()); i++) { + lastHeight = mAdapterView.getChildAt(i).getHeight(); + offset += lastHeight; + } + + if (lastHeight != 0 && isSendAction(getTargetIntent())) { + // make sure to leave room for direct share 4->8 expansion + int expansionArea = + (int) (mResolverDrawerLayout.getUncollapsibleHeight() + / DIRECT_SHARE_EXPANSION_RATE); + offset = Math.min(offset, bottom - top - lastHeight - expansionArea); + } + + mResolverDrawerLayout.setCollapsibleHeightReserved(offset); + }); + } + } + public class ChooserListAdapter extends ResolveListAdapter { public static final int TARGET_BAD = -1; public static final int TARGET_CALLER = 0; @@ -2541,7 +2598,6 @@ public class ChooserActivity extends ResolverActivity { getRow(0).measure(spec, spec); getRow(1).measure(spec, spec); - // uses ChooserActiivty state variables to track height mDirectShareMinHeight = getRow(0).getMeasuredHeight(); mDirectShareCurrHeight = mDirectShareCurrHeight > 0 ? mDirectShareCurrHeight : mDirectShareMinHeight; @@ -2574,18 +2630,18 @@ public class ChooserActivity extends ResolverActivity { } public void handleScroll(AbsListView view, int y, int oldy, int maxTargetsPerRow) { - // only expand if we have more than 4 targets, and delay that decision until - // they start to scroll if (mHideDirectShareExpansion) { return; } + // only expand if we have more than maxTargetsPerRow, and delay that decision + // until they start to scroll if (mChooserListAdapter.getSelectableServiceTargetCount() <= maxTargetsPerRow) { mHideDirectShareExpansion = true; return; } - int yDiff = (int) ((oldy - y) * 0.7f); + int yDiff = (int) ((oldy - y) * DIRECT_SHARE_EXPANSION_RATE); int prevHeight = mDirectShareCurrHeight; mDirectShareCurrHeight = Math.min(mDirectShareCurrHeight + yDiff, @@ -2593,27 +2649,31 @@ public class ChooserActivity extends ResolverActivity { mDirectShareCurrHeight = Math.max(mDirectShareCurrHeight, mDirectShareMinHeight); yDiff = mDirectShareCurrHeight - prevHeight; - if (view == null || view.getChildCount() == 0) { + if (view == null || view.getChildCount() == 0 || yDiff == 0) { return; } - int index = mChooserRowAdapter.getContentPreviewRowCount(); + // locate the item to expand, and offset the rows below that one + boolean foundExpansion = false; + for (int i = 0; i < view.getChildCount(); i++) { + View child = view.getChildAt(i); - ViewGroup expansionGroup = (ViewGroup) view.getChildAt(index); - int widthSpec = MeasureSpec.makeMeasureSpec(expansionGroup.getWidth(), - MeasureSpec.EXACTLY); - int heightSpec = MeasureSpec.makeMeasureSpec(mDirectShareCurrHeight, - MeasureSpec.EXACTLY); - expansionGroup.measure(widthSpec, heightSpec); - expansionGroup.getLayoutParams().height = expansionGroup.getMeasuredHeight(); - expansionGroup.layout(expansionGroup.getLeft(), expansionGroup.getTop(), - expansionGroup.getRight(), - expansionGroup.getTop() + expansionGroup.getMeasuredHeight()); - - // reposition list items - int items = view.getChildCount(); - for (int i = index + 1; i < items; i++) { - view.getChildAt(i).offsetTopAndBottom(yDiff); + if (foundExpansion) { + child.offsetTopAndBottom(yDiff); + } else { + if (child.getTag() != null && child.getTag() instanceof DirectShareViewHolder) { + int widthSpec = MeasureSpec.makeMeasureSpec(child.getWidth(), + MeasureSpec.EXACTLY); + int heightSpec = MeasureSpec.makeMeasureSpec(mDirectShareCurrHeight, + MeasureSpec.EXACTLY); + child.measure(widthSpec, heightSpec); + child.getLayoutParams().height = child.getMeasuredHeight(); + child.layout(child.getLeft(), child.getTop(), child.getRight(), + child.getTop() + child.getMeasuredHeight()); + + foundExpansion = true; + } + } } } } @@ -2771,47 +2831,6 @@ public class ChooserActivity extends ResolverActivity { } } - class OffsetDataSetObserver extends DataSetObserver { - private final AbsListView mListView; - private int mCachedViewType = -1; - private View mCachedView; - - public OffsetDataSetObserver(AbsListView listView) { - mListView = listView; - } - - @Override - public void onChanged() { - if (mResolverDrawerLayout == null) { - return; - } - - final int chooserTargetRows = mChooserRowAdapter.getServiceTargetRowCount(); - int offset = 0; - for (int i = 0; i < chooserTargetRows; i++) { - final int pos = mChooserRowAdapter.getContentPreviewRowCount() + i; - final int vt = mChooserRowAdapter.getItemViewType(pos); - if (vt != mCachedViewType) { - mCachedView = null; - } - final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView); - int height = ((RowViewHolder) (v.getTag())).getMeasuredRowHeight(); - - offset += (int) (height); - - if (vt >= 0) { - mCachedViewType = vt; - mCachedView = v; - } else { - mCachedViewType = -1; - } - } - - mResolverDrawerLayout.setCollapsibleHeightReserved(offset); - } - } - - /** * Used internally to round image corners while obeying view padding. */ diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index dd180601d537..7cca7b77b45d 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -22,6 +22,8 @@ import static android.system.OsConstants.S_IRWXO; import android.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.content.res.TypedArray; +import android.app.ApplicationLoaders; +import android.content.pm.SharedLibraryInfo; import android.os.Build; import android.os.Environment; import android.os.IInstalld; @@ -138,6 +140,9 @@ public class ZygoteInit { bootTimingsTraceLog.traceBegin("PreloadClasses"); preloadClasses(); bootTimingsTraceLog.traceEnd(); // PreloadClasses + bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders"); + cacheNonBootClasspathClassLoaders(); + bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders bootTimingsTraceLog.traceBegin("PreloadResources"); preloadResources(); bootTimingsTraceLog.traceEnd(); // PreloadResources @@ -344,6 +349,32 @@ public class ZygoteInit { } /** + * Load in things which are used by many apps but which cannot be put in the boot + * classpath. + */ + private static void cacheNonBootClasspathClassLoaders() { + // These libraries used to be part of the bootclasspath, but had to be removed. + // Old system applications still get them for backwards compatibility reasons, + // so they are cached here in order to preserve performance characteristics. + SharedLibraryInfo hidlBase = new SharedLibraryInfo( + "/system/framework/android.hidl.base-V1.0-java.jar", null /*packageName*/, + null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN, + null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/); + SharedLibraryInfo hidlManager = new SharedLibraryInfo( + "/system/framework/android.hidl.manager-V1.0-java.jar", null /*packageName*/, + null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN, + null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/); + hidlManager.addDependency(hidlBase); + + ApplicationLoaders.getDefault().createAndCacheNonBootclasspathSystemClassLoaders( + new SharedLibraryInfo[]{ + // ordered dependencies first + hidlBase, + hidlManager, + }); + } + + /** * Load in commonly used resources, so they can be shared across processes. * * These tend to be a few Kbytes, but are frequently in the 20-40K range, and occasionally even diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index 9722fcb129f6..a160b57fe2a1 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -868,6 +868,13 @@ public class ResolverDrawerLayout extends ViewGroup { setMeasuredDimension(sourceWidth, heightSize); } + /** + * @return The space reserved by views with 'alwaysShow=true' + */ + public int getUncollapsibleHeight() { + return mUncollapsibleHeight; + } + @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int width = getWidth(); diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index e0b7629013fb..a4e37093def0 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -39,7 +39,6 @@ static jclass gBitmap_class; static jfieldID gBitmap_nativePtr; static jmethodID gBitmap_constructorMethodID; static jmethodID gBitmap_reinitMethodID; -static jmethodID gBitmap_getAllocationByteCountMethodID; namespace android { @@ -193,11 +192,6 @@ void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info, info.width(), info.height(), isPremultiplied); } -int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap) -{ - return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID); -} - jobject createBitmap(JNIEnv* env, Bitmap* bitmap, int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets, int density) { @@ -236,8 +230,7 @@ Bitmap& toBitmap(JNIEnv* env, jobject bitmap) { return localBitmap->bitmap(); } -Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) { - SkASSERT(env); +Bitmap& toBitmap(jlong bitmapHandle) { LocalScopedBitmap localBitmap(bitmapHandle); return localBitmap->bitmap(); } @@ -1227,7 +1220,6 @@ int register_android_graphics_Bitmap(JNIEnv* env) gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J"); gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V"); gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V"); - gBitmap_getAllocationByteCountMethodID = GetMethodIDOrDie(env, gBitmap_class, "getAllocationByteCount", "()I"); return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods, NELEM(gBitmapMethods)); } diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h index 06877915856e..6934d26cdc78 100644 --- a/core/jni/android/graphics/Bitmap.h +++ b/core/jni/android/graphics/Bitmap.h @@ -41,7 +41,7 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap, void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap); Bitmap& toBitmap(JNIEnv* env, jobject bitmap); -Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle); +Bitmap& toBitmap(jlong bitmapHandle); // NDK access void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info); @@ -56,8 +56,6 @@ bool unlockPixels(JNIEnv* env, jobject bitmap); void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info, bool isPremultiplied); -int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap); - } // namespace bitmap } // namespace android diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 47b1548edb67..3f05c3b57c69 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -180,7 +180,8 @@ static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize, } static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, - jobject padding, jobject options, jlong colorSpaceHandle) { + jobject padding, jobject options, jlong inBitmapHandle, + jlong colorSpaceHandle) { // Set default values for the options parameters. int sampleSize = 1; bool onlyDecodeSize = false; @@ -323,14 +324,14 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, android::Bitmap* reuseBitmap = nullptr; unsigned int existingBufferSize = 0; - if (javaBitmap != NULL) { - reuseBitmap = &bitmap::toBitmap(env, javaBitmap); + if (javaBitmap != nullptr) { + reuseBitmap = &bitmap::toBitmap(inBitmapHandle); if (reuseBitmap->isImmutable()) { ALOGW("Unable to reuse an immutable bitmap as an image decoder target."); - javaBitmap = NULL; + javaBitmap = nullptr; reuseBitmap = nullptr; } else { - existingBufferSize = bitmap::getBitmapAllocationByteCount(env, javaBitmap); + existingBufferSize = reuseBitmap->getAllocationByteCount(); } } @@ -513,7 +514,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, } static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage, - jobject padding, jobject options, jlong colorSpaceHandle) { + jobject padding, jobject options, jlong inBitmapHandle, jlong colorSpaceHandle) { jobject bitmap = NULL; std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage)); @@ -522,13 +523,14 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA std::unique_ptr<SkStreamRewindable> bufferedStream( SkFrontBufferedStream::Make(std::move(stream), SkCodec::MinBufferedBytesNeeded())); SkASSERT(bufferedStream.get() != NULL); - bitmap = doDecode(env, std::move(bufferedStream), padding, options, colorSpaceHandle); + bitmap = doDecode(env, std::move(bufferedStream), padding, options, inBitmapHandle, + colorSpaceHandle); } return bitmap; } static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor, - jobject padding, jobject bitmapFactoryOptions, jlong colorSpaceHandle) { + jobject padding, jobject bitmapFactoryOptions, jlong inBitmapHandle, jlong colorSpaceHandle) { NPE_CHECK_RETURN_ZERO(env, fileDescriptor); @@ -565,7 +567,7 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi if (::lseek(descriptor, 0, SEEK_CUR) == 0) { assert(isSeekable(dupDescriptor)); return doDecode(env, std::move(fileStream), padding, bitmapFactoryOptions, - colorSpaceHandle); + inBitmapHandle, colorSpaceHandle); } // Use a buffered stream. Although an SkFILEStream can be rewound, this @@ -574,25 +576,26 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi std::unique_ptr<SkStreamRewindable> stream(SkFrontBufferedStream::Make(std::move(fileStream), SkCodec::MinBufferedBytesNeeded())); - return doDecode(env, std::move(stream), padding, bitmapFactoryOptions, colorSpaceHandle); + return doDecode(env, std::move(stream), padding, bitmapFactoryOptions, inBitmapHandle, + colorSpaceHandle); } static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jlong native_asset, - jobject padding, jobject options, jlong colorSpaceHandle) { + jobject padding, jobject options, jlong inBitmapHandle, jlong colorSpaceHandle) { Asset* asset = reinterpret_cast<Asset*>(native_asset); // since we know we'll be done with the asset when we return, we can // just use a simple wrapper return doDecode(env, skstd::make_unique<AssetStreamAdaptor>(asset), padding, options, - colorSpaceHandle); + inBitmapHandle, colorSpaceHandle); } static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray, - jint offset, jint length, jobject options, jlong colorSpaceHandle) { + jint offset, jint length, jobject options, jlong inBitmapHandle, jlong colorSpaceHandle) { AutoJavaByteArray ar(env, byteArray); return doDecode(env, skstd::make_unique<SkMemoryStream>(ar.ptr() + offset, length, false), - nullptr, options, colorSpaceHandle); + nullptr, options, inBitmapHandle, colorSpaceHandle); } static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) { @@ -604,22 +607,22 @@ static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) { static const JNINativeMethod gMethods[] = { { "nativeDecodeStream", - "(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;", + "(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;", (void*)nativeDecodeStream }, { "nativeDecodeFileDescriptor", - "(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;", + "(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;", (void*)nativeDecodeFileDescriptor }, { "nativeDecodeAsset", - "(JLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;", + "(JLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;", (void*)nativeDecodeAsset }, { "nativeDecodeByteArray", - "([BIILandroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;", + "([BIILandroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;", (void*)nativeDecodeByteArray }, diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp index 9c07e2d64c6e..6ffa72ad8903 100644 --- a/core/jni/android/graphics/BitmapRegionDecoder.cpp +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -125,13 +125,14 @@ static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz, * reportSizeToVM not supported */ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint inputX, - jint inputY, jint inputWidth, jint inputHeight, jobject options, jlong colorSpaceHandle) { + jint inputY, jint inputWidth, jint inputHeight, jobject options, jlong inBitmapHandle, + jlong colorSpaceHandle) { // Set default options. int sampleSize = 1; SkColorType colorType = kN32_SkColorType; bool requireUnpremul = false; - jobject javaBitmap = NULL; + jobject javaBitmap = nullptr; bool isHardware = false; sk_sp<SkColorSpace> colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle); // Update the default options with any options supplied by the client. @@ -158,11 +159,11 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in android::Bitmap* recycledBitmap = nullptr; size_t recycledBytes = 0; if (javaBitmap) { - recycledBitmap = &bitmap::toBitmap(env, javaBitmap); + recycledBitmap = &bitmap::toBitmap(inBitmapHandle); if (recycledBitmap->isImmutable()) { ALOGW("Warning: Reusing an immutable bitmap as an image decoder target."); } - recycledBytes = bitmap::getBitmapAllocationByteCount(env, javaBitmap); + recycledBytes = recycledBitmap->getAllocationByteCount(); } SkBitmapRegionDecoder* brd = reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle); @@ -258,7 +259,7 @@ static void nativeClean(JNIEnv* env, jobject, jlong brdHandle) { static const JNINativeMethod gBitmapRegionDecoderMethods[] = { { "nativeDecodeRegion", - "(JIIIILandroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;", + "(JIIIILandroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;", (void*)nativeDecodeRegion}, { "nativeGetHeight", "(J)I", (void*)nativeGetHeight}, diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp index bb291e74ce0d..15f951688d43 100644 --- a/core/jni/android/graphics/NinePatch.cpp +++ b/core/jni/android/graphics/NinePatch.cpp @@ -84,13 +84,13 @@ public: delete[] patch; } - static jlong getTransparentRegion(JNIEnv* env, jobject, jobject jbitmap, + static jlong getTransparentRegion(JNIEnv* env, jobject, jlong bitmapPtr, jlong chunkHandle, jobject dstRect) { Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle); SkASSERT(chunk); SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); SkRect dst; GraphicsJNI::jrect_to_rect(env, dstRect, &dst); @@ -156,7 +156,7 @@ static const JNINativeMethod gNinePatchMethods[] = { { "validateNinePatchChunk", "([B)J", (void*) SkNinePatchGlue::validateNinePatchChunk }, { "nativeFinalize", "(J)V", (void*) SkNinePatchGlue::finalize }, - { "nativeGetTransparentRegion", "(Landroid/graphics/Bitmap;JLandroid/graphics/Rect;)J", + { "nativeGetTransparentRegion", "(JJLandroid/graphics/Rect;)J", (void*) SkNinePatchGlue::getTransparentRegion } }; diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index 298f7f8f78e5..44d2cac8739d 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -62,14 +62,14 @@ static jlong Shader_getNativeFinalizer(JNIEnv*, jobject) { /////////////////////////////////////////////////////////////////////////////////////////////// -static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jobject jbitmap, +static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle, jint tileModeX, jint tileModeY) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); sk_sp<SkImage> image; - if (jbitmap) { + if (bitmapHandle) { // Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise, // we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility. - image = android::bitmap::toBitmap(env, jbitmap).makeImage(); + image = android::bitmap::toBitmap(bitmapHandle).makeImage(); } if (!image.get()) { @@ -222,7 +222,7 @@ static const JNINativeMethod gShaderMethods[] = { }; static const JNINativeMethod gBitmapShaderMethods[] = { - { "nativeCreate", "(JLandroid/graphics/Bitmap;II)J", (void*)BitmapShader_constructor }, + { "nativeCreate", "(JJII)J", (void*)BitmapShader_constructor }, }; static const JNINativeMethod gLinearGradientMethods[] = { diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp index 32ac30fdabb0..761830b0e97c 100644 --- a/core/jni/android/graphics/pdf/PdfRenderer.cpp +++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp @@ -73,12 +73,12 @@ static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { } static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr, - jobject jbitmap, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom, + jlong bitmapPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom, jlong transformPtr, jint renderMode) { FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); SkBitmap skBitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &skBitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&skBitmap); const int stride = skBitmap.width() * 4; @@ -117,7 +117,7 @@ static const JNINativeMethod gPdfRenderer_Methods[] = { {"nativeClose", "(J)V", (void*) nativeClose}, {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, - {"nativeRenderPage", "(JJLandroid/graphics/Bitmap;IIIIJI)V", (void*) nativeRenderPage}, + {"nativeRenderPage", "(JJJIIIIJI)V", (void*) nativeRenderPage}, {"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize}, {"nativeClosePage", "(J)V", (void*) nativeClosePage} }; diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp index d50e60c1a899..09f0e8e232bf 100644 --- a/core/jni/android/opengl/util.cpp +++ b/core/jni/android/opengl/util.cpp @@ -703,27 +703,27 @@ static int getType(SkColorType colorType) } static jint util_getInternalFormat(JNIEnv *env, jclass clazz, - jobject jbitmap) + jlong bitmapPtr) { SkBitmap nativeBitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &nativeBitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&nativeBitmap); return getInternalFormat(nativeBitmap.colorType()); } static jint util_getType(JNIEnv *env, jclass clazz, - jobject jbitmap) + jlong bitmapPtr) { SkBitmap nativeBitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &nativeBitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&nativeBitmap); return getType(nativeBitmap.colorType()); } static jint util_texImage2D(JNIEnv *env, jclass clazz, jint target, jint level, jint internalformat, - jobject jbitmap, jint type, jint border) + jlong bitmapPtr, jint type, jint border) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); SkColorType colorType = bitmap.colorType(); if (internalformat < 0) { internalformat = getInternalFormat(colorType); @@ -748,10 +748,10 @@ static jint util_texImage2D(JNIEnv *env, jclass clazz, static jint util_texSubImage2D(JNIEnv *env, jclass clazz, jint target, jint level, jint xoffset, jint yoffset, - jobject jbitmap, jint format, jint type) + jlong bitmapPtr, jint format, jint type) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); SkColorType colorType = bitmap.colorType(); int internalFormat = getInternalFormat(colorType); if (format < 0) { @@ -1068,10 +1068,10 @@ static const JNINativeMethod gVisibilityMethods[] = { }; static const JNINativeMethod gUtilsMethods[] = { - { "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat }, - { "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType }, - { "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D }, - { "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D }, + { "native_getInternalFormat", "(J)I", (void*) util_getInternalFormat }, + { "native_getType", "(J)I", (void*) util_getType }, + { "native_texImage2D", "(IIIJII)I", (void*)util_texImage2D }, + { "native_texSubImage2D", "(IIIIJII)I", (void*)util_texSubImage2D }, }; static const JNINativeMethod gEtc1Methods[] = { diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp index 9c48c33dc2ed..7a8c5c8a7b36 100644 --- a/core/jni/android_graphics_Canvas.cpp +++ b/core/jni/android_graphics_Canvas.cpp @@ -54,20 +54,20 @@ static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) { } // Native wrapper constructor used by Canvas(Bitmap) -static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) { +static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) { SkBitmap bitmap; - if (jbitmap != NULL) { - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + if (bitmapHandle != 0) { + bitmap::toBitmap(bitmapHandle).getSkBitmap(&bitmap); } return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap)); } // Set the given bitmap as the new draw target (wrapped in a new SkCanvas), // optionally copying canvas matrix & clip state. -static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) { +static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle) { SkBitmap bitmap; - if (jbitmap != NULL) { - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + if (bitmapHandle != 0) { + bitmap::toBitmap(bitmapHandle).getSkBitmap(&bitmap); } get_canvas(canvasHandle)->setBitmap(bitmap); } @@ -397,7 +397,7 @@ static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmap jlong paintHandle, jint dstDensity, jint srcDensity) { Canvas* canvas = get_canvas(canvasHandle); - Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapHandle); + Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle); const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); @@ -423,11 +423,11 @@ static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmap } } -static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, +static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, jfloat left, jfloat top, jlong paintHandle, jint canvasDensity, jint screenDensity, jint bitmapDensity) { Canvas* canvas = get_canvas(canvasHandle); - Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap); + Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) { @@ -458,22 +458,22 @@ static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap } } -static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, +static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, jlong matrixHandle, jlong paintHandle) { const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); - Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap); + Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle); get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint); } -static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, +static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, jlong paintHandle, jint screenDensity, jint bitmapDensity) { Canvas* canvas = get_canvas(canvasHandle); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); - Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap); + Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle); if (screenDensity != 0 && screenDensity != bitmapDensity) { Paint filteredPaint; if (paint) { @@ -512,7 +512,7 @@ static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle, get_canvas(canvasHandle)->drawBitmap(*androidBitmap, x, y, paint); } -static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, +static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, jint meshWidth, jint meshHeight, jfloatArray jverts, jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) { if (Canvas::GetApiLevel() < __ANDROID_API_P__) { @@ -527,7 +527,7 @@ static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbi AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount); const Paint* paint = reinterpret_cast<Paint*>(paintHandle); - Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap); + Bitmap& bitmap = android::bitmap::toBitmap(bitmapHandle); get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight, vertA.ptr() + vertIndex*2, colorA.ptr() + colorIndex, paint); @@ -651,13 +651,13 @@ static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) { static const JNINativeMethod gMethods[] = { {"nGetNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer}, - {"nInitRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster}, {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches}, {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}, {"nSetCompatibilityVersion", "(I)V", (void*) CanvasJNI::setCompatibilityVersion}, // ------------ @FastNative ---------------- - {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap}, + {"nInitRaster", "(J)J", (void*) CanvasJNI::initRaster}, + {"nSetBitmap", "(JJ)V", (void*) CanvasJNI::setBitmap}, {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds}, // ------------ @CriticalNative ---------------- @@ -706,10 +706,10 @@ static const JNINativeMethod gDrawMethods[] = { {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath}, {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices}, {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch}, - {"nDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix}, - {"nDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, - {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap}, - {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, + {"nDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix}, + {"nDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, + {"nDrawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap}, + {"nDrawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, {"nDrawText","(J[CIIFFIJ)V", (void*) CanvasJNI::drawTextChars}, {"nDrawText","(JLjava/lang/String;IIFFIJ)V", (void*) CanvasJNI::drawTextString}, diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index c8f81e2193c8..88713d10bb2d 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -144,6 +144,7 @@ static struct { static jclass gAudioMixingRuleClass; static struct { jfieldID mCriteria; + jfieldID mAllowPrivilegedPlaybackCapture; // other fields unused by JNI } gAudioMixingRuleFields; @@ -1868,6 +1869,8 @@ static jint convertAudioMixToNative(JNIEnv *env, jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule); jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria); + nAudioMix->mAllowPrivilegedPlaybackCapture = + env->GetBooleanField(jRule, gAudioMixingRuleFields.mAllowPrivilegedPlaybackCapture); env->DeleteLocalRef(jRule); jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria, gArrayListMethods.toArray); @@ -2456,6 +2459,8 @@ int register_android_media_AudioSystem(JNIEnv *env) gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass); gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria", "Ljava/util/ArrayList;"); + gAudioMixingRuleFields.mAllowPrivilegedPlaybackCapture = + GetFieldIDOrDie(env, audioMixingRuleClass, "mAllowPrivilegedPlaybackCapture", "Z"); jclass audioMixMatchCriterionClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion"); diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index ecc2dd0d3598..e7cbf938b128 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -736,11 +736,11 @@ static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz, } static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz, - jlong proxyPtr, jlong layerPtr, jobject jbitmap) { + jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); return proxy->copyLayerInto(layer, bitmap); } @@ -911,9 +911,9 @@ static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env, static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env, jobject clazz, jobject jsurface, jint left, jint top, - jint right, jint bottom, jobject jbitmap) { + jint right, jint bottom, jlong bitmapPtr) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); sp<Surface> surface = android_view_Surface_getSurface(env, jsurface); return RenderProxy::copySurfaceInto(surface, left, top, right, bottom, &bitmap); } @@ -1106,7 +1106,7 @@ static const JNINativeMethod gMethods[] = { { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer }, - { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, + { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate }, { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate }, { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture }, @@ -1135,7 +1135,7 @@ static const JNINativeMethod gMethods[] = { { "nRemoveFrameMetricsObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver }, - { "nCopySurfaceInto", "(Landroid/view/Surface;IIIILandroid/graphics/Bitmap;)I", + { "nCopySurfaceInto", "(Landroid/view/Surface;IIIIJ)I", (void*)android_view_ThreadedRenderer_copySurfaceInto }, { "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;", (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode }, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 2d7cfa44f109..cffa46c64b36 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3562,10 +3562,30 @@ android:protectionLevel="signature" /> <!-- Allows an application to capture audio output. + Use the {@code CAPTURE_MEDIA_OUTPUT} permission if only the {@code USAGE_UNKNOWN}), + {@code USAGE_MEDIA}) or {@code USAGE_GAME}) usages are intended to be captured. <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi Allows an application to capture the audio played by other apps + that have set an allow capture policy of + {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM}. + + Without this permission, only audio with an allow capture policy of + {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_ALL} can be used. + + There are strong restriction listed at + {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM} + on what an app can do with the captured audio. + + See {@code CAPTURE_AUDIO_OUTPUT} for capturing audio use cases other than media playback. + + <p>Not for use by third-party applications.</p> + @hide --> + <permission android:name="android.permission.CAPTURE_MEDIA_OUTPUT" + android:protectionLevel="signature|privileged" /> + <!-- @SystemApi Allows an application to capture audio for hotword detection. <p>Not for use by third-party applications.</p> @hide --> diff --git a/core/res/res/drawable/ic_drag_handle.xml b/core/res/res/drawable/ic_drag_handle.xml index 67ab84d4080d..9b0e204608ff 100644 --- a/core/res/res/drawable/ic_drag_handle.xml +++ b/core/res/res/drawable/ic_drag_handle.xml @@ -13,11 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24.0dp" - android:height="24.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:pathData="M20.0,9.0L4.0,9.0l0.0,2.0l16.0,0.0L20.0,9.0zM4.0,15.0l16.0,0.0l0.0,-2.0L4.0,13.0l0.0,2.0z"/> -</vector>
\ No newline at end of file +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle" > + <solid android:color="#FFFFFFFF" /> + <corners android:radius="2dp" /> +</shape> diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml index 2860ee478db8..1f8041741b46 100644 --- a/core/res/res/layout/chooser_grid.xml +++ b/core/res/res/layout/chooser_grid.xml @@ -20,7 +20,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:maxCollapsedHeight="288dp" + android:maxCollapsedHeight="0dp" android:maxCollapsedHeightSmall="56dp" android:id="@id/contentPanel"> @@ -32,12 +32,12 @@ <ImageView android:id="@+id/drag" - android:layout_width="48dp" - android:layout_height="wrap_content" + android:layout_width="32dp" + android:layout_height="4dp" android:src="@drawable/ic_drag_handle" android:clickable="true" - android:paddingTop="@dimen/chooser_edge_margin_normal" - android:tint="?android:attr/textColorSecondary" + android:layout_marginTop="@dimen/chooser_view_spacing" + android:tint="@color/lighter_gray" android:layout_centerHorizontal="true" android:layout_alignParentTop="true" /> @@ -62,8 +62,8 @@ android:textAppearance="?attr/textAppearanceMedium" android:textSize="20sp" android:gravity="center" - android:paddingTop="18dp" - android:paddingBottom="18dp" + android:paddingTop="@dimen/chooser_view_spacing" + android:paddingBottom="@dimen/chooser_view_spacing" android:paddingLeft="24dp" android:paddingRight="24dp" android:layout_below="@id/profile_button" diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index fe2c6655a6ed..362d01c30487 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1673,8 +1673,19 @@ This flag is turned on by default. <em>This attribute is usable only by system apps. </em> --> <attr name="allowClearUserDataOnFailedRestore"/> - <!-- If {@code true} the app's non sensitive audio can be capture by other apps. - The default value is true. --> + <!-- If {@code true} the app's non sensitive audio can be capture by other apps with + {@code AudioPlaybackCaptureConfiguration} and a {@code MediaProjection}. + + <p> + Non sensitive audio is defined as audio whose {@code AttributeUsage} is + {@code USAGE_UNKNOWN}), {@code USAGE_MEDIA}) or {@code USAGE_GAME}). + All other usages (eg. {@code USAGE_VOICE_COMMUNICATION}) will not be captured. + + <p> + The default value is: + - {@code true} for apps with targetSdkVersion >= 29 (Q). + - {@code false} for apps with targetSdkVersion < 29. + --> <attr name="allowAudioPlaybackCapture" format="boolean" /> </declare-styleable> <!-- The <code>permission</code> tag declares a security permission that can be diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5f3b328f41b6..05b5389ba0d8 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3978,4 +3978,19 @@ <!-- Whether or not to enable automatic heap dumps for the system server on debuggable builds. --> <bool name="config_debugEnableAutomaticSystemServerHeapDumps">false</bool> + + <!-- See DropBoxManagerService. + The minimum period in milliseconds between broadcasts for entries with low priority + dropbox tags. --> + <integer name="config_dropboxLowPriorityBroadcastRateLimitPeriod">2000</integer> + + <!-- See DropBoxManagerService. + An array of dropbox entry tags to marked as low priority. Low priority broadcasts will be + rated limited to a period defined by config_dropboxLowPriorityBroadcastRateLimitPeriod + (high frequency broadcasts for the tag will be dropped) --> + <string-array name="config_dropboxLowPriorityTags" translatable="false"> + <item>keymaster</item> + <item>system_server_strictmode</item> + </string-array> + </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 023fbaddfb83..feecd020b087 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -725,4 +725,5 @@ <dimen name="resolver_icon_size">42dp</dimen> <dimen name="resolver_badge_size">18dp</dimen> <dimen name="chooser_target_width">76dp</dimen> + <dimen name="chooser_max_collapsed_height">288dp</dimen> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index db65bbcfbf64..7b156753192e 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2771,6 +2771,7 @@ <java-symbol type="dimen" name="chooser_edge_margin_normal" /> <java-symbol type="dimen" name="chooser_preview_image_font_size"/> <java-symbol type="dimen" name="chooser_preview_width" /> + <java-symbol type="dimen" name="chooser_max_collapsed_height" /> <java-symbol type="layout" name="chooser_grid" /> <java-symbol type="layout" name="chooser_grid_preview_text" /> <java-symbol type="layout" name="chooser_grid_preview_image" /> @@ -3729,4 +3730,7 @@ <java-symbol type="dimen" name="resolver_icon_size"/> <java-symbol type="dimen" name="resolver_badge_size"/> + <!-- For DropBox --> + <java-symbol type="integer" name="config_dropboxLowPriorityBroadcastRateLimitPeriod" /> + <java-symbol type="array" name="config_dropboxLowPriorityTags" /> </resources> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 8fc6a9694586..80250db581d4 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -287,8 +287,6 @@ public class SettingsBackupTest { Settings.Global.HDMI_CONTROL_ENABLED, Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, - Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, - Settings.Global.HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE, Settings.Global.HIDDEN_API_POLICY, Settings.Global.HIDE_ERROR_DIALOGS, Settings.Global.HTTP_PROXY, diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index 8c2375eaaf4c..185fa0750ff1 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -599,7 +599,7 @@ public class ChooserActivityTest { mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); - verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture()); + verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture()); // First invocation is from onCreate assertThat(logMakerCaptor.getAllValues().get(1).getCategory(), is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW)); @@ -629,7 +629,7 @@ public class ChooserActivityTest { ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); - verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture()); + verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture()); // First invocation is from onCreate assertThat(logMakerCaptor.getAllValues().get(1).getCategory(), is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW)); diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index fd3773588299..c9431e3178f0 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -112,14 +112,14 @@ public abstract class BaseCanvas { public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { throwIfCannotDraw(bitmap); throwIfHasHwBitmapInSwMode(paint); - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity); } public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { throwIfHasHwBitmapInSwMode(paint); - nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(), + nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getNativeInstance(), matrix.ni(), paint != null ? paint.getNativeInstance() : 0); } @@ -144,7 +144,7 @@ public abstract class BaseCanvas { bottom = src.bottom; } - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -170,7 +170,7 @@ public abstract class BaseCanvas { bottom = src.bottom; } - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -229,7 +229,7 @@ public abstract class BaseCanvas { // no mul by 2, since we need only 1 color per vertex checkRange(colors.length, colorOffset, count); } - nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight, + nDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getNativeInstance(), meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint != null ? paint.getNativeInstance() : 0); } @@ -240,7 +240,7 @@ public abstract class BaseCanvas { } public void drawColor(@ColorInt int color) { - nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt); + nDrawColor(mNativeCanvasWrapper, color, BlendMode.SRC_OVER.getXfermode().porterDuffMode); } /** @@ -664,10 +664,11 @@ public abstract class BaseCanvas { } } - private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top, - long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity); + private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float left, + float top, long nativePaintOrZero, int canvasDensity, int screenDensity, + int bitmapDensity); - private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float srcLeft, + private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity); @@ -726,10 +727,10 @@ public abstract class BaseCanvas { float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity); - private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap, + private static native void nDrawBitmapMatrix(long nativeCanvas, long bitmapHandle, long nativeMatrix, long nativePaint); - private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth, + private static native void nDrawBitmapMesh(long nativeCanvas, long bitmapHandle, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, long nativePaint); diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index 3e117411db01..028b784d24c2 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -67,7 +67,7 @@ public class BaseRecordingCanvas extends Canvas { public final void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { throwIfCannotDraw(bitmap); - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity); } @@ -75,7 +75,7 @@ public class BaseRecordingCanvas extends Canvas { @Override public final void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { - nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(), + nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getNativeInstance(), matrix.ni(), paint != null ? paint.getNativeInstance() : 0); } @@ -100,7 +100,7 @@ public class BaseRecordingCanvas extends Canvas { bottom = src.bottom; } - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -126,7 +126,7 @@ public class BaseRecordingCanvas extends Canvas { bottom = src.bottom; } - nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, + nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -188,7 +188,7 @@ public class BaseRecordingCanvas extends Canvas { // no mul by 2, since we need only 1 color per vertex checkRange(colors.length, colorOffset, count); } - nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight, + nDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getNativeInstance(), meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint != null ? paint.getNativeInstance() : 0); } @@ -200,7 +200,7 @@ public class BaseRecordingCanvas extends Canvas { @Override public final void drawColor(@ColorInt int color) { - nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt); + nDrawColor(mNativeCanvasWrapper, color, BlendMode.SRC_OVER.getXfermode().porterDuffMode); } /** @@ -581,11 +581,12 @@ public class BaseRecordingCanvas extends Canvas { } @FastNative - private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top, - long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity); + private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float left, + float top, long nativePaintOrZero, int canvasDensity, int screenDensity, + int bitmapDensity); @FastNative - private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, + private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity); @@ -663,11 +664,11 @@ public class BaseRecordingCanvas extends Canvas { int screenDensity, int bitmapDensity); @FastNative - private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap, + private static native void nDrawBitmapMatrix(long nativeCanvas, long bitmapHandle, long nativeMatrix, long nativePaint); @FastNative - private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth, + private static native void nDrawBitmapMesh(long nativeCanvas, long bitmapHandle, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, long nativePaint); diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index 49c3a3ba68b8..5623a8a49b35 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -436,9 +436,15 @@ public class BitmapFactory { static void validate(Options opts) { if (opts == null) return; - if (opts.inBitmap != null && opts.inBitmap.getConfig() == Bitmap.Config.HARDWARE) { - throw new IllegalArgumentException( - "Bitmaps with Config.HARDWARE are always immutable"); + if (opts.inBitmap != null) { + if (opts.inBitmap.getConfig() == Bitmap.Config.HARDWARE) { + throw new IllegalArgumentException( + "Bitmaps with Config.HARDWARE are always immutable"); + } + if (opts.inBitmap.isRecycled()) { + throw new IllegalArgumentException( + "Cannot reuse a recycled Bitmap"); + } } if (opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) { @@ -459,6 +465,17 @@ public class BitmapFactory { } /** + * Helper for passing inBitmap's native pointer to native. + */ + static long nativeInBitmap(Options opts) { + if (opts == null || opts.inBitmap == null) { + return 0; + } + + return opts.inBitmap.getNativeInstance(); + } + + /** * Helper for passing SkColorSpace pointer to native. * * @throws IllegalArgumentException if the ColorSpace is not Rgb or does @@ -646,6 +663,7 @@ public class BitmapFactory { Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap"); try { bm = nativeDecodeByteArray(data, offset, length, opts, + Options.nativeInBitmap(opts), Options.nativeColorSpace(opts)); if (bm == null && opts != null && opts.inBitmap != null) { @@ -741,7 +759,8 @@ public class BitmapFactory { try { if (is instanceof AssetManager.AssetInputStream) { final long asset = ((AssetManager.AssetInputStream) is).getNativeAsset(); - bm = nativeDecodeAsset(asset, outPadding, opts, Options.nativeColorSpace(opts)); + bm = nativeDecodeAsset(asset, outPadding, opts, Options.nativeInBitmap(opts), + Options.nativeColorSpace(opts)); } else { bm = decodeStreamInternal(is, outPadding, opts); } @@ -769,6 +788,7 @@ public class BitmapFactory { if (opts != null) tempStorage = opts.inTempStorage; if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE]; return nativeDecodeStream(is, tempStorage, outPadding, opts, + Options.nativeInBitmap(opts), Options.nativeColorSpace(opts)); } @@ -813,6 +833,7 @@ public class BitmapFactory { try { if (nativeIsSeekable(fd)) { bm = nativeDecodeFileDescriptor(fd, outPadding, opts, + Options.nativeInBitmap(opts), Options.nativeColorSpace(opts)); } else { FileInputStream fis = new FileInputStream(fd); @@ -850,15 +871,15 @@ public class BitmapFactory { @UnsupportedAppUsage private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage, - Rect padding, Options opts, long colorSpaceHandle); + Rect padding, Options opts, long inBitmapHandle, long colorSpaceHandle); @UnsupportedAppUsage private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd, - Rect padding, Options opts, long colorSpaceHandle); + Rect padding, Options opts, long inBitmapHandle, long colorSpaceHandle); @UnsupportedAppUsage private static native Bitmap nativeDecodeAsset(long nativeAsset, Rect padding, Options opts, - long colorSpaceHandle); + long inBitmapHandle, long colorSpaceHandle); @UnsupportedAppUsage private static native Bitmap nativeDecodeByteArray(byte[] data, int offset, - int length, Options opts, long colorSpaceHandle); + int length, Options opts, long inBitmapHandle, long colorSpaceHandle); private static native boolean nativeIsSeekable(FileDescriptor fd); } diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java index 1410423eafac..629d8c131b68 100644 --- a/graphics/java/android/graphics/BitmapRegionDecoder.java +++ b/graphics/java/android/graphics/BitmapRegionDecoder.java @@ -196,6 +196,7 @@ public final class BitmapRegionDecoder { throw new IllegalArgumentException("rectangle is outside the image"); return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, options, + BitmapFactory.Options.nativeInBitmap(options), BitmapFactory.Options.nativeColorSpace(options)); } } @@ -266,7 +267,8 @@ public final class BitmapRegionDecoder { private static native Bitmap nativeDecodeRegion(long lbm, int start_x, int start_y, int width, int height, - BitmapFactory.Options options, long colorSpaceHandle); + BitmapFactory.Options options, long inBitmapHandle, + long colorSpaceHandle); private static native int nativeGetWidth(long lbm); private static native int nativeGetHeight(long lbm); private static native void nativeClean(long lbm); diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java index eb0f2e1e18f2..198d1e7bc956 100644 --- a/graphics/java/android/graphics/BitmapShader.java +++ b/graphics/java/android/graphics/BitmapShader.java @@ -62,9 +62,9 @@ public class BitmapShader extends Shader { @Override long createNativeInstance(long nativeMatrix) { - return nativeCreate(nativeMatrix, mBitmap, mTileX, mTileY); + return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY); } - private static native long nativeCreate(long nativeMatrix, Bitmap bitmap, + private static native long nativeCreate(long nativeMatrix, long bitmapHandle, int shaderTileModeX, int shaderTileModeY); } diff --git a/graphics/java/android/graphics/BlendMode.java b/graphics/java/android/graphics/BlendMode.java index 39392c89d170..0b267048d976 100644 --- a/graphics/java/android/graphics/BlendMode.java +++ b/graphics/java/android/graphics/BlendMode.java @@ -454,6 +454,64 @@ public enum BlendMode { return null; } + /** + * @hide + */ + public static int toValue(BlendMode mode) { + return mode.getXfermode().porterDuffMode; + } + + /** + * @hide + */ + public static @Nullable PorterDuff.Mode blendModeToPorterDuffMode(@Nullable BlendMode mode) { + if (mode != null) { + switch (mode) { + case CLEAR: + return PorterDuff.Mode.CLEAR; + case SRC: + return PorterDuff.Mode.SRC; + case DST: + return PorterDuff.Mode.DST; + case SRC_OVER: + return PorterDuff.Mode.SRC_OVER; + case DST_OVER: + return PorterDuff.Mode.DST_OVER; + case SRC_IN: + return PorterDuff.Mode.SRC_IN; + case DST_IN: + return PorterDuff.Mode.DST_IN; + case SRC_OUT: + return PorterDuff.Mode.SRC_OUT; + case DST_OUT: + return PorterDuff.Mode.DST_OUT; + case SRC_ATOP: + return PorterDuff.Mode.SRC_ATOP; + case DST_ATOP: + return PorterDuff.Mode.DST_ATOP; + case XOR: + return PorterDuff.Mode.XOR; + case DARKEN: + return PorterDuff.Mode.DARKEN; + case LIGHTEN: + return PorterDuff.Mode.LIGHTEN; + // b/73224934 PorterDuff Multiply maps to Skia Modulate + case MODULATE: + return PorterDuff.Mode.MULTIPLY; + case SCREEN: + return PorterDuff.Mode.SCREEN; + case PLUS: + return PorterDuff.Mode.ADD; + case OVERLAY: + return PorterDuff.Mode.OVERLAY; + default: + return null; + } + } else { + return null; + } + } + @NonNull private final Xfermode mXfermode; diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index df64204d8647..6f00fc907849 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -95,7 +95,7 @@ public class Canvas extends BaseCanvas { public Canvas() { if (!isHardwareAccelerated()) { // 0 means no native bitmap - mNativeCanvasWrapper = nInitRaster(null); + mNativeCanvasWrapper = nInitRaster(0); mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation( this, mNativeCanvasWrapper); } else { @@ -117,7 +117,7 @@ public class Canvas extends BaseCanvas { throw new IllegalStateException("Immutable bitmap passed to Canvas constructor"); } throwIfCannotDraw(bitmap); - mNativeCanvasWrapper = nInitRaster(bitmap); + mNativeCanvasWrapper = nInitRaster(bitmap.getNativeInstance()); mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation( this, mNativeCanvasWrapper); mBitmap = bitmap; @@ -185,7 +185,7 @@ public class Canvas extends BaseCanvas { } if (bitmap == null) { - nSetBitmap(mNativeCanvasWrapper, null); + nSetBitmap(mNativeCanvasWrapper, 0); mDensity = Bitmap.DENSITY_NONE; } else { if (!bitmap.isMutable()) { @@ -193,7 +193,7 @@ public class Canvas extends BaseCanvas { } throwIfCannotDraw(bitmap); - nSetBitmap(mNativeCanvasWrapper, bitmap); + nSetBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance()); mDensity = bitmap.mDensity; } @@ -1364,14 +1364,16 @@ public class Canvas extends BaseCanvas { private static native void nFreeCaches(); private static native void nFreeTextLayoutCaches(); - private static native long nInitRaster(Bitmap bitmap); private static native long nGetNativeFinalizer(); private static native void nSetCompatibilityVersion(int apiLevel); // ---------------- @FastNative ------------------- @FastNative - private static native void nSetBitmap(long canvasHandle, Bitmap bitmap); + private static native long nInitRaster(long bitmapHandle); + + @FastNative + private static native void nSetBitmap(long canvasHandle, long bitmapHandle); @FastNative private static native boolean nGetClipBounds(long nativeCanvas, Rect bounds); diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java index 189e1746e644..93ddb10d24bc 100644 --- a/graphics/java/android/graphics/ComposeShader.java +++ b/graphics/java/android/graphics/ComposeShader.java @@ -39,7 +39,10 @@ public class ComposeShader extends Shader { * @param shaderB The colors from this shader are seen as the "src" by the mode * @param mode The mode that combines the colors from the two shaders. If mode * is null, then SRC_OVER is assumed. + * + * @deprecated use {@link #ComposeShader(Shader, Shader, BlendMode)} instead */ + @Deprecated public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) { this(shaderA, shaderB, mode.porterDuffMode); } @@ -52,12 +55,29 @@ public class ComposeShader extends Shader { * @param shaderA The colors from this shader are seen as the "dst" by the mode * @param shaderB The colors from this shader are seen as the "src" by the mode * @param mode The PorterDuff mode that combines the colors from the two shaders. - */ + * + * @deprecated use {@link #ComposeShader(Shader, Shader, BlendMode)} instead + */ + @Deprecated public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull PorterDuff.Mode mode) { this(shaderA, shaderB, mode.nativeInt); } + /** + * Create a new compose shader, given shaders A, B, and a combining PorterDuff mode. + * When the mode is applied, it will be given the result from shader A as its + * "dst", and the result from shader B as its "src". + * + * @param shaderA The colors from this shader are seen as the "dst" by the mode + * @param shaderB The colors from this shader are seen as the "src" by the mode + * @param blendMode The blend mode that combines the colors from the two shaders. + */ + public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, + @NonNull BlendMode blendMode) { + this(shaderA, shaderB, blendMode.getXfermode().porterDuffMode); + } + private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) { if (shaderA == null || shaderB == null) { throw new IllegalArgumentException("Shader parameters must not be null"); diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index bc744cc7af3d..b6b2d4e1c46a 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -682,8 +682,8 @@ public class HardwareRenderer { /** @hide */ public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) { - return nCopyLayerInto(mNativeProxy, - layer.getDeferredLayerUpdater(), bitmap); + return nCopyLayerInto(mNativeProxy, layer.getDeferredLayerUpdater(), + bitmap.getNativeInstance()); } /** @@ -910,10 +910,10 @@ public class HardwareRenderer { public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) { if (srcRect == null) { // Empty rect means entire surface - return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap); + return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap.getNativeInstance()); } else { return nCopySurfaceInto(surface, srcRect.left, srcRect.top, - srcRect.right, srcRect.bottom, bitmap); + srcRect.right, srcRect.bottom, bitmap.getNativeInstance()); } } @@ -1115,7 +1115,7 @@ public class HardwareRenderer { private static native void nBuildLayer(long nativeProxy, long node); - private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap); + private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmapHandle); private static native void nPushLayerUpdate(long nativeProxy, long layer); @@ -1162,7 +1162,7 @@ public class HardwareRenderer { private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver); private static native int nCopySurfaceInto(Surface surface, - int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap); + int srcLeft, int srcTop, int srcRight, int srcBottom, long bitmapHandle); private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height); diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java index 800247af4927..c4c1eaceb4fc 100644 --- a/graphics/java/android/graphics/NinePatch.java +++ b/graphics/java/android/graphics/NinePatch.java @@ -261,7 +261,8 @@ public class NinePatch { * that are transparent. */ public final Region getTransparentRegion(Rect bounds) { - long r = nativeGetTransparentRegion(mBitmap, mNativeChunk, bounds); + long r = nativeGetTransparentRegion(mBitmap.getNativeInstance(), + mNativeChunk, bounds); return r != 0 ? new Region(r) : null; } @@ -282,5 +283,6 @@ public class NinePatch { */ private static native long validateNinePatchChunk(byte[] chunk); private static native void nativeFinalize(long chunk); - private static native long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location); + private static native long nativeGetTransparentRegion(long bitmapHandle, long chunk, + Rect location); } diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java index fba50430f2ef..459291b7565e 100644 --- a/graphics/java/android/graphics/PorterDuff.java +++ b/graphics/java/android/graphics/PorterDuff.java @@ -23,7 +23,10 @@ import android.annotation.UnsupportedAppUsage; * that can be passed to {@link PorterDuffXfermode}, a specialized implementation * of {@link Paint}'s {@link Paint#setXfermode(Xfermode) transfer mode}. * All the available modes can be found in the {@link Mode} enum.</p> + * + * @deprecated Use {@link BlendMode} with {@link Paint#setBlendMode(BlendMode)} instead */ +@Deprecated public class PorterDuff { /** * {@usesMathJax} diff --git a/graphics/java/android/graphics/PorterDuffXfermode.java b/graphics/java/android/graphics/PorterDuffXfermode.java index 84d953de91db..5b933c493162 100644 --- a/graphics/java/android/graphics/PorterDuffXfermode.java +++ b/graphics/java/android/graphics/PorterDuffXfermode.java @@ -21,6 +21,11 @@ package android.graphics; * {@link Paint#setXfermode(Xfermode) transfer mode}. Refer to the * documentation of the {@link PorterDuff.Mode} enum for more * information on the available alpha compositing and blending modes.</p> + * + * @deprecated Consider using {@link BlendMode} instead as it supports a wider + * set of blend modes than those defined in {@link PorterDuff.Mode} + * + * @see Paint#setBlendMode(BlendMode) */ public class PorterDuffXfermode extends Xfermode { /** diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java index cb12a7c6ba6b..7def322c1953 100644 --- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java @@ -27,6 +27,7 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -35,7 +36,6 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Shader; @@ -701,13 +701,13 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final ChildDrawable[] array = mLayerState.mChildren; final int N = mLayerState.N_CHILDREN; for (int i = 0; i < N; i++) { final Drawable dr = array[i].mDrawable; if (dr != null) { - dr.setTintMode(tintMode); + dr.setTintMode(blendMode); } } } diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index d9dab98c2be1..f45bf9b783e8 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -33,12 +33,12 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.RecordingCanvas; import android.graphics.Rect; import android.graphics.RenderNode; @@ -477,8 +477,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } @Override - public void setTintMode(PorterDuff.Mode tintMode) { - mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mAnimatedVectorState.mVectorDrawable.setTintMode(blendMode); } @Override diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index 976190109e7c..6b30158a183a 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -25,6 +25,8 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.ImageDecoder; @@ -33,9 +35,7 @@ import android.graphics.Matrix; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.Xfermode; @@ -90,7 +90,7 @@ public class BitmapDrawable extends Drawable { @UnsupportedAppUsage private BitmapState mBitmapState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeFilter; @UnsupportedAppUsage private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; @@ -527,8 +527,8 @@ public class BitmapDrawable extends Drawable { } final boolean clearColorFilter; - if (mTintFilter != null && paint.getColorFilter() == null) { - paint.setColorFilter(mTintFilter); + if (mBlendModeFilter != null && paint.getColorFilter() == null) { + paint.setColorFilter(mBlendModeFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -678,17 +678,19 @@ public class BitmapDrawable extends Drawable { final BitmapState state = mBitmapState; if (state.mTint != tint) { state.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mBitmapState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, tint, + mBitmapState.mBlendMode); invalidateSelf(); } } @Override - public void setTintMode(PorterDuff.Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final BitmapState state = mBitmapState; - if (state.mTintMode != tintMode) { - state.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, tintMode); + if (state.mBlendMode != blendMode) { + state.mBlendMode = blendMode; + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mBitmapState.mTint, + blendMode); invalidateSelf(); } } @@ -706,7 +708,7 @@ public class BitmapDrawable extends Drawable { */ @UnsupportedAppUsage public Mode getTintMode() { - return mBitmapState.mTintMode; + return BlendMode.blendModeToPorterDuffMode(mBitmapState.mBlendMode); } /** @@ -744,8 +746,9 @@ public class BitmapDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final BitmapState state = mBitmapState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -864,7 +867,7 @@ public class BitmapDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.BitmapDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.BitmapDrawable_tint); @@ -979,7 +982,8 @@ public class BitmapDrawable extends Drawable { int[] mThemeAttrs = null; Bitmap mBitmap = null; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; + int mGravity = Gravity.FILL; float mBaseAlpha = 1.0f; Shader.TileMode mTileModeX = null; @@ -1005,7 +1009,7 @@ public class BitmapDrawable extends Drawable { BitmapState(BitmapState bitmapState) { mBitmap = bitmapState.mBitmap; mTint = bitmapState.mTint; - mTintMode = bitmapState.mTintMode; + mBlendMode = bitmapState.mBlendMode; mThemeAttrs = bitmapState.mThemeAttrs; mChangingConfigurations = bitmapState.mChangingConfigurations; mGravity = bitmapState.mGravity; @@ -1065,7 +1069,8 @@ public class BitmapDrawable extends Drawable { */ private void updateLocalState(Resources res) { mTargetDensity = resolveDensity(res, mBitmapState.mTargetDensity); - mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, mBitmapState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mBitmapState.mTint, + mBitmapState.mBlendMode); computeBitmapSize(); } } diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index 3c449166d9d5..efa806afce70 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -26,13 +26,13 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Xfermode; import android.util.AttributeSet; import android.view.ViewDebug; @@ -58,7 +58,7 @@ public class ColorDrawable extends Drawable { @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_") private ColorState mColorState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeColorFilter; private boolean mMutated; @@ -111,9 +111,10 @@ public class ColorDrawable extends Drawable { @Override public void draw(Canvas canvas) { final ColorFilter colorFilter = mPaint.getColorFilter(); - if ((mColorState.mUseColor >>> 24) != 0 || colorFilter != null || mTintFilter != null) { + if ((mColorState.mUseColor >>> 24) != 0 || colorFilter != null + || mBlendModeColorFilter != null) { if (colorFilter == null) { - mPaint.setColorFilter(mTintFilter); + mPaint.setColorFilter(mBlendModeColorFilter); } mPaint.setColor(mColorState.mUseColor); @@ -208,22 +209,25 @@ public class ColorDrawable extends Drawable { @Override public void setTintList(ColorStateList tint) { mColorState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mColorState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, + mColorState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(Mode tintMode) { - mColorState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mColorState.mTint, tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mColorState.mBlendMode = blendMode; + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mColorState.mTint, + blendMode); invalidateSelf(); } @Override protected boolean onStateChange(int[] stateSet) { final ColorState state = mColorState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -261,7 +265,7 @@ public class ColorDrawable extends Drawable { @Override public int getOpacity() { - if (mTintFilter != null || mPaint.getColorFilter() != null) { + if (mBlendModeColorFilter != null || mPaint.getColorFilter() != null) { return PixelFormat.TRANSLUCENT; } @@ -348,7 +352,7 @@ public class ColorDrawable extends Drawable { int mUseColor; // basecolor modulated by setAlpha() @Config int mChangingConfigurations; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; ColorState() { // Empty constructor. @@ -360,7 +364,7 @@ public class ColorDrawable extends Drawable { mUseColor = state.mUseColor; mChangingConfigurations = state.mChangingConfigurations; mTint = state.mTint; - mTintMode = state.mTintMode; + mBlendMode = state.mBlendMode; } @Override @@ -398,6 +402,7 @@ public class ColorDrawable extends Drawable { * after inflating or applying a theme. */ private void updateLocalState(Resources r) { - mTintFilter = updateTintFilter(mTintFilter, mColorState.mTint, mColorState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mColorState.mTint, + mColorState.mBlendMode); } } diff --git a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java index ee4d1e72c130..b94b11468371 100644 --- a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java @@ -21,10 +21,10 @@ import android.annotation.Nullable; import android.content.pm.ActivityInfo; import android.content.res.ColorStateList; import android.content.res.Resources; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.util.MathUtils; /** @@ -114,9 +114,9 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac } @Override - public void setTintMode(@NonNull PorterDuff.Mode tintMode) { - mState.mTintMode = tintMode; - mColorDrawable.setTintMode(tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mState.mBlendMode = blendMode; + mColorDrawable.setTintMode(blendMode); onStateChange(getState()); } @@ -236,7 +236,7 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac ColorStateList mColor = null; ColorStateList mTint = null; int mAlpha = -1; - PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; @ActivityInfo.Config int mChangingConfigurations = 0; ColorStateListDrawableState() { @@ -246,7 +246,7 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac mColor = state.mColor; mTint = state.mTint; mAlpha = state.mAlpha; - mTintMode = state.mTintMode; + mBlendMode = state.mBlendMode; mChangingConfigurations = state.mChangingConfigurations; } @@ -292,8 +292,8 @@ public class ColorStateListDrawable extends Drawable implements Drawable.Callbac mColorDrawable.setTintList(mState.mTint); } - if (mState.mTintMode != DEFAULT_TINT_MODE) { - mColorDrawable.setTintMode(mState.mTintMode); + if (mState.mBlendMode != DEFAULT_BLEND_MODE) { + mColorDrawable.setTintMode(mState.mBlendMode); } } } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 49d353057d59..e4142a933f0f 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -30,6 +30,8 @@ import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -182,6 +184,7 @@ public abstract class Drawable { private static final Rect ZERO_BOUNDS_RECT = new Rect(); static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; + static final BlendMode DEFAULT_BLEND_MODE = BlendMode.SRC_IN; private int[] mStateSet = StateSet.WILD_CARD; private int mLevel = 0; @@ -210,6 +213,24 @@ public abstract class Drawable { protected int mSrcDensityOverride = 0; /** + * Flag used to break the recursive loop between setTintMode(PorterDuff.Mode) and + * setTintMode(BlendMode) as each default implementation invokes the other in order to + * support new use cases that utilize the new blending modes as well as support the legacy + * use cases. This flag tracks that {@link #setTintMode(BlendMode)} is only invoked once + * per invocation. + */ + private boolean mSetBlendModeInvoked = false; + + /** + * Flag used to break the recursive loop between setTintMode(PorterDuff.Mode) and + * setTintMode(BlendMode) as each default implementation invokes the other in order to + * support new use cases that utilize the new blending modes as well as support the legacy + * use cases. This flag tracks that {@link #setTintMode(Mode)} is only invoked once + * per invocation; + */ + private boolean mSetTintModeInvoked = false; + + /** * Draw in its bounds (set via setBounds) respecting optional effects such * as alpha (set via setAlpha) and color filter (set via setColorFilter). * @@ -630,6 +651,7 @@ public abstract class Drawable { * @param tintColor Color to use for tinting this drawable * @see #setTintList(ColorStateList) * @see #setTintMode(PorterDuff.Mode) + * @see #setTintMode(BlendMode) */ public void setTint(@ColorInt int tintColor) { setTintList(ColorStateList.valueOf(tintColor)); @@ -651,6 +673,7 @@ public abstract class Drawable { * {@code null} to clear the tint * @see #setTint(int) * @see #setTintMode(PorterDuff.Mode) + * @see #setTintMode(BlendMode) */ public void setTintList(@Nullable ColorStateList tint) {} @@ -668,8 +691,45 @@ public abstract class Drawable { * @param tintMode A Porter-Duff blending mode * @see #setTint(int) * @see #setTintList(ColorStateList) + * + * @deprecated use {@link #setTintMode(BlendMode)} instead + */ + @Deprecated + public void setTintMode(@NonNull PorterDuff.Mode tintMode) { + if (!mSetTintModeInvoked) { + mSetTintModeInvoked = true; + BlendMode mode = BlendMode.fromValue(tintMode.nativeInt); + if (mode != null) { + setTintMode(mode); + } + mSetTintModeInvoked = false; + } + } + + /** + * Specifies a tint blending mode for this drawable. + * <p> + * Defines how this drawable's tint color should be blended into the drawable + * before it is drawn to screen. Default tint mode is {@link BlendMode#SRC_IN}. + * </p> + * <p class="note"><strong>Note:</strong> Setting a color filter via + * {@link #setColorFilter(ColorFilter)} + * </p> + * + * @param blendMode + * @see #setTint(int) + * @see #setTintList(ColorStateList) */ - public void setTintMode(@NonNull PorterDuff.Mode tintMode) {} + public void setTintMode(@NonNull BlendMode blendMode) { + if (!mSetBlendModeInvoked) { + mSetBlendModeInvoked = true; + PorterDuff.Mode mode = BlendMode.blendModeToPorterDuffMode(blendMode); + if (mode != null) { + setTintMode(mode); + } + mSetBlendModeInvoked = false; + } + } /** * Returns the current color filter, or {@code null} if none set. @@ -1540,6 +1600,20 @@ public abstract class Drawable { return tintFilter; } + @Nullable BlendModeColorFilter updateBlendModeFilter(@Nullable BlendModeColorFilter blendFilter, + @Nullable ColorStateList tint, @Nullable BlendMode blendMode) { + if (tint == null || blendMode == null) { + return null; + } + + final int color = tint.getColorForState(getState(), Color.TRANSPARENT); + if (blendFilter == null || blendFilter.getColor() != color + || blendFilter.getMode() != blendMode) { + return new BlendModeColorFilter(color, blendMode); + } + return blendFilter; + } + /** * Obtains styled attributes from the theme, if available, or unstyled * resources if the theme is null. @@ -1642,5 +1716,26 @@ public abstract class Drawable { default: return defaultMode; } } + + /** + * Parses a {@link android.graphics.BlendMode} from a tintMode + * attribute's enum value. + * + * @hide + */ + @UnsupportedAppUsage + public static BlendMode parseBlendMode(int value, BlendMode defaultMode) { + switch (value) { + case 3: return BlendMode.SRC_OVER; + case 5: return BlendMode.SRC_IN; + case 9: return BlendMode.SRC_ATOP; + // b/73224934 PorterDuff Multiply maps to Skia Modulate so actually + // return BlendMode.MODULATE here + case 14: return BlendMode.MODULATE; + case 15: return BlendMode.SCREEN; + case 16: return BlendMode.PLUS; + default: return defaultMode; + } + } } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 77e77c49973c..3e0881aef9ed 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -22,12 +22,12 @@ import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.os.Build; import android.os.SystemClock; @@ -196,14 +196,14 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { mDrawableContainerState.mHasTintMode = true; - if (mDrawableContainerState.mTintMode != tintMode) { - mDrawableContainerState.mTintMode = tintMode; + if (mDrawableContainerState.mBlendMode != blendMode) { + mDrawableContainerState.mBlendMode = blendMode; if (mCurrDrawable != null) { - mCurrDrawable.setTintMode(tintMode); + mCurrDrawable.setTintMode(blendMode); } } } @@ -544,7 +544,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { d.setTintList(mDrawableContainerState.mTintList); } if (mDrawableContainerState.mHasTintMode) { - d.setTintMode(mDrawableContainerState.mTintMode); + d.setTintMode(mDrawableContainerState.mBlendMode); } } @@ -730,7 +730,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mHasColorFilter; ColorStateList mTintList; - Mode mTintMode; + BlendMode mBlendMode; boolean mHasTintList; boolean mHasTintMode; @@ -762,7 +762,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { mColorFilter = orig.mColorFilter; mHasColorFilter = orig.mHasColorFilter; mTintList = orig.mTintList; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; mHasTintList = orig.mHasTintList; mHasTintMode = orig.mHasTintMode; diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java index 70c90eb05b17..d81401d451ca 100644 --- a/graphics/java/android/graphics/drawable/DrawableWrapper.java +++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java @@ -24,12 +24,12 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.Xfermode; import android.util.AttributeSet; @@ -324,9 +324,9 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb } @Override - public void setTintMode(@Nullable PorterDuff.Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { if (mDrawable != null) { - mDrawable.setTintMode(tintMode); + mDrawable.setTintMode(blendMode); } } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index e58e80225292..cdb3441d5225 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -28,6 +28,8 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -38,8 +40,6 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; @@ -169,7 +169,7 @@ public class GradientDrawable extends Drawable { @UnsupportedAppUsage private Paint mStrokePaint; // optional, set by the caller private ColorFilter mColorFilter; // optional, set by the caller - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeColorFilter; private int mAlpha = 0xFF; // modified by the caller private final Path mPath = new Path(); @@ -731,7 +731,7 @@ public class GradientDrawable extends Drawable { mStrokePaint.getStrokeWidth() > 0; final boolean haveFill = currFillAlpha > 0; final GradientState st = mGradientState; - final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mTintFilter; + final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mBlendModeColorFilter; /* we need a layer iff we're drawing both a fill and stroke, and the stroke is non-opaque, and our shapetype actually supports @@ -1130,8 +1130,9 @@ public class GradientDrawable extends Drawable { } } - if (s.mTint != null && s.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode); + if (s.mTint != null && s.mBlendMode != null) { + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, s.mTint, + s.mBlendMode); invalidateSelf = true; } @@ -1204,14 +1205,16 @@ public class GradientDrawable extends Drawable { @Override public void setTintList(@Nullable ColorStateList tint) { mGradientState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode); + mBlendModeColorFilter = + updateBlendModeFilter(mBlendModeColorFilter, tint, mGradientState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(@Nullable PorterDuff.Mode tintMode) { - mGradientState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mGradientState.mBlendMode = blendMode; + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mGradientState.mTint, + blendMode); invalidateSelf(); } @@ -1465,7 +1468,7 @@ public class GradientDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, PorterDuff.Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.GradientDrawable_tint); @@ -2010,7 +2013,7 @@ public class GradientDrawable extends Drawable { boolean mOpaqueOverShape; ColorStateList mTint = null; - PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; int mDensity = DisplayMetrics.DENSITY_DEFAULT; @@ -2068,7 +2071,7 @@ public class GradientDrawable extends Drawable { mOpaqueOverBounds = orig.mOpaqueOverBounds; mOpaqueOverShape = orig.mOpaqueOverShape; mTint = orig.mTint; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; mThemeAttrs = orig.mThemeAttrs; mAttrSize = orig.mAttrSize; mAttrGradient = orig.mAttrGradient; @@ -2355,7 +2358,8 @@ public class GradientDrawable extends Drawable { } } - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); mGradientIsDirty = true; state.computeOpacity(); diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index 71dd7a2f4800..5fd18a1431e0 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -30,6 +30,7 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BlendMode; import android.graphics.PorterDuff; import android.net.Uri; import android.os.AsyncTask; @@ -105,8 +106,8 @@ public final class Icon implements Parcelable { private final int mType; private ColorStateList mTintList; - static final PorterDuff.Mode DEFAULT_TINT_MODE = Drawable.DEFAULT_TINT_MODE; // SRC_IN - private PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + static final BlendMode DEFAULT_BLEND_MODE = Drawable.DEFAULT_BLEND_MODE; // SRC_IN + private BlendMode mBlendMode = Drawable.DEFAULT_BLEND_MODE; // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed // based on the value of mType. @@ -320,10 +321,10 @@ public final class Icon implements Parcelable { */ public Drawable loadDrawable(Context context) { final Drawable result = loadDrawableInner(context); - if (result != null && (mTintList != null || mTintMode != DEFAULT_TINT_MODE)) { + if (result != null && (mTintList != null || mBlendMode != DEFAULT_BLEND_MODE)) { result.mutate(); result.setTintList(mTintList); - result.setTintMode(mTintMode); + result.setTintMode(mBlendMode); } return result; } @@ -695,16 +696,30 @@ public final class Icon implements Parcelable { * * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null * @return this same object, for use in chained construction + * + * @deprecated use {@link #setTintMode(BlendMode)} instead + */ + @Deprecated + public @NonNull Icon setTintMode(@NonNull PorterDuff.Mode mode) { + mBlendMode = BlendMode.fromValue(mode.nativeInt); + return this; + } + + /** + * Store a blending mode to use whenever this Icon is drawn. + * + * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null + * @return this same object, for use in chained construction */ - public Icon setTintMode(PorterDuff.Mode mode) { - mTintMode = mode; + public @NonNull Icon setTintMode(@NonNull BlendMode mode) { + mBlendMode = mode; return this; } /** @hide */ @UnsupportedAppUsage public boolean hasTint() { - return (mTintList != null) || (mTintMode != DEFAULT_TINT_MODE); + return (mTintList != null) || (mBlendMode != DEFAULT_BLEND_MODE); } /** @@ -757,7 +772,7 @@ public final class Icon implements Parcelable { sep = "|"; } } - if (mTintMode != DEFAULT_TINT_MODE) sb.append(" mode=").append(mTintMode); + if (mBlendMode != DEFAULT_BLEND_MODE) sb.append(" mode=").append(mBlendMode); sb.append(")"); return sb.toString(); } @@ -807,7 +822,7 @@ public final class Icon implements Parcelable { if (in.readInt() == 1) { mTintList = ColorStateList.CREATOR.createFromParcel(in); } - mTintMode = PorterDuff.intToMode(in.readInt()); + mBlendMode = BlendMode.fromValue(in.readInt()); } @Override @@ -837,7 +852,7 @@ public final class Icon implements Parcelable { dest.writeInt(1); mTintList.writeToParcel(dest, flags); } - dest.writeInt(PorterDuff.modeToInt(mTintMode)); + dest.writeInt(BlendMode.toValue(mBlendMode)); } public static final @android.annotation.NonNull Parcelable.Creator<Icon> CREATOR diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index b4392c8d023f..e2c84927b578 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -24,11 +24,11 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.util.AttributeSet; import android.util.DisplayMetrics; @@ -1397,13 +1397,13 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final ChildDrawable[] array = mLayerState.mChildren; final int N = mLayerState.mNumChildren; for (int i = 0; i < N; i++) { final Drawable dr = array[i].mDrawable; if (dr != null) { - dr.setTintMode(tintMode); + dr.setTintMode(blendMode); } } } diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index b53477137331..4972e6a82b7d 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -25,6 +25,8 @@ import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.ImageDecoder; @@ -33,9 +35,6 @@ import android.graphics.NinePatch; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Region; import android.util.AttributeSet; @@ -73,7 +72,7 @@ public class NinePatchDrawable extends Drawable { @UnsupportedAppUsage private NinePatchState mNinePatchState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeFilter; private Rect mPadding; private Insets mOpticalInsets = Insets.NONE; private Rect mOutlineInsets; @@ -198,8 +197,8 @@ public class NinePatchDrawable extends Drawable { int restoreToCount = -1; final boolean clearColorFilter; - if (mTintFilter != null && getPaint().getColorFilter() == null) { - mPaint.setColorFilter(mTintFilter); + if (mBlendModeFilter != null && getPaint().getColorFilter() == null) { + mPaint.setColorFilter(mBlendModeFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -344,14 +343,16 @@ public class NinePatchDrawable extends Drawable { @Override public void setTintList(@Nullable ColorStateList tint) { mNinePatchState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mNinePatchState.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, tint, + mNinePatchState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(@Nullable PorterDuff.Mode tintMode) { - mNinePatchState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mNinePatchState.mTint, tintMode); + public void setTintMode(@Nullable BlendMode blendMode) { + mNinePatchState.mBlendMode = blendMode; + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, mNinePatchState.mTint, + blendMode); invalidateSelf(); } @@ -467,7 +468,7 @@ public class NinePatchDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.NinePatchDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.NinePatchDrawable_tint); @@ -566,8 +567,9 @@ public class NinePatchDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final NinePatchState state = mNinePatchState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, + state.mBlendMode); return true; } @@ -593,7 +595,7 @@ public class NinePatchDrawable extends Drawable { @UnsupportedAppUsage NinePatch mNinePatch = null; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; Rect mPadding = null; Insets mOpticalInsets = Insets.NONE; float mBaseAlpha = 1.0f; @@ -628,7 +630,7 @@ public class NinePatchDrawable extends Drawable { mChangingConfigurations = orig.mChangingConfigurations; mNinePatch = orig.mNinePatch; mTint = orig.mTint; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; mPadding = orig.mPadding; mOpticalInsets = orig.mOpticalInsets; mBaseAlpha = orig.mBaseAlpha; @@ -751,7 +753,7 @@ public class NinePatchDrawable extends Drawable { } else { mTargetDensity = Drawable.resolveDensity(res, mTargetDensity); } - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + mBlendModeFilter = updateBlendModeFilter(mBlendModeFilter, state.mTint, state.mBlendMode); computeBitmapSize(); } } diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index 7bfb4c38d6c8..b5fe7f9e432d 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -24,14 +24,13 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.Xfermode; @@ -75,7 +74,7 @@ import java.io.IOException; */ public class ShapeDrawable extends Drawable { private @NonNull ShapeState mShapeState; - private PorterDuffColorFilter mTintFilter; + private BlendModeColorFilter mBlendModeColorFilter; private boolean mMutated; /** @@ -238,8 +237,8 @@ public class ShapeDrawable extends Drawable { // only draw shape if it may affect output if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadowLayer()) { final boolean clearColorFilter; - if (mTintFilter != null && paint.getColorFilter() == null) { - paint.setColorFilter(mTintFilter); + if (mBlendModeColorFilter != null && paint.getColorFilter() == null) { + paint.setColorFilter(mBlendModeColorFilter); clearColorFilter = true; } else { clearColorFilter = false; @@ -292,14 +291,16 @@ public class ShapeDrawable extends Drawable { @Override public void setTintList(ColorStateList tint) { mShapeState.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, mShapeState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, + mShapeState.mBlendMode); invalidateSelf(); } @Override - public void setTintMode(PorterDuff.Mode tintMode) { - mShapeState.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, tintMode); + public void setTintMode(@NonNull BlendMode blendMode) { + mShapeState.mBlendMode = blendMode; + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mShapeState.mTint, + blendMode); invalidateSelf(); } @@ -352,8 +353,9 @@ public class ShapeDrawable extends Drawable { @Override protected boolean onStateChange(int[] stateSet) { final ShapeState state = mShapeState; - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, state.mTint, + state.mBlendMode); return true; } return false; @@ -475,7 +477,7 @@ public class ShapeDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.ShapeDrawable_tint); @@ -540,7 +542,7 @@ public class ShapeDrawable extends Drawable { int[] mThemeAttrs; Shape mShape; ColorStateList mTint; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; Rect mPadding; int mIntrinsicWidth; int mIntrinsicHeight; @@ -573,7 +575,7 @@ public class ShapeDrawable extends Drawable { } } mTint = orig.mTint; - mTintMode = orig.mTintMode; + mBlendMode = orig.mBlendMode; if (orig.mPadding != null) { mPadding = new Rect(orig.mPadding); } @@ -625,7 +627,8 @@ public class ShapeDrawable extends Drawable { * after inflating or applying a theme. */ private void updateLocalState() { - mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, mShapeState.mTint, + mShapeState.mBlendMode); } /** diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 7325b857f02c..43772ec20cf3 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -24,11 +24,13 @@ import android.content.res.GradientColor; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.PixelFormat; -import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Shader; @@ -324,6 +326,8 @@ public class VectorDrawable extends Drawable { @UnsupportedAppUsage private PorterDuffColorFilter mTintFilter; + + private BlendModeColorFilter mBlendModeColorFilter; private ColorFilter mColorFilter; private boolean mMutated; @@ -371,7 +375,7 @@ public class VectorDrawable extends Drawable { mDpiScaledDirty = true; } - mTintFilter = updateTintFilter(mTintFilter, mVectorState.mTint, mVectorState.mTintMode); + updateColorFilters(mVectorState.mBlendMode, mVectorState.mTint); } @Override @@ -413,7 +417,8 @@ public class VectorDrawable extends Drawable { } // Color filters always override tint filters. - final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter); + final ColorFilter colorFilter = (mColorFilter == null ? mBlendModeColorFilter : + mColorFilter); final long colorFilterNativeInstance = colorFilter == null ? 0 : colorFilter.getNativeInstance(); boolean canReuseCache = mVectorState.canReuseCache(); @@ -475,17 +480,19 @@ public class VectorDrawable extends Drawable { final VectorDrawableState state = mVectorState; if (state.mTint != tint) { state.mTint = tint; - mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode); + + updateColorFilters(mVectorState.mBlendMode, tint); invalidateSelf(); } } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull BlendMode blendMode) { final VectorDrawableState state = mVectorState; - if (state.mTintMode != tintMode) { - state.mTintMode = tintMode; - mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode); + if (state.mBlendMode != blendMode) { + state.mBlendMode = blendMode; + + updateColorFilters(state.mBlendMode, state.mTint); invalidateSelf(); } } @@ -515,14 +522,22 @@ public class VectorDrawable extends Drawable { changed = true; state.mCacheDirty = true; } - if (state.mTint != null && state.mTintMode != null) { - mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); + if (state.mTint != null && state.mBlendMode != null) { + BlendMode blendMode = state.mBlendMode; + ColorStateList tint = state.mTint; + updateColorFilters(blendMode, tint); changed = true; } return changed; } + private void updateColorFilters(@Nullable BlendMode blendMode, ColorStateList tint) { + PorterDuff.Mode mode = BlendMode.blendModeToPorterDuffMode(blendMode); + mTintFilter = updateTintFilter(mTintFilter, tint, mode); + mBlendModeColorFilter = updateBlendModeFilter(mBlendModeColorFilter, tint, blendMode); + } + @Override public int getOpacity() { // We can't tell whether the drawable is fully opaque unless we examine all the pixels, @@ -737,7 +752,7 @@ public class VectorDrawable extends Drawable { final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); + state.mBlendMode = Drawable.parseBlendMode(tintMode, BlendMode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint); @@ -911,7 +926,7 @@ public class VectorDrawable extends Drawable { int[] mThemeAttrs; @Config int mChangingConfigurations; ColorStateList mTint = null; - Mode mTintMode = DEFAULT_TINT_MODE; + BlendMode mBlendMode = DEFAULT_BLEND_MODE; boolean mAutoMirrored; int mBaseWidth = 0; @@ -929,7 +944,7 @@ public class VectorDrawable extends Drawable { // Fields for cache int[] mCachedThemeAttrs; ColorStateList mCachedTint; - Mode mCachedTintMode; + BlendMode mCachedBlendMode; boolean mCachedAutoMirrored; boolean mCacheDirty; @@ -970,7 +985,7 @@ public class VectorDrawable extends Drawable { mThemeAttrs = copy.mThemeAttrs; mChangingConfigurations = copy.mChangingConfigurations; mTint = copy.mTint; - mTintMode = copy.mTintMode; + mBlendMode = copy.mBlendMode; mAutoMirrored = copy.mAutoMirrored; mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); createNativeTreeFromCopy(copy, mRootGroup); @@ -1026,7 +1041,7 @@ public class VectorDrawable extends Drawable { if (!mCacheDirty && mCachedThemeAttrs == mThemeAttrs && mCachedTint == mTint - && mCachedTintMode == mTintMode + && mCachedBlendMode == mBlendMode && mCachedAutoMirrored == mAutoMirrored) { return true; } @@ -1039,7 +1054,7 @@ public class VectorDrawable extends Drawable { // likely hit cache miss more, but practically not much difference. mCachedThemeAttrs = mThemeAttrs; mCachedTint = mTint; - mCachedTintMode = mTintMode; + mCachedBlendMode = mBlendMode; mCachedAutoMirrored = mAutoMirrored; mCacheDirty = false; } diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java index 1836f009f86b..bd1a49205fd5 100644 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -435,8 +435,9 @@ public final class PdfRenderer implements AutoCloseable { final long transformPtr = transform.native_instance; synchronized (sPdfiumLock) { - nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft, - contentTop, contentRight, contentBottom, transformPtr, renderMode); + nativeRenderPage(mNativeDocument, mNativePage, destination.getNativeInstance(), + contentLeft, contentTop, contentRight, contentBottom, transformPtr, + renderMode); } } @@ -487,7 +488,7 @@ public final class PdfRenderer implements AutoCloseable { private static native void nativeClose(long documentPtr); private static native int nativeGetPageCount(long documentPtr); private static native boolean nativeScaleForPrinting(long documentPtr); - private static native void nativeRenderPage(long documentPtr, long pagePtr, Bitmap dest, + private static native void nativeRenderPage(long documentPtr, long pagePtr, long bitmapHandle, int clipLeft, int clipTop, int clipRight, int clipBottom, long transformPtr, int renderMode); private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex, diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index 8f7e8142e735..9bb6031b76ac 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -349,8 +349,7 @@ static SkBitmap makeHwCompatible(const FormatInfo& format, const SkBitmap& sourc } else { SkBitmap bitmap; const SkImageInfo& info = source.info(); - bitmap.allocPixels( - SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType(), nullptr)); + bitmap.allocPixels(info.makeColorType(kN32_SkColorType)); SkCanvas canvas(bitmap); canvas.drawColor(0); @@ -416,7 +415,9 @@ void HardwareBitmapUploader::initialize() { } void HardwareBitmapUploader::terminate() { - sUploader->destroy(); + if (sUploader) { + sUploader->destroy(); + } } } // namespace android::uirenderer diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 93dc6fa9bf93..97bc4042b86f 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -93,10 +93,10 @@ interface ILocationManager ProviderProperties getProviderProperties(String provider); boolean isProviderPackage(String packageName); - void setLocationControllerExtraPackage(String packageName); - String getLocationControllerExtraPackage(); - void setLocationControllerExtraPackageEnabled(boolean enabled); - boolean isLocationControllerExtraPackageEnabled(); + void setExtraLocationControllerPackage(String packageName); + String getExtraLocationControllerPackage(); + void setExtraLocationControllerPackageEnabled(boolean enabled); + boolean isExtraLocationControllerPackageEnabled(); boolean isProviderEnabledForUser(String provider, int userId); boolean isLocationEnabledForUser(int userId); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index edf304ca69cd..af60e3c67288 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -2328,9 +2328,27 @@ public class LocationManager { */ @SystemApi @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) - public void setLocationControllerExtraPackage(@NonNull String packageName) { + public void setExtraLocationControllerPackage(@Nullable String packageName) { try { - mService.setLocationControllerExtraPackage(packageName); + mService.setExtraLocationControllerPackage(packageName); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Set the extra location controller package for location services on the device. + * + * @removed + * @deprecated Use {@link #setExtraLocationControllerPackage} instead. + * @hide + */ + @Deprecated + @SystemApi + @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) + public void setLocationControllerExtraPackage(String packageName) { + try { + mService.setExtraLocationControllerPackage(packageName); } catch (RemoteException e) { e.rethrowFromSystemServer(); } @@ -2342,9 +2360,9 @@ public class LocationManager { * @hide */ @SystemApi - public @Nullable String getLocationControllerExtraPackage() { + public @Nullable String getExtraLocationControllerPackage() { try { - return mService.getLocationControllerExtraPackage(); + return mService.getExtraLocationControllerPackage(); } catch (RemoteException e) { e.rethrowFromSystemServer(); return null; @@ -2354,13 +2372,31 @@ public class LocationManager { /** * Set whether the extra location controller package is currently enabled on the device. * + * @removed + * @deprecated Use {@link #setExtraLocationControllerPackageEnabled} instead. * @hide */ @SystemApi + @Deprecated @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean enabled) { try { - mService.setLocationControllerExtraPackageEnabled(enabled); + mService.setExtraLocationControllerPackageEnabled(enabled); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Set whether the extra location controller package is currently enabled on the device. + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) + public void setExtraLocationControllerPackageEnabled(boolean enabled) { + try { + mService.setExtraLocationControllerPackageEnabled(enabled); } catch (RemoteException e) { e.rethrowFromSystemServer(); } @@ -2372,9 +2408,9 @@ public class LocationManager { * @hide */ @SystemApi - public boolean isLocationControllerExtraPackageEnabled() { + public boolean isExtraLocationControllerPackageEnabled() { try { - return mService.isLocationControllerExtraPackageEnabled(); + return mService.isExtraLocationControllerPackageEnabled(); } catch (RemoteException e) { e.rethrowFromSystemServer(); return false; diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index c2f29bc6e3bc..efb7f4698797 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -370,9 +370,10 @@ public final class AudioAttributes implements Parcelable { /** * @hide - * Flag specifying that the audio shall not be captured by other apps. + * Flag specifying that the audio shall not be captured by third-party apps + * with a MediaProjection. */ - public static final int FLAG_NO_CAPTURE = 0x1 << 10; + public static final int FLAG_NO_MEDIA_PROJECTION = 0x1 << 10; /** * @hide @@ -380,12 +381,63 @@ public final class AudioAttributes implements Parcelable { */ public static final int FLAG_MUTE_HAPTIC = 0x1 << 11; + /** + * @hide + * Flag specifying that the audio shall not be captured by any apps, not even system apps. + */ + public static final int FLAG_NO_SYSTEM_CAPTURE = 0x1 << 12; + private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO | FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY | FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER | FLAG_MUTE_HAPTIC; private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED | FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY; + /** + * Indicates that the audio may be captured by any app. + * + * For privacy, the following usages can not be recorded: VOICE_COMMUNICATION*, + * USAGE_NOTIFICATION*, USAGE_ASSISTANCE* and USAGE_ASSISTANT. + * + * On {@link android.os.Build.VERSION_CODES#Q}, this means only {@link #USAGE_UNKNOWN}, + * {@link #USAGE_MEDIA} and {@link #USAGE_GAME} may be captured. + * + * See {@link android.media.projection.MediaProjection} and + * {@link Builder#setAllowedCapturePolicy}. + */ + public static final int ALLOW_CAPTURE_BY_ALL = 1; + /** + * Indicates that the audio may only be captured by system apps. + * + * System apps can capture for many purposes like accessibility, user guidance... + * but abide to the following restrictions: + * - the audio can not leave the device + * - the audio can not be passed to a third party app + * - the audio can not be recorded at a higher quality then 16kHz 16bit mono + * + * See {@link Builder#setAllowedCapturePolicy}. + */ + public static final int ALLOW_CAPTURE_BY_SYSTEM = 2; + /** + * Indicates that the audio is not to be recorded by any app, even if it is a system app. + * + * It is encouraged to use {@link #ALLOW_CAPTURE_BY_SYSTEM} instead of this value as system apps + * provide significant and useful features for the user (such as live captioning + * and accessibility). + * + * See {@link Builder#setAllowedCapturePolicy}. + */ + public static final int ALLOW_CAPTURE_BY_NONE = 3; + + /** @hide */ + @IntDef({ + ALLOW_CAPTURE_BY_ALL, + ALLOW_CAPTURE_BY_SYSTEM, + ALLOW_CAPTURE_BY_NONE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CapturePolicy {} + @UnsupportedAppUsage private int mUsage = USAGE_UNKNOWN; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @@ -593,10 +645,10 @@ public final class AudioAttributes implements Parcelable { case USAGE_GAME: case USAGE_VIRTUAL_SOURCE: case USAGE_ASSISTANT: - mUsage = usage; - break; + mUsage = usage; + break; default: - mUsage = USAGE_UNKNOWN; + mUsage = USAGE_UNKNOWN; } return this; } @@ -642,17 +694,34 @@ public final class AudioAttributes implements Parcelable { } /** - * Specifying if audio shall or shall not be captured by other apps. - * By default, capture is allowed. - * @param allowCapture false to forbid capture of the audio by any apps, - * true to allow apps to capture the audio + * Specifying if audio may or may not be captured by other apps or the system. + * + * The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}. + * + * Note that an application can also set its global policy, in which case the most + * restrictive policy is always applied. + * + * @param capturePolicy one of + * {@link #ALLOW_CAPTURE_BY_ALL}, + * {@link #ALLOW_CAPTURE_BY_SYSTEM}, + * {@link #ALLOW_CAPTURE_BY_NONE}. * @return the same Builder instance + * @throws IllegalArgumentException if the argument is not a valid value. */ - public @NonNull Builder setAllowCapture(boolean allowCapture) { - if (allowCapture) { - mFlags &= ~FLAG_NO_CAPTURE; - } else { - mFlags |= FLAG_NO_CAPTURE; + public @NonNull Builder setAllowedCapturePolicy(@CapturePolicy int capturePolicy) { + switch (capturePolicy) { + case ALLOW_CAPTURE_BY_NONE: + mFlags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE; + break; + case ALLOW_CAPTURE_BY_SYSTEM: + mFlags |= FLAG_NO_MEDIA_PROJECTION; + mFlags &= ~FLAG_NO_SYSTEM_CAPTURE; + break; + case ALLOW_CAPTURE_BY_ALL: + mFlags &= ~FLAG_NO_SYSTEM_CAPTURE & ~FLAG_NO_MEDIA_PROJECTION; + break; + default: + throw new IllegalArgumentException("Unknown allow playback capture policy"); } return this; } diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java index 4aa0b903bcdf..9ee6f8740568 100644 --- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java +++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java @@ -28,7 +28,7 @@ import com.android.internal.util.Preconditions; /** * Configuration for capturing audio played by other apps. * - * For privacy and copyright reason, only the following audio can be captured: + * Only the following audio can be captured: * - usage MUST be UNKNOWN or GAME or MEDIA. All other usages CAN NOT be capturable. * - audio attributes MUST NOT have the FLAG_NO_CAPTURE * - played by apps that MUST be in the same user profile as the capturing app diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index a22c8d0a8457..4d63cc8825e3 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -1060,7 +1060,7 @@ public final class MediaFormat { * that no B frames are allowed. Note that non-zero value does not guarantee * B frames; it's up to the encoder to decide. */ - public static final String KEY_MAX_BFRAMES = "max-bframes"; + public static final String KEY_MAX_B_FRAMES = "max-bframes"; /* package private */ MediaFormat(@NonNull Map<String, Object> map) { mMap = map; diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index 6fd6298adb7d..09f17c099609 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -142,7 +142,8 @@ public class AudioMix { return mFormat; } - AudioMixingRule getRule() { + /** @hide */ + public AudioMixingRule getRule() { return mRule; } diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java index d41f416f3d51..947b06cdf6b2 100644 --- a/media/java/android/media/audiopolicy/AudioMixingRule.java +++ b/media/java/android/media/audiopolicy/AudioMixingRule.java @@ -16,6 +16,7 @@ package android.media.audiopolicy; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.media.AudioAttributes; @@ -43,9 +44,11 @@ import java.util.Objects; @SystemApi public class AudioMixingRule { - private AudioMixingRule(int mixType, ArrayList<AudioMixMatchCriterion> criteria) { + private AudioMixingRule(int mixType, ArrayList<AudioMixMatchCriterion> criteria, + boolean allowPrivilegedPlaybackCapture) { mCriteria = criteria; mTargetMixType = mixType; + mAllowPrivilegedPlaybackCapture = allowPrivilegedPlaybackCapture; } /** @@ -161,6 +164,13 @@ public class AudioMixingRule { @UnsupportedAppUsage private final ArrayList<AudioMixMatchCriterion> mCriteria; ArrayList<AudioMixMatchCriterion> getCriteria() { return mCriteria; } + @UnsupportedAppUsage + private boolean mAllowPrivilegedPlaybackCapture = false; + + /** @hide */ + public boolean allowPrivilegedPlaybackCapture() { + return mAllowPrivilegedPlaybackCapture; + } /** @hide */ @Override @@ -170,12 +180,13 @@ public class AudioMixingRule { final AudioMixingRule that = (AudioMixingRule) o; return (this.mTargetMixType == that.mTargetMixType) - && (areCriteriaEquivalent(this.mCriteria, that.mCriteria)); + && (areCriteriaEquivalent(this.mCriteria, that.mCriteria) + && this.mAllowPrivilegedPlaybackCapture == that.mAllowPrivilegedPlaybackCapture); } @Override public int hashCode() { - return Objects.hash(mTargetMixType, mCriteria); + return Objects.hash(mTargetMixType, mCriteria, mAllowPrivilegedPlaybackCapture); } private static boolean isValidSystemApiRule(int rule) { @@ -239,6 +250,7 @@ public class AudioMixingRule { public static class Builder { private ArrayList<AudioMixMatchCriterion> mCriteria; private int mTargetMixType = AudioMix.MIX_TYPE_INVALID; + private boolean mAllowPrivilegedPlaybackCapture = false; /** * Constructs a new Builder with no rules. @@ -343,6 +355,21 @@ public class AudioMixingRule { } /** + * Set if the audio of app that opted out of audio playback capture should be captured. + * + * The permission {@link CAPTURE_AUDIO_OUTPUT} or {@link CAPTURE_MEDIA_OUTPUT} is needed + * to ignore the opt-out. + * + * Only affects LOOPBACK|RENDER mix. + * + * @return the same Builder instance. + */ + public @NonNull Builder allowPrivilegedPlaybackCapture(boolean allow) { + mAllowPrivilegedPlaybackCapture = allow; + return this; + } + + /** * Add or exclude a rule for the selection of which streams are mixed together. * Does error checking on the parameters. * @param rule @@ -507,7 +534,7 @@ public class AudioMixingRule { * @return a new {@link AudioMixingRule} object */ public AudioMixingRule build() { - return new AudioMixingRule(mTargetMixType, mCriteria); + return new AudioMixingRule(mTargetMixType, mCriteria, mAllowPrivilegedPlaybackCapture); } } } diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java index a6e63c7841d0..c4ba0c1fc835 100644 --- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java +++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java @@ -96,6 +96,8 @@ public class AudioPolicyConfig implements Parcelable { dest.writeInt(mix.getFormat().getSampleRate()); dest.writeInt(mix.getFormat().getEncoding()); dest.writeInt(mix.getFormat().getChannelMask()); + // write opt-out respect + dest.writeBoolean(mix.getRule().allowPrivilegedPlaybackCapture()); // write mix rules final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria(); dest.writeInt(criteria.size()); @@ -124,9 +126,12 @@ public class AudioPolicyConfig implements Parcelable { final AudioFormat format = new AudioFormat.Builder().setSampleRate(sampleRate) .setChannelMask(channelMask).setEncoding(encoding).build(); mixBuilder.setFormat(format); + + AudioMixingRule.Builder ruleBuilder = new AudioMixingRule.Builder(); + // write opt-out respect + ruleBuilder.allowPrivilegedPlaybackCapture(in.readBoolean()); // read mix rules int nbRules = in.readInt(); - AudioMixingRule.Builder ruleBuilder = new AudioMixingRule.Builder(); for (int j = 0 ; j < nbRules ; j++) { // read the matching rules ruleBuilder.addRuleFromParcel(in); @@ -161,7 +166,9 @@ public class AudioPolicyConfig implements Parcelable { textDump += " rate=" + mix.getFormat().getSampleRate() + "Hz\n"; textDump += " encoding=" + mix.getFormat().getEncoding() + "\n"; textDump += " channels=0x"; - textDump += Integer.toHexString(mix.getFormat().getChannelMask()).toUpperCase() +"\n"; + textDump += Integer.toHexString(mix.getFormat().getChannelMask()).toUpperCase() + "\n"; + textDump += " ignore playback capture opt out=" + + mix.getRule().allowPrivilegedPlaybackCapture() + "\n"; // write mix rules final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria(); for (AudioMixMatchCriterion criterion : criteria) { diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java index d0973359058a..ca8d5ac52021 100644 --- a/opengl/java/android/opengl/GLUtils.java +++ b/opengl/java/android/opengl/GLUtils.java @@ -44,7 +44,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - int result = native_getInternalFormat(bitmap); + int result = native_getInternalFormat(bitmap.getNativeInstance()); if (result < 0) { throw new IllegalArgumentException("Unknown internalformat"); } @@ -66,7 +66,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - int result = native_getType(bitmap); + int result = native_getType(bitmap.getNativeInstance()); if (result < 0) { throw new IllegalArgumentException("Unknown type"); } @@ -103,7 +103,8 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - if (native_texImage2D(target, level, internalformat, bitmap, -1, border)!=0) { + if (native_texImage2D(target, level, internalformat, bitmap.getNativeInstance(), -1, + border) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -129,7 +130,8 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - if (native_texImage2D(target, level, internalformat, bitmap, type, border)!=0) { + if (native_texImage2D(target, level, internalformat, bitmap.getNativeInstance(), type, + border) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -151,7 +153,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - if (native_texImage2D(target, level, -1, bitmap, -1, border)!=0) { + if (native_texImage2D(target, level, -1, bitmap.getNativeInstance(), -1, border) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -187,7 +189,8 @@ public final class GLUtils { throw new IllegalArgumentException("bitmap is recycled"); } int type = getType(bitmap); - if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, -1, type)!=0) { + if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap.getNativeInstance(), -1, + type) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -211,7 +214,8 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, format, type)!=0) { + if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap.getNativeInstance(), + format, type) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -261,10 +265,10 @@ public final class GLUtils { } } - native private static int native_getInternalFormat(Bitmap bitmap); - native private static int native_getType(Bitmap bitmap); + native private static int native_getInternalFormat(long bitmapHandle); + native private static int native_getType(long bitmapHandle); native private static int native_texImage2D(int target, int level, int internalformat, - Bitmap bitmap, int type, int border); + long bitmapHandle, int type, int border); native private static int native_texSubImage2D(int target, int level, int xoffset, int yoffset, - Bitmap bitmap, int format, int type); + long bitmapHandle, int format, int type); } diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp index 52534a8fbae7..0bd5c5f59133 100644 --- a/packages/NetworkStack/Android.bp +++ b/packages/NetworkStack/Android.bp @@ -49,6 +49,9 @@ java_defaults { // Resources already included in NetworkStackBase resource_dirs: [], jarjar_rules: "jarjar-rules-shared.txt", + optimize: { + proguard_flags_files: ["proguard.flags"], + }, // The permission configuration *must* be included to ensure security of the device required: ["NetworkStackPermissionStub"], } diff --git a/packages/NetworkStack/proguard.flags b/packages/NetworkStack/proguard.flags new file mode 100644 index 000000000000..c60f6c338d83 --- /dev/null +++ b/packages/NetworkStack/proguard.flags @@ -0,0 +1,9 @@ +-keepclassmembers class android.net.ip.IpClient { + static final int CMD_*; + static final int EVENT_*; +} + +-keepclassmembers class android.net.dhcp.DhcpClient { + static final int CMD_*; + static final int EVENT_*; +} diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java index c6dd0117477b..79d6a554e251 100644 --- a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java @@ -126,6 +126,7 @@ public class DhcpClient extends StateMachine { // DhcpClient uses IpClient's handler. private static final int PUBLIC_BASE = IpClient.DHCPCLIENT_CMD_BASE; + // Below constants are picked up by MessageUtils and exempt from ProGuard optimization. /* Commands from controller to start/stop DHCP */ public static final int CMD_START_DHCP = PUBLIC_BASE + 1; public static final int CMD_STOP_DHCP = PUBLIC_BASE + 2; diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java index 346ac68407de..7a06af41f951 100644 --- a/packages/NetworkStack/src/android/net/ip/IpClient.java +++ b/packages/NetworkStack/src/android/net/ip/IpClient.java @@ -282,6 +282,7 @@ public class IpClient extends StateMachine { public static final String DUMP_ARG_CONFIRM = "confirm"; + // Below constants are picked up by MessageUtils and exempt from ProGuard optimization. private static final int CMD_TERMINATE_AFTER_STOP = 1; private static final int CMD_STOP = 2; private static final int CMD_START = 3; diff --git a/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_chart.xml b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_chart.xml index 814246fc2698..9b3d1dfb6568 100644 --- a/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_chart.xml +++ b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_chart.xml @@ -20,8 +20,8 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp" android:gravity="center" android:orientation="vertical"> @@ -47,19 +47,19 @@ <com.android.settingslib.widget.BarView android:id="@+id/bar_view1" style="@style/BarViewStyle" - settings:barColor="#FA7B17"/> + settings:barColor="#A142F4"/> <com.android.settingslib.widget.BarView android:id="@+id/bar_view2" style="@style/BarViewStyle" - settings:barColor="#F439A0"/> + settings:barColor="#24C1E0"/> <com.android.settingslib.widget.BarView android:id="@+id/bar_view3" style="@style/BarViewStyle" - settings:barColor="#A142F4"/> + settings:barColor="#4285F4"/> <com.android.settingslib.widget.BarView android:id="@+id/bar_view4" style="@style/BarViewStyle" - settings:barColor="#24C1E0"/> + settings:barColor="#009688"/> </LinearLayout> <Button diff --git a/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml index 4bc68b333cc6..093c5debaab7 100644 --- a/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml +++ b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml @@ -32,15 +32,13 @@ android:layout_width="@dimen/settings_bar_view_icon_size" android:layout_height="@dimen/settings_bar_view_icon_size" android:scaleType="fitCenter" - android:layout_marginTop="12dp" - android:layout_marginBottom="12dp"/> + android:layout_marginTop="12dp"/> <TextView android:id="@+id/bar_title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dp" - android:layout_marginBottom="2dp" + android:layout_marginTop="12dp" android:singleLine="true" android:ellipsize="marquee" android:textAppearance="@style/BarChart.Text.Title"/> @@ -49,6 +47,7 @@ android:id="@+id/bar_summary" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginTop="4dp" android:layout_marginBottom="12dp" android:singleLine="true" android:ellipsize="marquee" diff --git a/packages/SettingsLib/BarChartPreference/res/values/styles.xml b/packages/SettingsLib/BarChartPreference/res/values/styles.xml index 558792855628..094f8aa79ba3 100644 --- a/packages/SettingsLib/BarChartPreference/res/values/styles.xml +++ b/packages/SettingsLib/BarChartPreference/res/values/styles.xml @@ -35,12 +35,12 @@ </style> <style name="BarChart.Text.Title"> - <item name="android:textSize">22sp</item> + <item name="android:textSize">14sp</item> </style> <style name="BarChart.Text.Summary" - parent="@android:style/TextAppearance.Material.Body1"> + parent="@*android:style/TextAppearance.DeviceDefault.Body1"> <item name="android:textColor">?android:attr/textColorSecondary</item> - <item name="android:textSize">14sp</item> + <item name="android:textSize">12sp</item> </style> </resources>
\ No newline at end of file diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java index 03dfd3ee6080..fccb7196b12f 100644 --- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java +++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java @@ -71,8 +71,7 @@ public class BarView extends LinearLayout { //Set height of bar view mBarView.getLayoutParams().height = barViewInfo.getNormalizedHeight(); mIcon.setImageDrawable(barViewInfo.getIcon()); - // For now, we use the bar number as title. - mBarTitle.setText(Integer.toString(barViewInfo.getHeight())); + mBarTitle.setText(barViewInfo.getTitle()); mBarSummary.setText(barViewInfo.getSummary()); mIcon.setContentDescription(barViewInfo.getContentDescription()); } diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java index 1ef36a2a75b7..922337a92f18 100644 --- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java +++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java @@ -21,7 +21,6 @@ import android.view.View; import androidx.annotation.IntRange; import androidx.annotation.Nullable; -import androidx.annotation.StringRes; import java.util.Comparator; @@ -32,8 +31,8 @@ public class BarViewInfo implements Comparable<BarViewInfo> { private final Drawable mIcon; private View.OnClickListener mClickListener; - @StringRes - private int mSummary; + private CharSequence mTitle; + private CharSequence mSummary; private @Nullable CharSequence mContentDescription; // A number indicates this bar's height. The larger number shows a higher bar view. private int mHeight; @@ -45,13 +44,16 @@ public class BarViewInfo implements Comparable<BarViewInfo> { * * @param icon The icon of bar view. * @param barHeight The height of bar view. Larger number shows a higher bar view. - * @param summary The string resource id for summary. + * @param title The string for title. If this is null, use the height of the bar. + * @param summary The string for summary. * @param contentDescription Optional text that briefly describes the contents of the icon. */ - public BarViewInfo(Drawable icon, @IntRange(from = 0) int barHeight, @StringRes int summary, + public BarViewInfo(Drawable icon, @IntRange(from = 0) int barHeight, + @Nullable CharSequence title, CharSequence summary, @Nullable CharSequence contentDescription) { mIcon = icon; mHeight = barHeight; + mTitle = title; mSummary = summary; mContentDescription = contentDescription; } @@ -74,8 +76,12 @@ public class BarViewInfo implements Comparable<BarViewInfo> { mHeight = height; } - void setSummary(@StringRes int resId) { - mSummary = resId; + void setTitle(CharSequence title) { + mTitle = title; + } + + void setSummary(CharSequence summary) { + mSummary = summary; } Drawable getIcon() { @@ -90,8 +96,12 @@ public class BarViewInfo implements Comparable<BarViewInfo> { return mClickListener; } - @StringRes - int getSummary() { + @Nullable + CharSequence getTitle() { + return mTitle; + } + + CharSequence getSummary() { return mSummary; } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java index c1c5fa932b0c..5d2a0d1df96c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java @@ -16,9 +16,10 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; - import android.util.LongSparseLongArray; + import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -83,6 +84,7 @@ public class RecentLocationAccessesTest { } @Test + @Ignore public void testGetAppList_shouldFilterRecentAccesses() { List<RecentLocationAccesses.Access> requests = mRecentLocationAccesses.getAppList(); // Only two of the apps have requested location within 15 min. @@ -95,6 +97,7 @@ public class RecentLocationAccessesTest { } @Test + @Ignore public void testGetAppList_shouldNotShowAndroidOS() throws NameNotFoundException { // Add android OS to the list of apps. PackageOps androidSystemPackageOps = diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartInfoTest.java index 2b272485dff3..7faac7a90664 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartInfoTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartInfoTest.java @@ -39,6 +39,8 @@ public class BarChartInfoTest { private final int mDetails = 0x22222222; @StringRes private final int mEmptyText = 0x33333333; + private final CharSequence mTitleStr = "title"; + private final CharSequence mSummaryStr = "summary"; private final View.OnClickListener mClickListener = v -> { }; @@ -72,7 +74,8 @@ public class BarChartInfoTest { final BarViewInfo barViewInfo = new BarViewInfo( null /* icon */, 50, - mTitle, + mTitleStr, + mSummaryStr, null); final BarChartInfo mBarChartInfo = new BarChartInfo.Builder() @@ -92,7 +95,8 @@ public class BarChartInfoTest { final BarViewInfo barViewInfo = new BarViewInfo( null /* icon */, 50, - mTitle, + mTitleStr, + mSummaryStr, null); final BarChartInfo mBarChartInfo = new BarChartInfo.Builder() .setTitle(mTitle) @@ -115,7 +119,8 @@ public class BarChartInfoTest { final BarViewInfo barViewInfo = new BarViewInfo( null /* icon */, 50, - mTitle, + mTitleStr, + mSummaryStr, null); new BarChartInfo.Builder() .setTitle(mTitle) diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java index 266554be57d3..567d90fa8916 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java @@ -39,6 +39,8 @@ public class BarChartPreferenceTest { @Rule public final ExpectedException thrown = ExpectedException.none(); + private final CharSequence mTitleStr = "title"; + private final CharSequence mSummaryStr = "summary"; private Context mContext; private View mBarChartView; @@ -114,7 +116,9 @@ public class BarChartPreferenceTest { .setTitle(R.string.debug_app) .setDetails(R.string.debug_app) .addBarViewInfo( - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null)) + new BarViewInfo(mIcon, 10, null /* title */, + mContext.getText(R.string.debug_app) /* summary */, + null /* contentDescription */)) .build(); mPreference.initializeBarChart(barChartInfo); @@ -130,7 +134,9 @@ public class BarChartPreferenceTest { final BarChartInfo barChartInfo = new BarChartInfo.Builder() .setTitle(R.string.debug_app) .addBarViewInfo( - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null)) + new BarViewInfo(mIcon, 10, null /* title */, + mContext.getText(R.string.debug_app) /* summary */, + null /* contentDescription */)) .build(); mPreference.initializeBarChart(barChartInfo); @@ -147,7 +153,9 @@ public class BarChartPreferenceTest { .setDetailsOnClickListener(v -> { }) .addBarViewInfo( - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null)) + new BarViewInfo(mIcon, 10, null /* title */, + mContext.getText(R.string.debug_app) /* summary */, + null /* contentDescription */)) .build(); mPreference.initializeBarChart(barChartInfo); @@ -160,7 +168,7 @@ public class BarChartPreferenceTest { @Test public void setBarViewInfos_oneBarViewInfoSet_shouldShowOneBarView() { final BarViewInfo[] barViewsInfo = new BarViewInfo[]{ - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null) + new BarViewInfo(mIcon, 10, mTitleStr, mSummaryStr, null /* contentDescription */) }; mPreference.initializeBarChart(mBarChartInfo); @@ -168,7 +176,7 @@ public class BarChartPreferenceTest { mPreference.onBindViewHolder(mHolder); assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView1.getTitle()).isEqualTo("10"); + assertThat(mBarView1.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView2.getVisibility()).isEqualTo(View.GONE); assertThat(mBarView3.getVisibility()).isEqualTo(View.GONE); @@ -178,8 +186,8 @@ public class BarChartPreferenceTest { @Test public void setBarViewInfos_twoBarViewInfosSet_shouldShowTwoBarViews() { final BarViewInfo[] barViewsInfo = new BarViewInfo[]{ - new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null) + new BarViewInfo(mIcon, 20, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 10, mTitleStr, mSummaryStr, null /* contentDescription */), }; mPreference.initializeBarChart(mBarChartInfo); @@ -187,9 +195,9 @@ public class BarChartPreferenceTest { mPreference.onBindViewHolder(mHolder); assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView1.getTitle()).isEqualTo("20"); + assertThat(mBarView1.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView2.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView2.getTitle()).isEqualTo("10"); + assertThat(mBarView2.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView3.getVisibility()).isEqualTo(View.GONE); assertThat(mBarView4.getVisibility()).isEqualTo(View.GONE); @@ -198,9 +206,9 @@ public class BarChartPreferenceTest { @Test public void setBarViewInfos_threeBarViewInfosSet_shouldShowThreeBarViews() { final BarViewInfo[] barViewsInfo = new BarViewInfo[]{ - new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app, null) + new BarViewInfo(mIcon, 20, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 10, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 5, mTitleStr, mSummaryStr, null /* contentDescription */) }; mPreference.initializeBarChart(mBarChartInfo); @@ -208,11 +216,11 @@ public class BarChartPreferenceTest { mPreference.onBindViewHolder(mHolder); assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView1.getTitle()).isEqualTo("20"); + assertThat(mBarView1.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView2.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView2.getTitle()).isEqualTo("10"); + assertThat(mBarView2.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView3.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView3.getTitle()).isEqualTo("5"); + assertThat(mBarView3.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView4.getVisibility()).isEqualTo(View.GONE); } @@ -220,10 +228,10 @@ public class BarChartPreferenceTest { @Test public void setBarViewInfos_fourBarViewInfosSet_shouldShowFourBarViews() { final BarViewInfo[] barViewsInfo = new BarViewInfo[]{ - new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 2 /* barNumber */, R.string.debug_app, null), + new BarViewInfo(mIcon, 20, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 10, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 5, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 2, mTitleStr, mSummaryStr, null /* contentDescription */) }; mPreference.initializeBarChart(mBarChartInfo); @@ -231,13 +239,13 @@ public class BarChartPreferenceTest { mPreference.onBindViewHolder(mHolder); assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView1.getTitle()).isEqualTo("20"); + assertThat(mBarView1.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView2.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView2.getTitle()).isEqualTo("10"); + assertThat(mBarView2.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView3.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView3.getTitle()).isEqualTo("5"); + assertThat(mBarView3.getTitle()).isEqualTo(mTitleStr); assertThat(mBarView4.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView4.getTitle()).isEqualTo("2"); + assertThat(mBarView4.getTitle()).isEqualTo(mTitleStr); } @Test @@ -245,11 +253,11 @@ public class BarChartPreferenceTest { thrown.expect(IllegalStateException.class); final BarViewInfo[] barViewsInfo = new BarViewInfo[]{ - new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 50 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 70 /* barNumber */, R.string.debug_app, null), + new BarViewInfo(mIcon, 30, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 50, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 5, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 10, mTitleStr, mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 70, mTitleStr, mSummaryStr, null /* contentDescription */), }; mPreference.setBarViewInfos(barViewsInfo); @@ -258,10 +266,10 @@ public class BarChartPreferenceTest { @Test public void setBarViewInfos_barViewInfosSet_shouldBeSortedInDescending() { final BarViewInfo[] barViewsInfo = new BarViewInfo[]{ - new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 50 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app, null), - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null), + new BarViewInfo(mIcon, 30, "30", mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 50, "50", mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 5, "5", mSummaryStr, null /* contentDescription */), + new BarViewInfo(mIcon, 10, "10", mSummaryStr, null /* contentDescription */) }; mPreference.initializeBarChart(mBarChartInfo); @@ -281,7 +289,7 @@ public class BarChartPreferenceTest { @Test public void setBarViewInfos_validBarViewSummarySet_barViewShouldShowSummary() { final BarViewInfo[] barViewsInfo = new BarViewInfo[]{ - new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null), + new BarViewInfo(mIcon, 10, mTitleStr, mSummaryStr, null /* contentDescription */) }; mPreference.initializeBarChart(mBarChartInfo); @@ -289,13 +297,27 @@ public class BarChartPreferenceTest { mPreference.onBindViewHolder(mHolder); assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mBarView1.getSummary()).isEqualTo(mContext.getText(R.string.debug_app)); + assertThat(mBarView1.getSummary()).isEqualTo(mSummaryStr); + } + + @Test + public void setBarViewInfos_validBarViewTitleSet_barViewShouldShowTitle() { + final BarViewInfo[] barViewsInfo = new BarViewInfo[]{ + new BarViewInfo(mIcon, 10, mTitleStr, mSummaryStr, null /* contentDescription */) + }; + + mPreference.initializeBarChart(mBarChartInfo); + mPreference.setBarViewInfos(barViewsInfo); + mPreference.onBindViewHolder(mHolder); + + assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mBarView1.getTitle()).isEqualTo(mTitleStr); } @Test public void setBarViewInfos_clickListenerForBarViewSet_barViewShouldHaveClickListener() { - final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app, - null); + final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30, mTitleStr, mSummaryStr, + null /* contentDescription */); viewInfo.setClickListener(v -> { }); final BarViewInfo[] barViewsInfo = new BarViewInfo[]{viewInfo}; @@ -310,8 +332,8 @@ public class BarChartPreferenceTest { @Test public void onBindViewHolder_loadingStateIsTrue_shouldHideAllViews() { - final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app, - null); + final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30, mTitleStr, mSummaryStr, + null /* contentDescription */); viewInfo.setClickListener(v -> { }); final BarViewInfo[] barViewsInfo = new BarViewInfo[]{viewInfo}; @@ -327,8 +349,8 @@ public class BarChartPreferenceTest { @Test public void onBindViewHolder_loadingStateIsFalse_shouldInitAnyView() { - final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app, - null); + final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30, mTitleStr, mSummaryStr, + null /* contentDescription */); viewInfo.setClickListener(v -> { }); final BarViewInfo[] barViewsInfo = new BarViewInfo[]{viewInfo}; diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_left_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_left_animation.xml deleted file mode 100644 index d6054c4d3422..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_left_animation.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="250" - android:propertyName="scaleX" - android:valueFrom="1.0" - android:valueTo="1.8" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_mask_1_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_mask_1_animation.xml deleted file mode 100644 index 282170c1fae4..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_mask_1_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="83" - android:propertyName="pathData" - android:valueFrom="M 366.5,-269.5 c 0.0,0.0 -578.0,2.0 -578.0,2.0 c 0.0,0.0 65.7498321533,68.2501220703 65.7498321533,68.2501220703 c 0.0,0.0 -20.7500457764,20.7500610352 -20.7500457764,20.7500610352 c 0.0,0.0 -65.749786377,-68.2501983643 -65.749786377,-68.2501983643 c 0.0,0.0 -7.25,539.250015259 -7.25,539.250015259 c 0.0,0.0 606.0,0.0 606.0,0.0 c 0.0,0.0 0.0,-562.0 0.0,-562.0 Z" - android:valueTo="M 366.5,-269.5 c 0.0,0.0 -578.0,2.0 -578.0,2.0 c 0.0,0.0 65.7498321533,68.2501220703 65.7498321533,68.2501220703 c 0.0,0.0 -20.7500457764,20.7500610352 -20.7500457764,20.7500610352 c 0.0,0.0 -65.749786377,-68.2501983643 -65.749786377,-68.2501983643 c 0.0,0.0 -7.25,539.250015259 -7.25,539.250015259 c 0.0,0.0 606.0,0.0 606.0,0.0 c 0.0,0.0 0.0,-562.0 0.0,-562.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="250" - android:propertyName="pathData" - android:valueFrom="M 366.5,-269.5 c 0.0,0.0 -578.0,2.0 -578.0,2.0 c 0.0,0.0 65.7498321533,68.2501220703 65.7498321533,68.2501220703 c 0.0,0.0 -20.7500457764,20.7500610352 -20.7500457764,20.7500610352 c 0.0,0.0 -65.749786377,-68.2501983643 -65.749786377,-68.2501983643 c 0.0,0.0 -7.25,539.250015259 -7.25,539.250015259 c 0.0,0.0 606.0,0.0 606.0,0.0 c 0.0,0.0 0.0,-562.0 0.0,-562.0 Z" - android:valueTo="M 366.5,-269.5 c 0.0,0.0 -578.0,2.0 -578.0,2.0 c 0.0,0.0 480.0,480.0 480.0,480.0 c 0.0,0.0 -20.7500915527,20.75 -20.7500915527,20.75 c 0.0,0.0 -479.999908447,-480.000015259 -479.999908447,-480.000015259 c 0.0,0.0 -7.25,539.250015259 -7.25,539.250015259 c 0.0,0.0 606.0,0.0 606.0,0.0 c 0.0,0.0 0.0,-562.0 0.0,-562.0 Z" - android:valueType="pathType" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_2" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_3_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_3_animation.xml deleted file mode 100644 index b59c66419080..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_3_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="133" - android:propertyName="pathData" - android:valueFrom="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueTo="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="116" - android:propertyName="pathData" - android:valueFrom="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueTo="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_3_position_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_3_position_animation.xml deleted file mode 100644 index 60d23966ed12..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_3_position_animation.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="250" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M 0.0,0.0 c 0.0,4.16667 0.0,20.83333 0.0,25.0" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_1" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_4_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_4_animation.xml deleted file mode 100644 index ef442e9ef13a..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_4_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="33" - android:propertyName="pathData" - android:valueFrom="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueTo="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="200" - android:propertyName="pathData" - android:valueFrom="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueTo="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_4_position_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_4_position_animation.xml deleted file mode 100644 index 97782be4f145..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_rectangle_path_4_position_animation.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="233" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M 0.0,0.0 c 0.0,-4.16667 0.0,-20.83333 0.0,-25.0" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_0" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_right_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_right_animation.xml deleted file mode 100644 index d6054c4d3422..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_right_animation.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="250" - android:propertyName="scaleX" - android:valueFrom="1.0" - android:valueTo="1.8" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_stick_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_stick_animation.xml deleted file mode 100644 index 573205ffd2c8..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_stick_animation.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="250" - android:propertyName="scaleY" - android:valueFrom="0.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_3" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_stickito_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_stickito_animation.xml deleted file mode 100644 index 4b038b930c46..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_stickito_animation.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="333" - android:propertyName="alpha" - android:valueFrom="1.0" - android:valueTo="0.54" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_4" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_whole_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_whole_animation.xml deleted file mode 100644 index 562985a89ba9..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_whole_animation.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="83" - android:propertyName="scaleX" - android:valueFrom="1.0" - android:valueTo="1.15667" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_5" /> - <objectAnimator - android:duration="166" - android:propertyName="scaleX" - android:valueFrom="1.15667" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_5" /> - </set> - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="83" - android:propertyName="scaleY" - android:valueFrom="1.0" - android:valueTo="1.15667" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_5" /> - <objectAnimator - android:duration="166" - android:propertyName="scaleY" - android:valueFrom="1.15667" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_disable_animation_interpolator_5" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_cross_1.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_cross_1.xml deleted file mode 100644 index 6c7e75118f5c..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_cross_1.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="pathData" - android:valueFrom="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 " - android:valueTo="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 " - android:valueType="pathType" - android:interpolator="@interpolator/ic_signal_workmode_enable_cross_1_pathdata_interpolator" /> - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="333" - android:propertyName="strokeAlpha" - android:valueFrom="1" - android:valueTo="1" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="17" - android:propertyName="strokeAlpha" - android:valueFrom="1" - android:valueTo="0" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_ic_signal_briefcase.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_ic_signal_briefcase.xml deleted file mode 100644 index c699fe280f66..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_ic_signal_briefcase.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="200" - android:propertyName="alpha" - android:valueFrom="0.5" - android:valueTo="0.5" - android:interpolator="@android:interpolator/fast_out_slow_in" /> - <objectAnimator - android:duration="350" - android:propertyName="alpha" - android:valueFrom="0.5" - android:valueTo="1" - android:interpolator="@android:interpolator/fast_out_slow_in" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_mask.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_mask.xml deleted file mode 100644 index 5595e5c76297..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_mask.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="350" - android:propertyName="pathData" - android:valueFrom="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" - android:valueTo="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" - android:valueType="pathType" - android:interpolator="@interpolator/ic_signal_workmode_enable_mask_pathdata_interpolator" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_left_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_left_animation.xml deleted file mode 100644 index 4614bfc849e1..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_left_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="83" - android:propertyName="scaleX" - android:valueFrom="1.8" - android:valueTo="1.8" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="250" - android:propertyName="scaleX" - android:valueFrom="1.8" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_mask_1_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_mask_1_animation.xml deleted file mode 100644 index f5cfcf91b777..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_mask_1_animation.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="250" - android:propertyName="pathData" - android:valueFrom="M 366.5,-269.5 c 0.0,0.0 -578.0,2.0 -578.0,2.0 c 0.0,0.0 480.0,480.0 480.0,480.0 c 0.0,0.0 -20.7500915527,20.75 -20.7500915527,20.75 c 0.0,0.0 -479.999908447,-480.000015259 -479.999908447,-480.000015259 c 0.0,0.0 -7.25,539.250015259 -7.25,539.250015259 c 0.0,0.0 606.0,0.0 606.0,0.0 c 0.0,0.0 0.0,-562.0 0.0,-562.0 Z" - android:valueTo="M 366.5,-269.5 c 0.0,0.0 -578.0,2.0 -578.0,2.0 c 0.0,0.0 65.7498321533,68.2501220703 65.7498321533,68.2501220703 c 0.0,0.0 -20.7500457764,20.7500610352 -20.7500457764,20.7500610352 c 0.0,0.0 -65.749786377,-68.2501983643 -65.749786377,-68.2501983643 c 0.0,0.0 -7.25,539.250015259 -7.25,539.250015259 c 0.0,0.0 606.0,0.0 606.0,0.0 c 0.0,0.0 0.0,-562.0 0.0,-562.0 Z" - android:valueType="pathType" - android:interpolator="@interpolator/ic_signal_workmode_enable_animation_interpolator_1" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_3_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_3_animation.xml deleted file mode 100644 index 0b74b3a4fdc5..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_3_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="83" - android:propertyName="pathData" - android:valueFrom="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueTo="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="133" - android:propertyName="pathData" - android:valueFrom="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueTo="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_3_position_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_3_position_animation.xml deleted file mode 100644 index ba10224ab4db..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_3_position_animation.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="216" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M 0.0,25.0 c 0.0,-4.16667 0.0,-20.83333 0.0,-25.0" - android:interpolator="@interpolator/ic_signal_workmode_enable_animation_interpolator_2" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_4_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_4_animation.xml deleted file mode 100644 index 395bbf4802dd..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_4_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="100" - android:propertyName="pathData" - android:valueFrom="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueTo="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="199" - android:propertyName="pathData" - android:valueFrom="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueTo="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_4_position_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_4_position_animation.xml deleted file mode 100644 index 0115759ab0d8..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_rectangle_path_4_position_animation.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="300" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M 0.0,-25.0 c 0.0,4.16667 0.0,20.83333 0.0,25.0" - android:interpolator="@interpolator/ic_signal_workmode_enable_animation_interpolator_4" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_right_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_right_animation.xml deleted file mode 100644 index 4614bfc849e1..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_right_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="83" - android:propertyName="scaleX" - android:valueFrom="1.8" - android:valueTo="1.8" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="250" - android:propertyName="scaleX" - android:valueFrom="1.8" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_stick_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_stick_animation.xml deleted file mode 100644 index 6b182be01446..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_stick_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="83" - android:propertyName="scaleY" - android:valueFrom="1.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="250" - android:propertyName="scaleY" - android:valueFrom="1.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_stickito_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_stickito_animation.xml deleted file mode 100644 index 828f7a289ec6..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_stickito_animation.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="333" - android:propertyName="alpha" - android:valueFrom="0.54" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_enable_animation_interpolator_3" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_whole_animation.xml b/packages/SystemUI/res/anim/ic_signal_workmode_enable_whole_animation.xml deleted file mode 100644 index 89ab5808b4ab..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_whole_animation.xml +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="66" - android:propertyName="scaleX" - android:valueFrom="0.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="166" - android:propertyName="scaleX" - android:valueFrom="0.0" - android:valueTo="1.15667" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_enable_animation_interpolator_5" /> - <objectAnimator - android:duration="83" - android:propertyName="scaleX" - android:valueFrom="1.15667" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_enable_animation_interpolator_0" /> - </set> - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="66" - android:propertyName="scaleY" - android:valueFrom="0.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="166" - android:propertyName="scaleY" - android:valueFrom="0.0" - android:valueTo="1.15667" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_enable_animation_interpolator_5" /> - <objectAnimator - android:duration="83" - android:propertyName="scaleY" - android:valueFrom="1.15667" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_signal_workmode_enable_animation_interpolator_0" /> - </set> -</set> diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_disable.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_disable.xml deleted file mode 100644 index 96d848406955..000000000000 --- a/packages/SystemUI/res/drawable/ic_signal_workmode_disable.xml +++ /dev/null @@ -1,122 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector - xmlns:android="http://schemas.android.com/apk/res/android" - android:name="ic_signal_workmode_disable" - android:width="42dp" - android:viewportWidth="42" - android:height="42dp" - android:viewportHeight="42" > - <group - android:name="suitcase" - android:translateX="21" - android:translateY="36.9375" - android:scaleX="0.1" - android:scaleY="0.1" > - <group - android:name="suitcase_pivot" - android:translateY="-158" > - <clip-path - android:name="mask_1" - android:pathData="M 366.5,-269.5 c 0.0,0.0 -578.0,2.0 -578.0,2.0 c 0.0,0.0 65.7498321533,68.2501220703 65.7498321533,68.2501220703 c 0.0,0.0 -20.7500457764,20.7500610352 -20.7500457764,20.7500610352 c 0.0,0.0 -65.749786377,-68.2501983643 -65.749786377,-68.2501983643 c 0.0,0.0 -7.25,539.250015259 -7.25,539.250015259 c 0.0,0.0 606.0,0.0 606.0,0.0 c 0.0,0.0 0.0,-562.0 0.0,-562.0 Z" /> - <group - android:name="whole" - android:translateX="-1.11523" - android:translateY="32.0918" > - <path - android:name="rectangle_path_1" - android:strokeColor="#FFFFFFFF" - android:strokeWidth="65" - android:pathData="M 0.0,-66.5 l 0.0,0.0 c 36.7269358617,0.0 66.5,29.7730641383 66.5,66.5 l 0.0,0.0 c 0.0,36.7269358617 -29.7730641383,66.5 -66.5,66.5 l 0.0,0.0 c -36.7269358617,0.0 -66.5,-29.7730641383 -66.5,-66.5 l 0.0,0.0 c 0.0,-36.7269358617 29.7730641383,-66.5 66.5,-66.5 Z" /> - </group> - <group - android:name="handle" - android:translateY="-100" > - <path - android:name="rectangle_path_2" - android:strokeColor="#FFFFFFFF" - android:strokeWidth="35" - android:pathData="M -34.0,-50.0 l 68.0,0.0 c 8.8365559968,0.0 16.0,7.1634440032 16.0,16.0 l 0.0,68.0 c 0.0,8.8365559968 -7.1634440032,16.0 -16.0,16.0 l -68.0,0.0 c -8.8365559968,0.0 -16.0,-7.1634440032 -16.0,-16.0 l 0.0,-68.0 c 0.0,-8.8365559968 7.1634440032,-16.0 16.0,-16.0 Z" /> - </group> - <group - android:name="case" - android:translateY="32.68518" > - <group - android:name="case_pivot" - android:translateY="-32.68518" > - <group - android:name="bottom" - android:translateY="-97.62964" > - <group - android:name="bottom_pivot" - android:translateY="40" > - <group - android:name="rectangle_path_3_position" > - <path - android:name="rectangle_path_3" - android:fillColor="#FFFFFFFF" - android:pathData="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" /> - </group> - </group> - </group> - <group - android:name="top" - android:translateY="163" > - <group - android:name="top_pivot" - android:translateY="-40" > - <group - android:name="rectangle_path_4_position" > - <path - android:name="rectangle_path_4" - android:fillColor="#FFFFFFFF" - android:pathData="M -143.0,-40.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,16.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-16.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" /> - </group> - </group> - </group> - <group - android:name="left" - android:translateX="-175.00635" - android:translateY="30" > - <group - android:name="left_pivot" - android:translateX="50.00635" > - <path - android:name="rectangle_path_5" - android:fillColor="#FFFFFFFF" - android:pathData="M -50.0,-88.0 l 100.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,176.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -100.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-176.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" /> - </group> - </group> - <group - android:name="right" - android:translateX="174.97778" - android:translateY="30" > - <group - android:name="right_pivot" - android:translateX="-49.97778" > - <path - android:name="rectangle_path_6" - android:fillColor="#FFFFFFFF" - android:pathData="M -50.0,-88.0 l 100.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,176.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -100.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-176.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" /> - </group> - </group> - </group> - </group> - <group - android:name="stick" - android:translateX="-166.59082" - android:translateY="-156.51367" - android:scaleY="0" - android:rotation="-45" > - <group - android:name="stick_pivot" - android:translateX="0.18161" - android:translateY="243.8158" > - <path - android:name="stickito" - android:fillColor="#FFFFFFFF" - android:pathData="M -16.5,-243.999885 l 33.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,487.99977 c 0.0,0.0 0.0,0.0 0.0,0.0 l -33.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-487.99977 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" /> - </group> - </group> - </group> - </group> -</vector> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_0.xml deleted file mode 100644 index 5009c6b7ac10..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_0.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 l 0.144628099174,0.0 l 0.855371900826,1.0 L 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_1.xml deleted file mode 100644 index 678b90b24914..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_1.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 l 0.534759358289,0.0 l 0.465240641711,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_2.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_2.xml deleted file mode 100644 index 6c6df6078aaa..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_2.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 c 0.313385868073,0.330828523695 0.125984191895,0.661170632677 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_3.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_3.xml deleted file mode 100644 index b1eec483cdf4..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_3.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 c 0.4,0.0 0.2,0.2 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_4.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_4.xml deleted file mode 100644 index 17ff65aaa155..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_4.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 c 0.4,0.4 0.2,0.2 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_5.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_5.xml deleted file mode 100644 index aee48dc2637a..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_animation_interpolator_5.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 c 0.33333333,0.0 0.66666667,1.0 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_cross_1_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_cross_1_pathdata_interpolator.xml deleted file mode 100644 index 66cfaffd9936..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_disable_cross_1_pathdata_interpolator.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0,0 c 0.166666667,0 0.2,1 1,1" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_0.xml deleted file mode 100644 index 4a5fde9fd49b..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_0.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 c 0.33333333,0.0 0.83333333333,1.0 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_1.xml deleted file mode 100644 index 0f35e5d01470..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_1.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 c 0.714960628748,0.0 0.678740215302,1.0 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_2.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_2.xml deleted file mode 100644 index 626f9ef97881..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_2.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 l 0.392038600724,0.0 l 0.607961399276,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_3.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_3.xml deleted file mode 100644 index 17ff65aaa155..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_3.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 c 0.4,0.4 0.2,0.2 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_4.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_4.xml deleted file mode 100644 index 96bdb484c2f9..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_4.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 l 0.337078651685,0.0 l 0.662921348315,1.0 L 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_5.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_5.xml deleted file mode 100644 index a91610d617f2..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_animation_interpolator_5.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<pathInterpolator - xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0.0,0.0 c 0.16666666667,0.0 0.66666667,1.0 1.0,1.0" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_cross_1_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_cross_1_pathdata_interpolator.xml deleted file mode 100644 index a0118d707951..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_cross_1_pathdata_interpolator.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0,0 c 0.8,0 0.833333333,1 1,1" /> diff --git a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_mask_pathdata_interpolator.xml b/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_mask_pathdata_interpolator.xml deleted file mode 100644 index 1820bab9e469..000000000000 --- a/packages/SystemUI/res/interpolator/ic_signal_workmode_enable_mask_pathdata_interpolator.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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. ---> -<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" - android:pathData="M 0,0 c 0.8,0 0.6,1 1,1" /> diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml index 8f7a45f02c46..c452855cc9e9 100644 --- a/packages/SystemUI/res/layout/biometric_dialog.xml +++ b/packages/SystemUI/res/layout/biometric_dialog.xml @@ -76,10 +76,6 @@ android:layout_marginTop="24dp" android:gravity="@integer/biometric_dialog_text_gravity" android:textSize="20sp" - android:maxLines="1" - android:singleLine="true" - android:ellipsize="marquee" - android:marqueeRepeatLimit="marquee_forever" android:textColor="?android:attr/textColorPrimary"/> <TextView @@ -91,10 +87,6 @@ android:layout_marginEnd="24dp" android:gravity="@integer/biometric_dialog_text_gravity" android:textSize="16sp" - android:maxLines="1" - android:singleLine="true" - android:ellipsize="marquee" - android:marqueeRepeatLimit="marquee_forever" android:textColor="?android:attr/textColorPrimary"/> <TextView @@ -106,7 +98,6 @@ android:gravity="@integer/biometric_dialog_text_gravity" android:paddingTop="8dp" android:textSize="16sp" - android:maxLines="4" android:textColor="?android:attr/textColorPrimary"/> <ImageView diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index baa2055a1736..039eca694e24 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -37,7 +37,13 @@ <dimen name="navigation_handle_radius">1dp</dimen> <dimen name="navigation_handle_bottom">6dp</dimen> <dimen name="navigation_handle_horizontal_margin">30dp</dimen> - <dimen name="navigation_home_handle_width">280dp</dimen> + <dimen name="navigation_handle_sample_horizontal_margin">10dp</dimen> + <dimen name="navigation_home_handle_width">72dp</dimen> + + <!-- Luminance threshold to determine black/white contrast for the navigation affordances --> + <item name="navigation_luminance_threshold" type="dimen" format="float">0.5</item> + <!-- Luminance change threshold that allows applying new value if difference was exceeded --> + <item name="navigation_luminance_change_threshold" type="dimen" format="float">0.05</item> <!-- Height of notification icons in the status bar --> <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 22c019f950e7..e84c64838fd6 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -384,9 +384,11 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe } if (shouldAutoBubbleForFlags(mContext, entry) || shouldBubble(entry)) { // TODO: handle group summaries - // It's a new notif, it shows in the shade and as a bubble entry.setIsBubble(true); - entry.setShowInShadeWhenBubble(true); + boolean suppressNotification = entry.getBubbleMetadata() != null + && entry.getBubbleMetadata().getSuppressInitialNotification() + && isForegroundApp(entry.notification.getPackageName()); + entry.setShowInShadeWhenBubble(!suppressNotification); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 608f646e77a4..8ed5424cf673 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -113,6 +113,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta public void saveSpecs(QSTileHost host) { List<String> newSpecs = new ArrayList<>(); + clearAccessibilityState(); for (int i = 1; i < mTiles.size() && mTiles.get(i) != null; i++) { newSpecs.add(mTiles.get(i).spec); } @@ -120,6 +121,17 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta mCurrentSpecs = newSpecs; } + private void clearAccessibilityState() { + if (mAccessibilityAction == ACTION_ADD) { + // Remove blank tile from last spot + mTiles.remove(--mEditIndex); + // Update the tile divider position + mTileDividerIndex--; + notifyDataSetChanged(); + } + mAccessibilityAction = ACTION_NONE; + } + public void resetTileSpecs(QSTileHost host, List<String> specs) { // Notify the host so the tiles get removed callbacks. host.changeTiles(mCurrentSpecs, specs); @@ -333,8 +345,6 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta // Remove the placeholder. mTiles.remove(mEditIndex--); notifyItemRemoved(mEditIndex); - // Don't remove items when the last position is selected. - if (position == mEditIndex - 1) position--; } mAccessibilityAction = ACTION_NONE; move(mAccessibilityFromIndex, position, v); @@ -372,6 +382,8 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta mAccessibilityAction = ACTION_ADD; // Add placeholder for last slot. mTiles.add(mEditIndex++, null); + // Update the tile divider position + mTileDividerIndex++; mNeedsFocus = true; notifyDataSetChanged(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index f921eb9a49a6..7853dc388bcb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -33,7 +33,7 @@ import javax.inject.Inject; /** Quick settings tile: Work profile on/off */ public class WorkModeTile extends QSTileImpl<BooleanState> implements ManagedProfileController.Callback { - private final Icon mIcon = ResourceIcon.get(R.drawable.ic_signal_workmode_disable); + private final Icon mIcon = ResourceIcon.get(R.drawable.stat_sys_managed_profile_status); private final ManagedProfileController mProfileController; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 8faeb155b1e6..a87e50c50f51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -308,11 +308,23 @@ public class KeyguardIndicationController implements StateListener { // Walk down a precedence-ordered list of what indication // should be shown based on user or device state if (mDozing) { + // When dozing we ignore any text color and use white instead, because + // colors can be hard to read in low brightness. + mTextView.setTextColor(Color.WHITE); if (!TextUtils.isEmpty(mTransientIndication)) { - mTextView.setTextColor(Color.WHITE); mTextView.switchIndication(mTransientIndication); + } else if (mPowerPluggedIn) { + String indication = computePowerIndication(); + if (animate) { + animateText(mTextView, indication); + } else { + mTextView.switchIndication(indication); + } + } else { + String percentage = NumberFormat.getPercentInstance() + .format(mBatteryLevel / 100f); + mTextView.switchIndication(percentage); } - updateAlphas(); return; } @@ -353,14 +365,6 @@ public class KeyguardIndicationController implements StateListener { } } - private void updateAlphas() { - if (!TextUtils.isEmpty(mTransientIndication)) { - mTextView.setAlpha(1f); - } else { - mTextView.setAlpha(1f - mDarkAmount); - } - } - // animates textView - textView moves up and bounces down private void animateText(KeyguardIndicationTextView textView, String indication) { int yTranslation = mContext.getResources().getInteger( @@ -523,14 +527,6 @@ public class KeyguardIndicationController implements StateListener { pw.println(" computePowerIndication(): " + computePowerIndication()); } - public void setDarkAmount(float darkAmount) { - if (mDarkAmount == darkAmount) { - return; - } - mDarkAmount = darkAmount; - updateAlphas(); - } - @Override public void onStateChanged(int newState) { // don't care @@ -675,6 +671,7 @@ public class KeyguardIndicationController implements StateListener { public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) { super.onBiometricAuthenticated(userId, biometricSourceType); mLastSuccessiveErrorMessage = -1; + mHandler.sendEmptyMessage(MSG_HIDE_TRANSIENT); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 2d91d53212f4..a924680b7043 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON; @@ -172,6 +173,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private boolean mDozing; private int mIndicationBottomMargin; private float mDarkAmount; + private int mBurnInXOffset; + private int mBurnInYOffset; private ActivityIntentHelper mActivityIntentHelper; public KeyguardBottomAreaView(Context context) { @@ -252,6 +255,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mIndicationText = findViewById(R.id.keyguard_indication_text); mIndicationBottomMargin = getResources().getDimensionPixelSize( R.dimen.keyguard_indication_margin_bottom); + mBurnInYOffset = getResources().getDimensionPixelSize( + R.dimen.default_burn_in_prevention_offset); updateCameraVisibility(); mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); mUnlockMethodCache.addListener(this); @@ -321,6 +326,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL super.onConfigurationChanged(newConfig); mIndicationBottomMargin = getResources().getDimensionPixelSize( R.dimen.keyguard_indication_margin_bottom); + mBurnInYOffset = getResources().getDimensionPixelSize( + R.dimen.default_burn_in_prevention_offset); MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams(); if (mlp.bottomMargin != mIndicationBottomMargin) { mlp.bottomMargin = mIndicationBottomMargin; @@ -564,8 +571,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL return; } mDarkAmount = darkAmount; - mIndicationController.setDarkAmount(darkAmount); mLockIcon.setDarkAmount(darkAmount); + dozeTimeTick(); } /** @@ -841,6 +848,20 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } } + public void dozeTimeTick() { + int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */) + - mBurnInYOffset; + mIndicationArea.setTranslationY(burnInYOffset * mDarkAmount); + } + + public void setAntiBurnInOffsetX(int burnInXOffset) { + if (mBurnInXOffset == burnInXOffset) { + return; + } + mBurnInXOffset = burnInXOffset; + mIndicationArea.setTranslationX(burnInXOffset); + } + /** * Sets the alpha of the indication areas and affordances, excluding the lock icon. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index 4c50d07aa6ea..2bd8d41a24e3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.phone; import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection; -import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import android.annotation.ColorInt; import android.content.Context; @@ -102,19 +101,6 @@ public class KeyguardStatusBarView extends RelativeLayout */ private int mCutoutSideNudge = 0; - /** - * How much to move icons to avoid burn in. - */ - private int mBurnInOffset; - private int mCurrentBurnInOffsetX; - private int mCurrentBurnInOffsetY; - - /** - * Ratio representing being in ambient mode or not. - */ - private float mDarkAmount; - private boolean mDozing; - public KeyguardStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -186,8 +172,6 @@ public class KeyguardStatusBarView extends RelativeLayout R.dimen.system_icons_super_container_avatarless_margin_end); mCutoutSideNudge = getResources().getDimensionPixelSize( R.dimen.display_cutout_margin_consumption); - mBurnInOffset = getResources().getDimensionPixelSize( - R.dimen.default_burn_in_prevention_offset); mShowPercentAvailable = getContext().getResources().getBoolean( com.android.internal.R.bool.config_battery_percentage_setting_available); } @@ -211,7 +195,7 @@ public class KeyguardStatusBarView extends RelativeLayout mMultiUserSwitch.setVisibility(View.GONE); } } - mBatteryView.setForceShowPercent(mBatteryCharging && mShowPercentAvailable || mDozing); + mBatteryView.setForceShowPercent(mBatteryCharging && mShowPercentAvailable); } private void updateSystemIconsLayoutParams() { @@ -348,7 +332,6 @@ public class KeyguardStatusBarView extends RelativeLayout mIconManager = new TintedIconManager(findViewById(R.id.statusIcons)); Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager); onThemeChanged(); - updateDarkState(); } @Override @@ -492,7 +475,7 @@ public class KeyguardStatusBarView extends RelativeLayout mIconManager.setTint(iconColor); } - applyDarkness(R.id.battery, mEmptyRect, intensity * (1f - mDarkAmount), iconColor); + applyDarkness(R.id.battery, mEmptyRect, intensity, iconColor); applyDarkness(R.id.clock, mEmptyRect, intensity, iconColor); } @@ -513,48 +496,4 @@ public class KeyguardStatusBarView extends RelativeLayout mBatteryView.dump(fd, pw, args); } } - - public void setDozing(boolean dozing) { - if (mDozing == dozing) { - return; - } - mDozing = dozing; - setClipChildren(!dozing); - setClipToPadding(!dozing); - updateVisibilities(); - } - - public void setDarkAmount(float darkAmount) { - mDarkAmount = darkAmount; - if (darkAmount == 0) { - dozeTimeTick(); - } - updateDarkState(); - } - - public void dozeTimeTick() { - mCurrentBurnInOffsetX = getBurnInOffset(mBurnInOffset, true /* xAxis */); - mCurrentBurnInOffsetY = getBurnInOffset(mBurnInOffset, false /* xAxis */); - updateDarkState(); - } - - private void updateDarkState() { - float alpha = 1f - mDarkAmount; - int visibility = alpha != 0f ? VISIBLE : INVISIBLE; - mCarrierLabel.setAlpha(alpha * alpha); - mStatusIconContainer.setAlpha(alpha); - mStatusIconContainer.setVisibility(visibility); - - float iconsX = -mCurrentBurnInOffsetX; - if (mMultiUserSwitch.getVisibility() == VISIBLE) { - // Squared alpha to add a nice easing curve and avoid overlap during animation. - mMultiUserAvatar.setAlpha(alpha * alpha); - iconsX += mMultiUserAvatar.getPaddingLeft() + mMultiUserAvatar.getWidth() - + mMultiUserAvatar.getPaddingRight(); - } - mSystemIconsContainer.setTranslationX(iconsX * mDarkAmount); - mSystemIconsContainer.setTranslationY(mCurrentBurnInOffsetY * mDarkAmount); - updateIconsAndTextColors(); - } - } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java index 9cfb1aa192b1..bf5b60a9437b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java @@ -19,11 +19,14 @@ package com.android.systemui.statusbar.phone; import static android.view.Display.DEFAULT_DISPLAY; import android.content.Context; +import android.content.res.Resources; +import android.graphics.Point; import android.graphics.Rect; import android.os.Handler; import android.view.CompositionSamplingListener; import android.view.View; +import com.android.systemui.R; import com.android.systemui.shared.system.QuickStepContract; import java.io.PrintWriter; @@ -37,9 +40,6 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400; public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1700; - // Passing the threshold of this luminance value will make the button black otherwise white - private static final float LUMINANCE_THRESHOLD = 0.3f; - private final Handler mHandler = new Handler(); private final NavigationBarView mNavigationBarView; private final LightBarTransitionsController mLightBarController; @@ -50,9 +50,17 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, private boolean mSamplingEnabled = false; private boolean mSamplingListenerRegistered = false; - private float mLastMediaLuma; + private float mLastMedianLuma; + private float mCurrentMedianLuma; private boolean mUpdateOnNextDraw; + private final int mNavBarHeight; + private final int mNavColorSampleMargin; + + // Passing the threshold of this luminance value will make the button black otherwise white + private final float mLuminanceThreshold; + private final float mLuminanceChangeThreshold; + public NavBarTintController(NavigationBarView navigationBarView, LightBarTransitionsController lightBarController) { mSamplingListener = new CompositionSamplingListener( @@ -66,6 +74,13 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, mNavigationBarView.addOnAttachStateChangeListener(this); mNavigationBarView.addOnLayoutChangeListener(this); mLightBarController = lightBarController; + + final Resources res = navigationBarView.getResources(); + mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_height); + mNavColorSampleMargin = + res.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin); + mLuminanceThreshold = res.getFloat(R.dimen.navigation_luminance_threshold); + mLuminanceChangeThreshold = res.getFloat(R.dimen.navigation_luminance_change_threshold); } void onDraw() { @@ -109,8 +124,11 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, if (view != null) { int[] pos = new int[2]; view.getLocationOnScreen(pos); - final Rect samplingBounds = new Rect(pos[0], pos[1], - pos[0] + view.getWidth(), pos[1] + view.getHeight()); + Point displaySize = new Point(); + view.getContext().getDisplay().getRealSize(displaySize); + final Rect samplingBounds = new Rect(pos[0] - mNavColorSampleMargin, + displaySize.y - mNavBarHeight, pos[0] + view.getWidth() + mNavColorSampleMargin, + displaySize.y); if (!samplingBounds.equals(mSamplingBounds)) { mSamplingBounds.set(samplingBounds); requestUpdateSamplingListener(); @@ -144,13 +162,19 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, } private void updateTint(float medianLuma) { - mLastMediaLuma = medianLuma; - if (medianLuma > LUMINANCE_THRESHOLD) { - // Black - mLightBarController.setIconsDark(true /* dark */, true /* animate */); - } else { - // White - mLightBarController.setIconsDark(false /* dark */, true /* animate */); + mLastMedianLuma = medianLuma; + + // If the difference between the new luma and the current luma is larger than threshold + // then apply the current luma, this is to prevent small changes causing colors to flicker + if (Math.abs(mCurrentMedianLuma - mLastMedianLuma) > mLuminanceChangeThreshold) { + if (medianLuma > mLuminanceThreshold) { + // Black + mLightBarController.setIconsDark(true /* dark */, true /* animate */); + } else { + // White + mLightBarController.setIconsDark(false /* dark */, true /* animate */); + } + mCurrentMedianLuma = medianLuma; } } @@ -162,7 +186,8 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, : "false")); pw.println(" mSamplingListenerRegistered: " + mSamplingListenerRegistered); pw.println(" mSamplingBounds: " + mSamplingBounds); - pw.println(" mLastMediaLuma: " + mLastMediaLuma); + pw.println(" mLastMedianLuma: " + mLastMedianLuma); + pw.println(" mCurrentMedianLuma: " + mCurrentMedianLuma); } public static boolean isEnabled(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java index 968074c6af59..81a425cd5eba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java @@ -68,7 +68,7 @@ public class NavigationHandle extends View implements ButtonInterface { int height = mRadius * 2; int width = getWidth(); int y = (navHeight - mBottom - height); - canvas.drawRoundRect(mRadius, y, width - mRadius, y + height, mRadius, mRadius, mPaint); + canvas.drawRoundRect(0, y, width, y + height, mRadius, mRadius, mPaint); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index ab1f500b25e0..02bad736723d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -635,6 +635,7 @@ public class NotificationPanelView extends PanelView implements } mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding); mNotificationStackScroller.setAntiBurnInOffsetX(mClockPositionResult.clockX); + mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX); mStackScrollerMeasuringPass++; requestScrollerTopPaddingUpdate(animate); @@ -1886,7 +1887,7 @@ public class NotificationPanelView extends PanelView implements float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion) * mKeyguardStatusBarAnimateAlpha; mKeyguardStatusBar.setAlpha(newAlpha); - mKeyguardStatusBar.setVisibility(newAlpha != 0f ? VISIBLE : INVISIBLE); + mKeyguardStatusBar.setVisibility(newAlpha != 0f && !mDozing ? VISIBLE : INVISIBLE); } private void updateKeyguardBottomAreaAlpha() { @@ -2373,12 +2374,11 @@ public class NotificationPanelView extends PanelView implements positionClockAndNotifications(); } - private static float interpolate(float t, float start, float end) { - return (1 - t) * start + t * end; - } - private void updateDozingVisibilities(boolean animate) { mKeyguardBottomArea.setDozing(mDozing, animate); + if (!mDozing && animate) { + animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD); + } } @Override @@ -2814,7 +2814,7 @@ public class NotificationPanelView extends PanelView implements if (mDozing) { mNotificationStackScroller.setShowDarkShelf(!hasCustomClock()); } - mKeyguardStatusBar.setDozing(mDozing); + mKeyguardBottomArea.setDozing(mDozing, animate); if (mBarState == StatusBarState.KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) { @@ -2829,7 +2829,6 @@ public class NotificationPanelView extends PanelView implements public void onDozeAmountChanged(float linearAmount, float amount) { mInterpolatedDarkAmount = amount; mLinearDarkAmount = linearAmount; - mKeyguardStatusBar.setDarkAmount(mInterpolatedDarkAmount); mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount); mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount); positionClockAndNotifications(); @@ -2861,7 +2860,7 @@ public class NotificationPanelView extends PanelView implements } public void dozeTimeTick() { - mKeyguardStatusBar.dozeTimeTick(); + mKeyguardBottomArea.dozeTimeTick(); mKeyguardStatusView.dozeTimeTick(); if (mInterpolatedDarkAmount > 0) { positionClockAndNotifications(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index f666d60d6282..14bc71b6a142 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -71,6 +71,9 @@ import java.util.concurrent.TimeUnit; @TestableLooper.RunWithLooper(setAsMainLooper = true) public class BubbleControllerTest extends SysuiTestCase { + // Some APIs rely on the app being foreground, check is via pkg name + private static final String FOREGROUND_TEST_PKG_NAME = "com.android.systemui.tests"; + @Mock private NotificationEntryManager mNotificationEntryManager; @Mock @@ -95,6 +98,7 @@ public class BubbleControllerTest extends SysuiTestCase { private ExpandableNotificationRow mRow2; private ExpandableNotificationRow mNoChannelRow; private ExpandableNotificationRow mAutoExpandRow; + private ExpandableNotificationRow mSuppressNotifRow; @Mock private NotificationData mNotificationData; @@ -126,9 +130,18 @@ public class BubbleControllerTest extends SysuiTestCase { mRow = mNotificationTestHelper.createBubble(mDeleteIntent); mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent); mNoChannelRow = mNotificationTestHelper.createBubble(mDeleteIntent); - Notification.BubbleMetadata metadata = getBuilder().setAutoExpandBubble(true).build(); - mAutoExpandRow = mNotificationTestHelper.createBubble(metadata, - "com.android.systemui.tests"); + + // Some bubbles want to auto expand + Notification.BubbleMetadata autoExpandMetadata = + getBuilder().setAutoExpandBubble(true).build(); + mAutoExpandRow = mNotificationTestHelper.createBubble(autoExpandMetadata, + FOREGROUND_TEST_PKG_NAME); + + // Some bubbles want to suppress notifs + Notification.BubbleMetadata suppressNotifMetadata = + getBuilder().setSuppressInitialNotification(true).build(); + mSuppressNotifRow = mNotificationTestHelper.createBubble(suppressNotifMetadata, + FOREGROUND_TEST_PKG_NAME); // Return non-null notification data from the NEM when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData); @@ -317,7 +330,7 @@ public class BubbleControllerTest extends SysuiTestCase { } @Test - public void testAutoExpandFailsNotForeground() { + public void testAutoExpand_FailsNotForeground() { assertFalse(mBubbleController.isStackExpanded()); // Add the auto expand bubble @@ -334,7 +347,7 @@ public class BubbleControllerTest extends SysuiTestCase { } @Test - public void testAutoExpandSucceedsForeground() { + public void testAutoExpand_SucceedsForeground() { final CountDownLatch latch = new CountDownLatch(1); BroadcastReceiver receiver = new BroadcastReceiver() { @Override @@ -372,6 +385,57 @@ public class BubbleControllerTest extends SysuiTestCase { mContext.unregisterReceiver(receiver); } + @Test + public void testSuppressNotif_FailsNotForeground() { + // Add the suppress notif bubble + mEntryListener.onPendingEntryAdded(mSuppressNotifRow.getEntry()); + mBubbleController.updateBubble(mSuppressNotifRow.getEntry(), true /* updatePosition */); + + // Should be a bubble & should show in shade because we weren't forground + assertTrue(mSuppressNotifRow.getEntry().isBubble()); + assertTrue(mSuppressNotifRow.getEntry().showInShadeWhenBubble()); + + // # of bubbles should change + verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */); + } + + @Test + public void testSuppressNotif_SucceedsForeground() { + final CountDownLatch latch = new CountDownLatch(1); + BroadcastReceiver receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + latch.countDown(); + } + }; + IntentFilter filter = new IntentFilter(BubblesTestActivity.BUBBLE_ACTIVITY_OPENED); + mContext.registerReceiver(receiver, filter); + + assertFalse(mBubbleController.isStackExpanded()); + + // Make ourselves foreground + Intent i = new Intent(mContext, BubblesTestActivity.class); + i.setFlags(FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(i); + + try { + latch.await(100, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // Add the suppress notif bubble + mEntryListener.onPendingEntryAdded(mSuppressNotifRow.getEntry()); + mBubbleController.updateBubble(mSuppressNotifRow.getEntry(), true /* updatePosition */); + + // Should be a bubble & should NOT show in shade because we were foreground + assertTrue(mSuppressNotifRow.getEntry().isBubble()); + assertFalse(mSuppressNotifRow.getEntry().showInShadeWhenBubble()); + + // # of bubbles should change + verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */); + mContext.unregisterReceiver(receiver); + } @Test public void testMarkNewNotificationAsBubble() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index 232c6a25a708..3b56e45ea354 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -60,6 +60,8 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private KeyguardStatusView mKeyguardStatusView; @Mock + private KeyguardBottomAreaView mKeyguardBottomArea; + @Mock private KeyguardStatusBarView mKeyguardStatusBar; private NotificationPanelView mNotificationPanelView; @@ -113,6 +115,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mNotificationStackScroller = mNotificationStackScrollLayout; mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView; mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar; + mKeyguardBottomArea = NotificationPanelViewTest.this.mKeyguardBottomArea; } } } diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java index 85c82bc009a0..f4c27771c846 100644 --- a/rs/java/android/renderscript/RenderScript.java +++ b/rs/java/android/renderscript/RenderScript.java @@ -447,27 +447,33 @@ public class RenderScript { validate(); return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer); } - native long rsnAllocationCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage); + native long rsnAllocationCreateFromBitmap(long con, long type, int mip, long bitmapHandle, + int usage); synchronized long nAllocationCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) { validate(); - return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage); + return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp.getNativeInstance(), usage); } - native long rsnAllocationCreateBitmapBackedAllocation(long con, long type, int mip, Bitmap bmp, int usage); - synchronized long nAllocationCreateBitmapBackedAllocation(long type, int mip, Bitmap bmp, int usage) { + native long rsnAllocationCreateBitmapBackedAllocation(long con, long type, int mip, long bitmapHandle, + int usage); + synchronized long nAllocationCreateBitmapBackedAllocation(long type, int mip, Bitmap bmp, + int usage) { validate(); - return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp, usage); + return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp.getNativeInstance(), + usage); } - native long rsnAllocationCubeCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage); + native long rsnAllocationCubeCreateFromBitmap(long con, long type, int mip, long bitmapHandle, + int usage); synchronized long nAllocationCubeCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) { validate(); - return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage); + return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp.getNativeInstance(), + usage); } - native long rsnAllocationCreateBitmapRef(long con, long type, Bitmap bmp); + native long rsnAllocationCreateBitmapRef(long con, long type, long bitmapHandle); synchronized long nAllocationCreateBitmapRef(long type, Bitmap bmp) { validate(); - return rsnAllocationCreateBitmapRef(mContext, type, bmp); + return rsnAllocationCreateBitmapRef(mContext, type, bmp.getNativeInstance()); } native long rsnAllocationCreateFromAssetStream(long con, int mips, int assetStream, int usage); synchronized long nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) { @@ -475,10 +481,10 @@ public class RenderScript { return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage); } - native void rsnAllocationCopyToBitmap(long con, long alloc, Bitmap bmp); + native void rsnAllocationCopyToBitmap(long con, long alloc, long bitmapHandle); synchronized void nAllocationCopyToBitmap(long alloc, Bitmap bmp) { validate(); - rsnAllocationCopyToBitmap(mContext, alloc, bmp); + rsnAllocationCopyToBitmap(mContext, alloc, bmp.getNativeInstance()); } native void rsnAllocationSyncAll(long con, long alloc, int src); @@ -487,8 +493,10 @@ public class RenderScript { rsnAllocationSyncAll(mContext, alloc, src); } - native ByteBuffer rsnAllocationGetByteBuffer(long con, long alloc, long[] stride, int xBytesSize, int dimY, int dimZ); - synchronized ByteBuffer nAllocationGetByteBuffer(long alloc, long[] stride, int xBytesSize, int dimY, int dimZ) { + native ByteBuffer rsnAllocationGetByteBuffer(long con, long alloc, long[] stride, + int xBytesSize, int dimY, int dimZ); + synchronized ByteBuffer nAllocationGetByteBuffer(long alloc, long[] stride, int xBytesSize, + int dimY, int dimZ) { validate(); return rsnAllocationGetByteBuffer(mContext, alloc, stride, xBytesSize, dimY, dimZ); } @@ -529,10 +537,10 @@ public class RenderScript { validate(); rsnAllocationGenerateMipmaps(mContext, alloc); } - native void rsnAllocationCopyFromBitmap(long con, long alloc, Bitmap bmp); + native void rsnAllocationCopyFromBitmap(long con, long alloc, long bitmapHandle); synchronized void nAllocationCopyFromBitmap(long alloc, Bitmap bmp) { validate(); - rsnAllocationCopyFromBitmap(mContext, alloc, bmp); + rsnAllocationCopyFromBitmap(mContext, alloc, bmp.getNativeInstance()); } diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp index 52d0e08e4e7f..dfee96182a48 100644 --- a/rs/jni/android_renderscript_RenderScript.cpp +++ b/rs/jni/android_renderscript_RenderScript.cpp @@ -1321,10 +1321,10 @@ nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc) static jlong nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip, - jobject jbitmap, jint usage) + jlong bitmapPtr, jint usage) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); const void* ptr = bitmap.getPixels(); jlong id = (jlong)(uintptr_t)rsAllocationCreateFromBitmap((RsContext)con, @@ -1335,10 +1335,10 @@ nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, static jlong nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type, - jint mip, jobject jbitmap, jint usage) + jint mip, jlong bitmapPtr, jint usage) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); const void* ptr = bitmap.getPixels(); jlong id = (jlong)(uintptr_t)rsAllocationCreateTyped((RsContext)con, @@ -1349,10 +1349,10 @@ nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, static jlong nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip, - jobject jbitmap, jint usage) + jlong bitmapPtr, jint usage) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); const void* ptr = bitmap.getPixels(); jlong id = (jlong)(uintptr_t)rsAllocationCubeCreateFromBitmap((RsContext)con, @@ -1362,10 +1362,10 @@ nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong ty } static void -nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap) +nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jlong bitmapPtr) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); int w = bitmap.width(); int h = bitmap.height(); @@ -1376,10 +1376,10 @@ nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, j } static void -nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap) +nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jlong bitmapPtr) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); + bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap); void* ptr = bitmap.getPixels(); rsAllocationCopyToBitmap((RsContext)con, (RsAllocation)alloc, ptr, bitmap.computeByteSize()); @@ -2866,13 +2866,13 @@ static const JNINativeMethod methods[] = { {"rsnTypeCreate", "(JJIIIZZI)J", (void*)nTypeCreate }, {"rsnTypeGetNativeData", "(JJ[J)V", (void*)nTypeGetNativeData }, -{"rsnAllocationCreateTyped", "(JJIIJ)J", (void*)nAllocationCreateTyped }, -{"rsnAllocationCreateFromBitmap", "(JJILandroid/graphics/Bitmap;I)J", (void*)nAllocationCreateFromBitmap }, -{"rsnAllocationCreateBitmapBackedAllocation", "(JJILandroid/graphics/Bitmap;I)J", (void*)nAllocationCreateBitmapBackedAllocation }, -{"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J", (void*)nAllocationCubeCreateFromBitmap }, +{"rsnAllocationCreateTyped", "(JJIIJ)J", (void*)nAllocationCreateTyped }, +{"rsnAllocationCreateFromBitmap", "(JJIJI)J", (void*)nAllocationCreateFromBitmap }, +{"rsnAllocationCreateBitmapBackedAllocation", "(JJIJI)J", (void*)nAllocationCreateBitmapBackedAllocation }, +{"rsnAllocationCubeCreateFromBitmap","(JJIJI)J", (void*)nAllocationCubeCreateFromBitmap }, -{"rsnAllocationCopyFromBitmap", "(JJLandroid/graphics/Bitmap;)V", (void*)nAllocationCopyFromBitmap }, -{"rsnAllocationCopyToBitmap", "(JJLandroid/graphics/Bitmap;)V", (void*)nAllocationCopyToBitmap }, +{"rsnAllocationCopyFromBitmap", "(JJJ)V", (void*)nAllocationCopyFromBitmap }, +{"rsnAllocationCopyToBitmap", "(JJJ)V", (void*)nAllocationCopyToBitmap }, {"rsnAllocationSyncAll", "(JJI)V", (void*)nAllocationSyncAll }, {"rsnAllocationSetupBufferQueue", "(JJI)V", (void*)nAllocationSetupBufferQueue }, diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 3d918fc052c8..0f39029f47b9 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -3825,6 +3825,7 @@ class AlarmManagerService extends SystemService { Slog.w(TAG, "Failure sending alarm.", e); } Trace.traceEnd(Trace.TRACE_TAG_POWER); + decrementAlarmCount(alarm.uid); } } @@ -4148,6 +4149,10 @@ class AlarmManagerService extends SystemService { public void handleMessage(Message msg) { switch (msg.what) { case ALARM_EVENT: { + // This code is used when the kernel timer driver is not available, which + // shouldn't happen. Here, we try our best to simulate it, which may be useful + // when porting Android to a new device. Note that we can't wake up a device + // this way, so WAKE_UP alarms will be delivered only when the device is awake. ArrayList<Alarm> triggerList = new ArrayList<Alarm>(); synchronized (mLock) { final long nowELAPSED = mInjector.getElapsedRealtime(); @@ -4167,6 +4172,7 @@ class AlarmManagerService extends SystemService { removeImpl(alarm.operation, null); } } + decrementAlarmCount(alarm.uid); } break; } @@ -4760,7 +4766,6 @@ class AlarmManagerService extends SystemService { mAppWakeupHistory.recordAlarmForPackage(alarm.sourcePackage, UserHandle.getUserId(alarm.creatorUid), nowELAPSED); } - decrementAlarmCount(alarm.uid); final BroadcastStats bs = inflight.mBroadcastStats; bs.count++; if (bs.nesting == 0) { diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java index f0f8adbb6dda..33b846f7bb52 100644 --- a/services/core/java/com/android/server/DropBoxManagerService.java +++ b/services/core/java/com/android/server/DropBoxManagerService.java @@ -23,6 +23,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources; import android.database.ContentObserver; import android.net.Uri; import android.os.Binder; @@ -32,6 +33,9 @@ import android.os.FileUtils; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.ResultReceiver; +import android.os.ShellCallback; +import android.os.ShellCommand; import android.os.StatFs; import android.os.SystemClock; import android.os.UserHandle; @@ -39,8 +43,11 @@ import android.provider.Settings; import android.text.TextUtils; import android.text.format.Time; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Slog; +import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.IDropBoxManagerService; import com.android.internal.util.DumpUtils; @@ -76,9 +83,6 @@ public final class DropBoxManagerService extends SystemService { private static final int DEFAULT_RESERVE_PERCENT = 10; private static final int QUOTA_RESCAN_MILLIS = 5000; - // mHandler 'what' value. - private static final int MSG_SEND_BROADCAST = 1; - private static final boolean PROFILE_DUMP = false; // TODO: This implementation currently uses one file per entry, which is @@ -95,6 +99,9 @@ public final class DropBoxManagerService extends SystemService { private FileList mAllFiles = null; private ArrayMap<String, FileList> mFilesByTag = null; + private long mLowPriorityRateLimitPeriod = 0; + private ArraySet<String> mLowPriorityTags = null; + // Various bits of disk information private StatFs mStatFs = null; @@ -105,7 +112,7 @@ public final class DropBoxManagerService extends SystemService { private volatile boolean mBooted = false; // Provide a way to perform sendBroadcast asynchronously to avoid deadlocks. - private final Handler mHandler; + private final DropBoxManagerBroadcastHandler mHandler; private int mMaxFiles = -1; // -1 means uninitialized. @@ -152,8 +159,142 @@ public final class DropBoxManagerService extends SystemService { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { DropBoxManagerService.this.dump(fd, pw, args); } + + @Override + public void onShellCommand(FileDescriptor in, FileDescriptor out, + FileDescriptor err, String[] args, ShellCallback callback, + ResultReceiver resultReceiver) { + (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver); + } }; + private class ShellCmd extends ShellCommand { + @Override + public int onCommand(String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + final PrintWriter pw = getOutPrintWriter(); + try { + switch (cmd) { + case "set-rate-limit": + final long period = Long.parseLong(getNextArgRequired()); + DropBoxManagerService.this.setLowPriorityRateLimit(period); + break; + case "add-low-priority": + final String addedTag = getNextArgRequired(); + DropBoxManagerService.this.addLowPriorityTag(addedTag); + break; + case "remove-low-priority": + final String removeTag = getNextArgRequired(); + DropBoxManagerService.this.removeLowPriorityTag(removeTag); + break; + case "restore-defaults": + DropBoxManagerService.this.restoreDefaults(); + break; + default: + return handleDefaultCommands(cmd); + } + } catch (Exception e) { + pw.println(e); + } + return 0; + } + + @Override + public void onHelp() { + PrintWriter pw = getOutPrintWriter(); + pw.println("Dropbox manager service commands:"); + pw.println(" help"); + pw.println(" Print this help text."); + pw.println(" set-rate-limit PERIOD"); + pw.println(" Sets low priority broadcast rate limit period to PERIOD ms"); + pw.println(" add-low-priority TAG"); + pw.println(" Add TAG to dropbox low priority list"); + pw.println(" remove-low-priority TAG"); + pw.println(" Remove TAG from dropbox low priority list"); + pw.println(" restore-defaults"); + pw.println(" restore dropbox settings to defaults"); + } + } + + private class DropBoxManagerBroadcastHandler extends Handler { + private final Object mLock = new Object(); + + static final int MSG_SEND_BROADCAST = 1; + static final int MSG_SEND_DEFERRED_BROADCAST = 2; + + @GuardedBy("mLock") + private final ArrayMap<String, Intent> mDeferredMap = new ArrayMap(); + + DropBoxManagerBroadcastHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SEND_BROADCAST: + prepareAndSendBroadcast((Intent) msg.obj); + break; + case MSG_SEND_DEFERRED_BROADCAST: + Intent deferredIntent; + synchronized (mLock) { + deferredIntent = mDeferredMap.remove((String) msg.obj); + } + if (deferredIntent != null) { + prepareAndSendBroadcast(deferredIntent); + } + break; + } + } + + private void prepareAndSendBroadcast(Intent intent) { + if (!DropBoxManagerService.this.mBooted) { + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + } + getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM, + android.Manifest.permission.READ_LOGS); + } + + private Intent createIntent(String tag, long time) { + final Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED); + dropboxIntent.putExtra(DropBoxManager.EXTRA_TAG, tag); + dropboxIntent.putExtra(DropBoxManager.EXTRA_TIME, time); + return dropboxIntent; + } + + /** + * Schedule a dropbox broadcast to be sent asynchronously. + */ + public void sendBroadcast(String tag, long time) { + sendMessage(obtainMessage(MSG_SEND_BROADCAST, createIntent(tag, time))); + } + + /** + * Possibly schedule a delayed dropbox broadcast. The broadcast will only be scheduled if + * no broadcast is currently scheduled. Otherwise updated the scheduled broadcast with the + * new intent information, effectively dropping the previous broadcast. + */ + public void maybeDeferBroadcast(String tag, long time) { + synchronized (mLock) { + final Intent intent = mDeferredMap.get(tag); + if (intent == null) { + // Schedule new delayed broadcast. + mDeferredMap.put(tag, createIntent(tag, time)); + sendMessageDelayed(obtainMessage(MSG_SEND_DEFERRED_BROADCAST, tag), + mLowPriorityRateLimitPeriod); + } else { + // Broadcast is already scheduled. Update intent with new data. + intent.putExtra(DropBoxManager.EXTRA_TIME, time); + final int dropped = intent.getIntExtra(DropBoxManager.EXTRA_DROPPED_COUNT, 0); + intent.putExtra(DropBoxManager.EXTRA_DROPPED_COUNT, dropped + 1); + return; + } + } + } + } + /** * Creates an instance of managed drop box storage using the default dropbox * directory. @@ -176,15 +317,7 @@ public final class DropBoxManagerService extends SystemService { super(context); mDropBoxDir = path; mContentResolver = getContext().getContentResolver(); - mHandler = new Handler(looper) { - @Override - public void handleMessage(Message msg) { - if (msg.what == MSG_SEND_BROADCAST) { - getContext().sendBroadcastAsUser((Intent)msg.obj, UserHandle.SYSTEM, - android.Manifest.permission.READ_LOGS); - } - } - }; + mHandler = new DropBoxManagerBroadcastHandler(looper); } @Override @@ -211,6 +344,8 @@ public final class DropBoxManagerService extends SystemService { mReceiver.onReceive(getContext(), (Intent) null); } }); + + getLowPriorityResourceConfigs(); break; case PHASE_BOOT_COMPLETED: @@ -298,17 +433,16 @@ public final class DropBoxManagerService extends SystemService { long time = createEntry(temp, tag, flags); temp = null; - final Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED); - dropboxIntent.putExtra(DropBoxManager.EXTRA_TAG, tag); - dropboxIntent.putExtra(DropBoxManager.EXTRA_TIME, time); - if (!mBooted) { - dropboxIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - } // Call sendBroadcast after returning from this call to avoid deadlock. In particular // the caller may be holding the WindowManagerService lock but sendBroadcast requires a // lock in ActivityManagerService. ActivityManagerService has been caught holding that // very lock while waiting for the WindowManagerService lock. - mHandler.sendMessage(mHandler.obtainMessage(MSG_SEND_BROADCAST, dropboxIntent)); + if (mLowPriorityTags != null && mLowPriorityTags.contains(tag)) { + // Rate limit low priority Dropbox entries + mHandler.maybeDeferBroadcast(tag, time); + } else { + mHandler.sendBroadcast(tag, time); + } } catch (IOException e) { Slog.e(TAG, "Can't write: " + tag, e); } finally { @@ -382,6 +516,22 @@ public final class DropBoxManagerService extends SystemService { return null; } + private synchronized void setLowPriorityRateLimit(long period) { + mLowPriorityRateLimitPeriod = period; + } + + private synchronized void addLowPriorityTag(String tag) { + mLowPriorityTags.add(tag); + } + + private synchronized void removeLowPriorityTag(String tag) { + mLowPriorityTags.remove(tag); + } + + private synchronized void restoreDefaults() { + getLowPriorityResourceConfigs(); + } + public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return; @@ -421,6 +571,10 @@ public final class DropBoxManagerService extends SystemService { out.append("Drop box contents: ").append(mAllFiles.contents.size()).append(" entries\n"); out.append("Max entries: ").append(mMaxFiles).append("\n"); + out.append("Low priority rate limit period: "); + out.append(mLowPriorityRateLimitPeriod).append(" ms\n"); + out.append("Low priority tags: ").append(mLowPriorityTags).append("\n"); + if (!searchArgs.isEmpty()) { out.append("Searching for:"); for (String a : searchArgs) out.append(" ").append(a); @@ -936,4 +1090,21 @@ public final class DropBoxManagerService extends SystemService { return mCachedQuotaBlocks * mBlockSize; } + + private void getLowPriorityResourceConfigs() { + mLowPriorityRateLimitPeriod = Resources.getSystem().getInteger( + R.integer.config_dropboxLowPriorityBroadcastRateLimitPeriod); + + final String[] lowPrioritytags = Resources.getSystem().getStringArray( + R.array.config_dropboxLowPriorityTags); + final int size = lowPrioritytags.length; + if (size == 0) { + mLowPriorityTags = null; + return; + } + mLowPriorityTags = new ArraySet(size); + for (int i = 0; i < size; i++) { + mLowPriorityTags.add(lowPrioritytags[i]); + } + } } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index f0244c303360..2ded1e58bf2d 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -200,8 +200,8 @@ public class LocationManagerService extends ILocationManager.Stub { private GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider; private GnssNavigationMessageProvider mGnssNavigationMessageProvider; @GuardedBy("mLock") - private String mLocationControllerExtraPackage; - private boolean mLocationControllerExtraPackageEnabled; + private String mExtraLocationControllerPackage; + private boolean mExtraLocationControllerPackageEnabled; private IGpsGeofenceHardware mGpsGeofenceProxy; // list of currently active providers @@ -3045,35 +3045,35 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public void setLocationControllerExtraPackage(String packageName) { + public void setExtraLocationControllerPackage(String packageName) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, Manifest.permission.LOCATION_HARDWARE + " permission required"); synchronized (mLock) { - mLocationControllerExtraPackage = packageName; + mExtraLocationControllerPackage = packageName; } } @Override - public String getLocationControllerExtraPackage() { + public String getExtraLocationControllerPackage() { synchronized (mLock) { - return mLocationControllerExtraPackage; + return mExtraLocationControllerPackage; } } @Override - public void setLocationControllerExtraPackageEnabled(boolean enabled) { + public void setExtraLocationControllerPackageEnabled(boolean enabled) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, Manifest.permission.LOCATION_HARDWARE + " permission required"); synchronized (mLock) { - mLocationControllerExtraPackageEnabled = enabled; + mExtraLocationControllerPackageEnabled = enabled; } } @Override - public boolean isLocationControllerExtraPackageEnabled() { + public boolean isExtraLocationControllerPackageEnabled() { synchronized (mLock) { - return mLocationControllerExtraPackageEnabled - && (mLocationControllerExtraPackage != null); + return mExtraLocationControllerPackageEnabled + && (mExtraLocationControllerPackage != null); } } @@ -3610,9 +3610,9 @@ public class LocationManagerService extends ILocationManager.Stub { pw.println(" mBlacklist=null"); } - if (mLocationControllerExtraPackage != null) { - pw.println(" Location controller extra package: " + mLocationControllerExtraPackage - + " enabled: " + mLocationControllerExtraPackageEnabled); + if (mExtraLocationControllerPackage != null) { + pw.println(" Location controller extra package: " + mExtraLocationControllerPackage + + " enabled: " + mExtraLocationControllerPackageEnabled); } if (!mBackgroundThrottlePackageWhitelist.isEmpty()) { diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 5b9c1f8d6f24..1a842f72fcb4 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -17,10 +17,14 @@ package com.android.server; import static android.Manifest.permission.INSTALL_PACKAGES; +import static android.Manifest.permission.READ_EXTERNAL_STORAGE; +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_MEDIA_STORAGE; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_LEGACY_STORAGE; +import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES; +import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE; import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN; import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; import static android.content.pm.PackageManager.GET_PERMISSIONS; @@ -280,6 +284,7 @@ class StorageManagerService extends IStorageManager.Stub private static final boolean EMULATE_FBE_SUPPORTED = true; private static final String TAG = "StorageManagerService"; + private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE); private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark"; private static final String TAG_STORAGE_TRIM = "storage_trim"; @@ -3863,44 +3868,57 @@ class StorageManagerService extends IStorageManager.Stub } private int getMountMode(int uid, String packageName) { + final int mode = getMountModeInternal(uid, packageName); + if (LOCAL_LOGV) { + Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/" + + UserHandle.formatUid(uid)); + } + return mode; + } + + private int getMountModeInternal(int uid, String packageName) { try { + // Get some easy cases out of the way first if (Process.isIsolated(uid)) { return Zygote.MOUNT_EXTERNAL_NONE; } - if (mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid) - == PERMISSION_GRANTED) { + if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { + return Zygote.MOUNT_EXTERNAL_NONE; + } + + // Determine if caller is holding runtime permission + final boolean hasRead = StorageManager.checkPermissionAndAppOp(mContext, false, 0, + uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE); + final boolean hasWrite = StorageManager.checkPermissionAndAppOp(mContext, false, 0, + uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE); + final boolean hasStorage = hasRead || hasWrite; + + // We're only willing to give out broad access if they also hold + // runtime permission; this is a firm CDD requirement + final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, + uid) == PERMISSION_GRANTED; + if (hasFull && hasStorage) { return Zygote.MOUNT_EXTERNAL_FULL; - } else if (mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid, - packageName) == MODE_ALLOWED) { - return Zygote.MOUNT_EXTERNAL_LEGACY; - } else if (mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid) - == PERMISSION_GRANTED || mIAppOpsService.checkOperation( - OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED) { + } + + // We're only willing to give out installer access if they also hold + // runtime permission; this is a firm CDD requirement + final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES, + uid) == PERMISSION_GRANTED; + final boolean hasInstallOp = mIAppOpsService.checkOperation(OP_REQUEST_INSTALL_PACKAGES, + uid, packageName) == MODE_ALLOWED; + if ((hasInstall || hasInstallOp) && hasStorage) { return Zygote.MOUNT_EXTERNAL_INSTALLER; - } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { - return Zygote.MOUNT_EXTERNAL_NONE; + } + + // Otherwise we're willing to give out sandboxed or non-sandboxed if + // they hold the runtime permission + final boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, + uid, packageName) == MODE_ALLOWED; + final boolean hasGreylist = isLegacyGreylisted(packageName); + if ((hasLegacy || hasGreylist) && hasStorage) { + return Zygote.MOUNT_EXTERNAL_LEGACY; } else { - if (ENABLE_LEGACY_GREYLIST) { - // STOPSHIP: remove this temporary workaround once developers - // fix bugs where they're opening _data paths in native code - switch (packageName) { - case "com.facebook.katana": // b/123996076 - case "jp.naver.line.android": // b/124767356 - case "com.mxtech.videoplayer.ad": // b/124531483 - case "com.whatsapp": // b/124766614 - case "com.maxmpz.audioplayer": // b/127886230 - case "com.estrongs.android.pop": // b/127926473 - case "com.roidapp.photogrid": // b/128269119 - case "com.cleanmaster.mguard": // b/128384413 - case "com.skype.raider": // b/128487044 - case "org.telegram.messenger": // b/128652960 - case "com.jrtstudio.AnotherMusicPlayer": // b/129084562 - case "ak.alizandro.smartaudiobookplayer": // b/129084042 - case "com.campmobile.snow": // b/128803870 - case "com.qnap.qfile": // b/126374406 - return Zygote.MOUNT_EXTERNAL_LEGACY; - } - } return Zygote.MOUNT_EXTERNAL_WRITE; } } catch (RemoteException e) { @@ -3909,6 +3927,32 @@ class StorageManagerService extends IStorageManager.Stub return Zygote.MOUNT_EXTERNAL_NONE; } + private boolean isLegacyGreylisted(String packageName) { + // TODO: decide legacy defaults at install time based on signals + if (ENABLE_LEGACY_GREYLIST) { + // STOPSHIP: remove this temporary workaround once developers + // fix bugs where they're opening _data paths in native code + switch (packageName) { + case "com.facebook.katana": // b/123996076 + case "jp.naver.line.android": // b/124767356 + case "com.mxtech.videoplayer.ad": // b/124531483 + case "com.whatsapp": // b/124766614 + case "com.maxmpz.audioplayer": // b/127886230 + case "com.estrongs.android.pop": // b/127926473 + case "com.roidapp.photogrid": // b/128269119 + case "com.cleanmaster.mguard": // b/128384413 + case "com.skype.raider": // b/128487044 + case "org.telegram.messenger": // b/128652960 + case "com.jrtstudio.AnotherMusicPlayer": // b/129084562 + case "ak.alizandro.smartaudiobookplayer": // b/129084042 + case "com.campmobile.snow": // b/128803870 + case "com.qnap.qfile": // b/126374406 + return true; + } + } + return false; + } + private static class Callbacks extends Handler { private static final int MSG_STORAGE_STATE_CHANGED = 1; private static final int MSG_VOLUME_STATE_CHANGED = 2; diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 1878d00ba9f9..cef245ba332f 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1478,7 +1478,6 @@ public final class ActiveServices { if (sr.isForeground || sr.fgRequired) { anyForeground = true; fgServiceTypes |= sr.foregroundServiceType; - break; } } mAm.updateProcessForegroundLocked(proc, anyForeground, fgServiceTypes, oomAdj); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index e39c6ac29104..73393ed6e095 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -271,6 +271,7 @@ import android.os.UserManager; import android.os.WorkSource; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; +import android.provider.DeviceConfig; import android.provider.Settings; import android.sysprop.VoldProperties; import android.text.TextUtils; @@ -1750,7 +1751,6 @@ public class ActivityManagerService extends IActivityManager.Stub ? R.string.dump_heap_ready_notification : R.string.dump_heap_notification; String text = mContext.getString(titleId, procName); - Intent deleteIntent = new Intent(); deleteIntent.setAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP); Intent intent = new Intent(); @@ -1766,8 +1766,6 @@ public class ActivityManagerService extends IActivityManager.Stub Notification notification = new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER) .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) - .setWhen(0) - .setOngoing(true) .setAutoCancel(true) .setTicker(text) .setColor(mContext.getColor( @@ -2154,7 +2152,8 @@ public class ActivityManagerService extends IActivityManager.Stub * Encapsulates global settings related to hidden API enforcement behaviour, including tracking * the latest value via a content observer. */ - static class HiddenApiSettings extends ContentObserver { + static class HiddenApiSettings extends ContentObserver + implements DeviceConfig.OnPropertiesChangedListener { private final Context mContext; private boolean mBlacklistDisabled; @@ -2164,6 +2163,45 @@ public class ActivityManagerService extends IActivityManager.Stub private int mStatslogSampleRate = -1; @HiddenApiEnforcementPolicy private int mPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT; + /** + * Sampling rate for hidden API access event logs with libmetricslogger, as an integer in + * the range 0 to 0x10000 inclusive. + * + * @hide + */ + public static final String HIDDEN_API_ACCESS_LOG_SAMPLING_RATE = + "hidden_api_access_log_sampling_rate"; + + /** + * Sampling rate for hidden API access event logging with statslog, as an integer in the + * range 0 to 0x10000 inclusive. + * + * @hide + */ + public static final String HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE = + "hidden_api_access_statslog_sampling_rate"; + + public void onPropertiesChanged(DeviceConfig.Properties properties) { + int logSampleRate = properties.getInt(HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, 0x0); + if (logSampleRate < 0 || logSampleRate > 0x10000) { + logSampleRate = -1; + } + if (logSampleRate != -1 && logSampleRate != mLogSampleRate) { + mLogSampleRate = logSampleRate; + ZYGOTE_PROCESS.setHiddenApiAccessLogSampleRate(mLogSampleRate); + } + + int statslogSampleRate = + properties.getInt(HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE, 0); + if (statslogSampleRate < 0 || statslogSampleRate > 0x10000) { + statslogSampleRate = -1; + } + if (statslogSampleRate != -1 && statslogSampleRate != mStatslogSampleRate) { + mStatslogSampleRate = statslogSampleRate; + ZYGOTE_PROCESS.setHiddenApiAccessStatslogSampleRate(mStatslogSampleRate); + } + } + public HiddenApiSettings(Handler handler, Context context) { super(handler); mContext = context; @@ -2175,18 +2213,11 @@ public class ActivityManagerService extends IActivityManager.Stub false, this); mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor(Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE), - false, - this); - mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor( - Settings.Global.HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE), - false, - this); - mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY), false, this); + DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_APP_COMPAT, + mContext.getMainExecutor(), this); update(); } @@ -2210,24 +2241,6 @@ public class ActivityManagerService extends IActivityManager.Stub mExemptions = Collections.emptyList(); } } - int logSampleRate = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, 0x200); - if (logSampleRate < 0 || logSampleRate > 0x10000) { - logSampleRate = -1; - } - if (logSampleRate != -1 && logSampleRate != mLogSampleRate) { - mLogSampleRate = logSampleRate; - ZYGOTE_PROCESS.setHiddenApiAccessLogSampleRate(mLogSampleRate); - } - int statslogSampleRate = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE, 0); - if (statslogSampleRate < 0 || statslogSampleRate > 0x10000) { - statslogSampleRate = -1; - } - if (statslogSampleRate != -1 && statslogSampleRate != mStatslogSampleRate) { - mStatslogSampleRate = statslogSampleRate; - ZYGOTE_PROCESS.setHiddenApiAccessStatslogSampleRate(mStatslogSampleRate); - } mPolicy = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY); } @@ -5077,11 +5090,9 @@ public class ActivityManagerService extends IActivityManager.Stub mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (intent.getBooleanExtra(DumpHeapActivity.EXTRA_DELAY_DELETE, false)) { - mHandler.sendEmptyMessageDelayed(POST_DUMP_HEAP_NOTIFICATION_MSG, 5*60*1000); - } else { - mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG); - } + final long delay = intent.getBooleanExtra( + DumpHeapActivity.EXTRA_DELAY_DELETE, false) ? 5 * 60 * 1000 : 0; + mHandler.sendEmptyMessageDelayed(DELETE_DUMPHEAP_MSG, delay); } }, dumpheapFilter); @@ -8824,6 +8835,7 @@ public class ActivityManagerService extends IActivityManager.Stub mAtmInternal.updateTopComponentForFactoryTest(); retrieveSettings(); + final int currentUserId = mUserController.getCurrentUserId(); mUgmInternal.onSystemReady(); final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class); @@ -8837,16 +8849,6 @@ public class ActivityManagerService extends IActivityManager.Stub } if (goingCallback != null) goingCallback.run(); - // Check the current user here as a user can be started inside goingCallback.run() from - // other system services. - final int currentUserId = mUserController.getCurrentUserId(); - Slog.i(TAG, "Current user:" + currentUserId); - if (currentUserId != UserHandle.USER_SYSTEM && !mUserController.isSystemUserStarted()) { - // User other than system user has started. Make sure that system user is already - // started before switching user. - throw new RuntimeException("System user not started while current user is:" - + currentUserId); - } traceLog.traceBegin("ActivityManagerStartApps"); mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START, Integer.toString(currentUserId), currentUserId); @@ -16382,12 +16384,10 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("this") final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground, int fgServiceTypes, boolean oomAdj) { - proc.setHasForegroundServices(isForeground, fgServiceTypes); - final boolean hasFgServiceLocationType = - (fgServiceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION) != 0; if (isForeground != proc.hasForegroundServices() - || proc.hasLocationForegroundServices() != hasFgServiceLocationType) { + || proc.getForegroundServiceTypes() != fgServiceTypes) { + proc.setHasForegroundServices(isForeground, fgServiceTypes); ArrayList<ProcessRecord> curProcs = mForegroundPackages.get(proc.info.packageName, proc.info.uid); if (isForeground) { @@ -16412,16 +16412,15 @@ public class ActivityManagerService extends IActivityManager.Stub } } } - if (oomAdj) { - updateOomAdjLocked(); - } - } - if (proc.getForegroundServiceTypes() != fgServiceTypes) { proc.setReportedForegroundServiceTypes(fgServiceTypes); ProcessChangeItem item = enqueueProcessChangeItemLocked(proc.info.uid, proc.pid); item.changes = ProcessChangeItem.CHANGE_FOREGROUND_SERVICES; item.foregroundServiceTypes = fgServiceTypes; + + if (oomAdj) { + updateOomAdjLocked(); + } } } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index ea23081b8447..4bfbb78e4187 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -460,10 +460,9 @@ public final class BroadcastQueue { // that request - we don't want the token to be swept from under our feet... mHandler.removeCallbacksAndMessages(msgToken); // ...then schedule the removal of the token after the extended timeout + final ProcessRecord app = r.curApp; mHandler.postAtTime(() -> { - if (r.curApp != null) { - r.curApp.removeAllowBackgroundActivityStartsToken(r); - } + app.removeAllowBackgroundActivityStartsToken(r); }, msgToken, (r.receiverTime + mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT)); } } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 17b244c75819..a90e994c1ee8 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -561,6 +561,13 @@ class ProcessRecord implements WindowProcessListener { pw.print(prefix); pw.print(" - "); pw.println(receivers.valueAt(i)); } } + if (mAllowBackgroundActivityStartsTokens.size() > 0) { + pw.print(prefix); pw.println("Background activity start whitelist tokens:"); + for (int i = 0; i < mAllowBackgroundActivityStartsTokens.size(); i++) { + pw.print(prefix); pw.print(" - "); + pw.println(mAllowBackgroundActivityStartsTokens.valueAt(i)); + } + } } ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName, diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 688020f0cc0c..07c9cca3f6c3 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -1743,24 +1743,6 @@ class UserController implements Handler.Callback { return state.state != UserState.STATE_STOPPING && state.state != UserState.STATE_SHUTDOWN; } - /** - * Check if system user is already started. Unlike other user, system user is in STATE_BOOTING - * even if it is not explicitly started. So isUserRunning cannot give the right state - * to check if system user is started or not. - * @return true if system user is started. - */ - boolean isSystemUserStarted() { - synchronized (mLock) { - UserState uss = mStartedUsers.get(UserHandle.USER_SYSTEM); - if (uss == null) { - return false; - } - return uss.state == UserState.STATE_RUNNING_LOCKED - || uss.state == UserState.STATE_RUNNING_UNLOCKING - || uss.state == UserState.STATE_RUNNING_UNLOCKED; - } - } - UserInfo getCurrentUser() { if ((mInjector.checkCallingPermission(INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) && ( diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 93f7831e8886..82a4f1df2e10 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -6360,9 +6360,20 @@ public class AudioService extends IAudioService.Stub boolean isLoopbackRenderPolicy = policyConfig.getMixes().stream().allMatch( mix -> mix.getRouteFlags() == (mix.ROUTE_FLAG_RENDER | mix.ROUTE_FLAG_LOOP_BACK)); - // Policy that do not modify the audio routing only need an audio projection - if (isLoopbackRenderPolicy && canProjectAudio(projection)) { - return true; + if (isLoopbackRenderPolicy) { + boolean allowPrivilegedPlaybackCapture = policyConfig.getMixes().stream().anyMatch( + mix -> mix.getRule().allowPrivilegedPlaybackCapture()); + if (allowPrivilegedPlaybackCapture + && !(hasPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) + || hasPermission(android.Manifest.permission.CAPTURE_MEDIA_OUTPUT))) { + // Opt-out can not be bypassed without a system permission + return false; + } + + if (canProjectAudio(projection)) { + // Policy that do not modify the audio routing only need an audio projection + return true; + } } boolean hasPermissionModifyAudioRouting = @@ -6373,6 +6384,9 @@ public class AudioService extends IAudioService.Stub } return false; } + private boolean hasPermission(String permission) { + return PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(permission); + } /** @return true if projection is a valid MediaProjection that can project audio. */ private boolean canProjectAudio(IMediaProjection projection) { diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index ce887eb4f0fe..d7a57b992eef 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -154,12 +154,19 @@ public class KeepaliveTracker { // keepalives are sent cannot be reused by another app even if the fd gets closed by // the user. A null is acceptable here for backward compatibility of PacketKeepalive // API. - // TODO: don't accept null fd after legacy packetKeepalive API is removed. try { if (fd != null) { mFd = Os.dup(fd); } else { - Log.d(TAG, "uid/pid " + mUid + "/" + mPid + " calls with null fd"); + Log.d(TAG, toString() + " calls with null fd"); + if (!mPrivileged) { + throw new SecurityException( + "null fd is not allowed for unprivileged access."); + } + if (mType == TYPE_TCP) { + throw new IllegalArgumentException( + "null fd is not allowed for tcp socket keepalives."); + } mFd = null; } } catch (ErrnoException e) { @@ -480,7 +487,6 @@ public class KeepaliveTracker { } } else { // Keepalive successfully stopped, or error. - ki.mStartedState = KeepaliveInfo.NOT_STARTED; if (reason == SUCCESS) { // The message indicated success stopping : don't call handleStopKeepalive. if (DBG) Log.d(TAG, "Successfully stopped keepalive " + slot + " on " + nai.name()); @@ -490,6 +496,7 @@ public class KeepaliveTracker { handleStopKeepalive(nai, slot, reason); if (DBG) Log.d(TAG, "Keepalive " + slot + " on " + nai.name() + " error " + reason); } + ki.mStartedState = KeepaliveInfo.NOT_STARTED; } } @@ -531,7 +538,8 @@ public class KeepaliveTracker { try { ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, KeepaliveInfo.TYPE_NATT, fd); - } catch (InvalidSocketException e) { + } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) { + Log.e(TAG, "Fail to construct keepalive", e); notifyErrorCallback(cb, ERROR_INVALID_SOCKET); return; } @@ -570,7 +578,8 @@ public class KeepaliveTracker { try { ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, KeepaliveInfo.TYPE_TCP, fd); - } catch (InvalidSocketException e) { + } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) { + Log.e(TAG, "Fail to construct keepalive e=" + e); notifyErrorCallback(cb, ERROR_INVALID_SOCKET); return; } diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java index df0dc77613b1..b4c7dd310dd0 100755 --- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java +++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java @@ -335,7 +335,6 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { current.mDeviceType = params[2] & 0xFF; current.mDisplayName = HdmiUtils.getDefaultDeviceName(current.mDeviceType); - // TODO(amyjojo): check if non-TV device needs to update cec switch info. // This is to manager CEC device separately in case they don't have address. if (mIsTvDevice) { tv().updateCecSwitchInfo(current.mLogicalAddress, current.mDeviceType, diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 2026957b6c44..10f7db5e3a73 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -314,7 +314,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { super.disableDevice(initiatedByCec, callback); assertRunOnServiceThread(); mService.unregisterTvInputCallback(mTvInputCallback); - // TODO(amyjojo): check disableDevice and onStandby behaviors per spec + // TODO(b/129088603): check disableDevice and onStandby behaviors per spec } @Override @@ -465,15 +465,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { @Override @ServiceThreadOnly - protected boolean handleReportAudioStatus(HdmiCecMessage message) { - assertRunOnServiceThread(); - // TODO(amyjojo): implement report audio status handler - HdmiLogger.debug(TAG + "Stub handleReportAudioStatus"); - return true; - } - - @Override - @ServiceThreadOnly protected boolean handleInitiateArc(HdmiCecMessage message) { assertRunOnServiceThread(); // TODO(amyjojo): implement initiate arc handler diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index f5adb0111559..3398d36ffdb9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -1764,7 +1764,7 @@ public class HdmiControlService extends SystemService { } @Override - // TODO(AMYJOJO): add a result callback + // TODO(b/128427908): add a result callback public void askRemoteDeviceToBecomeActiveSource(int physicalAddress) { enforceAccessPermission(); runOnServiceThread(new Runnable() { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index dddb7efca50b..20b898760389 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2406,6 +2406,11 @@ public class NotificationManagerService extends SystemService { @Override public boolean areNotificationsEnabledForPackage(String pkg, int uid) { checkCallerIsSystemOrSameApp(pkg); + if (UserHandle.getCallingUserId() != UserHandle.getUserId(uid)) { + getContext().enforceCallingPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS, + "canNotifyAsPackage for uid " + uid); + } return mPreferencesHelper.getImportance(pkg, uid) != IMPORTANCE_NONE; } @@ -2419,6 +2424,13 @@ public class NotificationManagerService extends SystemService { public boolean areBubblesAllowedForPackage(String pkg, int uid) { enforceSystemOrSystemUIOrSamePackage(pkg, "Caller not system or systemui or same package"); + + if (UserHandle.getCallingUserId() != UserHandle.getUserId(uid)) { + getContext().enforceCallingPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS, + "canNotifyAsPackage for uid " + uid); + } + return mPreferencesHelper.areBubblesAllowed(pkg, uid); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index ad17549d7448..afa5ae907fc0 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -808,7 +808,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, statusReceiver, versionedPackage.getPackageName(), - canSilentlyInstallPackage, userId); + !canSilentlyInstallPackage, userId); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES) == PackageManager.PERMISSION_GRANTED) { // Sweet, call straight through! diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 81448b7c7129..eec1e539b2d7 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1315,8 +1315,11 @@ public class PackageManagerService extends IPackageManager.Stub static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds - // Delay time in millisecs - static final int BROADCAST_DELAY = 10 * 1000; + private static final long BROADCAST_DELAY_DURING_STARTUP = 10 * 1000L; // 10 seconds (in millis) + private static final long BROADCAST_DELAY = 1 * 1000L; // 1 second (in millis) + + // When the service constructor finished plus a delay (used for broadcast delay computation) + private long mServiceStartWithDelay; private static final long DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD = 2 * 60 * 60 * 1000L; /* two hours */ @@ -3217,6 +3220,8 @@ public class PackageManagerService extends IPackageManager.Stub // once we have a booted system. mInstaller.setWarnIfHeld(mPackages); + mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L); + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } @@ -20603,8 +20608,14 @@ public class PackageManagerService extends IPackageManager.Stub mPendingBroadcasts.put(userId, packageName, components); } if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { - // Schedule a message - mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY); + // Schedule a message - if it has been a "reasonably long time" since the + // service started, send the broadcast with a delay of one second to avoid + // delayed reactions from the receiver, else keep the default ten second delay + // to avoid extreme thrashing on service startup. + final long broadcastDelay = SystemClock.uptimeMillis() > mServiceStartWithDelay + ? BROADCAST_DELAY + : BROADCAST_DELAY_DURING_STARTUP; + mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, broadcastDelay); } } } diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 28a853ff6767..15148f3af194 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -44,6 +44,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; @@ -149,6 +150,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -2010,6 +2012,40 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } + private void pullAppsOnExternalStorageInfo(int tagId, long elapsedNanos, long wallClockNanos, + List<StatsLogEventWrapper> pulledData) { + PackageManager pm = mContext.getPackageManager(); + StorageManager storage = mContext.getSystemService(StorageManager.class); + List<ApplicationInfo> apps = pm.getInstalledApplications(/* flags = */ 0); + for (ApplicationInfo appInfo : apps) { + UUID storageUuid = appInfo.storageUuid; + if (storageUuid != null) { + VolumeInfo volumeInfo = storage.findVolumeByUuid(appInfo.storageUuid.toString()); + if (volumeInfo != null) { + DiskInfo diskInfo = volumeInfo.getDisk(); + if (diskInfo != null) { + int externalStorageType = -1; + if (diskInfo.isSd()) { + externalStorageType = StorageEnums.SD_CARD; + } else if (diskInfo.isUsb()) { + externalStorageType = StorageEnums.USB; + } else if (appInfo.isExternal()) { + externalStorageType = StorageEnums.OTHER; + } + // App is installed on external storage. + if (externalStorageType != -1) { + StatsLogEventWrapper e = + new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); + e.writeInt(externalStorageType); + e.writeString(appInfo.packageName); + pulledData.add(e); + } + } + } + } + } + } + /** * Pulls various data. */ @@ -2210,6 +2246,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { pullExternalStorageInfo(tagId, elapsedNanos, wallClockNanos, ret); break; } + case StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO: { + pullAppsOnExternalStorageInfo(tagId, elapsedNanos, wallClockNanos, ret); + break; + } default: Slog.w(TAG, "No such tagId data as " + tagId); return null; diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 5502bb98564f..0c9f81525509 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -2669,6 +2669,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } wallpaper.connection.mReply = null; } + try { + wallpaper.connection.mService.detach(); + } catch (RemoteException e) { + Slog.w(TAG, "Failed detaching wallpaper service ", e); + } mContext.unbindService(wallpaper.connection); wallpaper.connection.forEachDisplayConnector( WallpaperConnection.DisplayConnector::disconnectLocked); diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 2d89bc7c5613..d916e39c2531 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -85,6 +85,7 @@ import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_T import android.app.WaitResult; import android.app.WindowConfiguration.WindowingMode; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -876,6 +877,11 @@ class ActivityMetricsLogger { builder.addTaggedData(FIELD_COMING_FROM_PENDING_INTENT, comingFromPendingIntent ? 1 : 0); if (intent != null) { builder.addTaggedData(FIELD_INTENT_ACTION, intent.getAction()); + ComponentName component = intent.getComponent(); + if (component != null) { + builder.addTaggedData(FIELD_TARGET_SHORT_COMPONENT_NAME, + component.flattenToShortString()); + } } if (callerApp != null) { builder.addTaggedData(FIELD_PROCESS_RECORD_PROCESS_NAME, callerApp.mName); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 3acd4e7fc746..ea1db406b8df 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -997,6 +997,10 @@ class ActivityStarter { if (callerApp.areBackgroundActivityStartsAllowed()) { return false; } + // don't abort if the caller has an activity in any foreground task + if (callerApp.hasActivityInVisibleTask()) { + return false; + } } // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid) diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index db96847e802b..a46fa13adf4e 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -26,6 +26,8 @@ import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAU import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import android.annotation.IntDef; +import android.annotation.Nullable; import android.app.WindowConfiguration; import android.os.Environment; import android.provider.Settings; @@ -33,6 +35,7 @@ import android.util.AtomicFile; import android.util.Slog; import android.util.Xml; import android.view.Display; +import android.view.DisplayAddress; import android.view.DisplayInfo; import android.view.Surface; @@ -47,10 +50,11 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; @@ -60,9 +64,33 @@ import java.util.HashMap; class DisplayWindowSettings { private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayWindowSettings" : TAG_WM; + private static final int IDENTIFIER_UNIQUE_ID = 0; + private static final int IDENTIFIER_PORT = 1; + @IntDef(prefix = { "IDENTIFIER_" }, value = { + IDENTIFIER_UNIQUE_ID, + IDENTIFIER_PORT, + }) + @interface DisplayIdentifierType {} + private final WindowManagerService mService; - private final AtomicFile mFile; - private final HashMap<String, Entry> mEntries = new HashMap<String, Entry>(); + private final HashMap<String, Entry> mEntries = new HashMap<>(); + private final SettingPersister mStorage; + + /** + * The preferred type of a display identifier to use when storing and retrieving entries. + * {@link #getIdentifier(DisplayInfo)} must be used to get current preferred identifier for each + * display. It will fall back to using {@link #IDENTIFIER_UNIQUE_ID} if the currently selected + * one is not applicable to a particular display. + */ + @DisplayIdentifierType + private int mIdentifier = IDENTIFIER_UNIQUE_ID; + + /** Interface for persisting the display window settings. */ + interface SettingPersister { + InputStream openRead() throws IOException; + OutputStream startWrite() throws IOException; + void finishWrite(OutputStream os, boolean success); + } private static class Entry { private final String mName; @@ -88,6 +116,26 @@ class DisplayWindowSettings { mName = name; } + private Entry(String name, Entry copyFrom) { + this(name); + mOverscanLeft = copyFrom.mOverscanLeft; + mOverscanTop = copyFrom.mOverscanTop; + mOverscanRight = copyFrom.mOverscanRight; + mOverscanBottom = copyFrom.mOverscanBottom; + mWindowingMode = copyFrom.mWindowingMode; + mUserRotationMode = copyFrom.mUserRotationMode; + mUserRotation = copyFrom.mUserRotation; + mForcedWidth = copyFrom.mForcedWidth; + mForcedHeight = copyFrom.mForcedHeight; + mForcedDensity = copyFrom.mForcedDensity; + mForcedScalingMode = copyFrom.mForcedScalingMode; + mRemoveContentMode = copyFrom.mRemoveContentMode; + mShouldShowWithInsecureKeyguard = copyFrom.mShouldShowWithInsecureKeyguard; + mShouldShowSystemDecors = copyFrom.mShouldShowSystemDecors; + mShouldShowIme = copyFrom.mShouldShowIme; + mFixedToUserRotation = copyFrom.mFixedToUserRotation; + } + /** @return {@code true} if all values are default. */ private boolean isEmpty() { return mOverscanLeft == 0 && mOverscanTop == 0 && mOverscanRight == 0 @@ -106,29 +154,46 @@ class DisplayWindowSettings { } DisplayWindowSettings(WindowManagerService service) { - this(service, new File(Environment.getDataDirectory(), "system")); + this(service, new AtomicFileStorage()); } @VisibleForTesting - DisplayWindowSettings(WindowManagerService service, File folder) { + DisplayWindowSettings(WindowManagerService service, SettingPersister storageImpl) { mService = service; - mFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays"); + mStorage = storageImpl; readSettings(); } - private Entry getEntry(DisplayInfo displayInfo) { - // Try to get the entry with the unique if possible. - // Else, fall back on the display name. + private @Nullable Entry getEntry(DisplayInfo displayInfo) { + final String identifier = getIdentifier(displayInfo); Entry entry; - if (displayInfo.uniqueId == null || (entry = mEntries.get(displayInfo.uniqueId)) == null) { - entry = mEntries.get(displayInfo.name); + // Try to get corresponding entry using preferred identifier for the current config. + if ((entry = mEntries.get(identifier)) != null) { + return entry; + } + // Else, fall back to the display name. + if ((entry = mEntries.get(displayInfo.name)) != null) { + // Found an entry stored with old identifier - upgrade to the new type now. + return updateIdentifierForEntry(entry, displayInfo); } - return entry; + return null; } private Entry getOrCreateEntry(DisplayInfo displayInfo) { final Entry entry = getEntry(displayInfo); - return entry != null ? entry : new Entry(displayInfo.uniqueId); + return entry != null ? entry : new Entry(getIdentifier(displayInfo)); + } + + /** + * Upgrades the identifier of a legacy entry. Does it by copying the data from the old record + * and clearing the old key in memory. The entry will be written to storage next time when a + * setting changes. + */ + private Entry updateIdentifierForEntry(Entry entry, DisplayInfo displayInfo) { + final Entry newEntry = new Entry(getIdentifier(displayInfo), entry); + removeEntry(displayInfo); + mEntries.put(newEntry.mName, newEntry); + return newEntry; } void setOverscanLocked(DisplayInfo displayInfo, int left, int top, int right, int bottom) { @@ -371,12 +436,11 @@ class DisplayWindowSettings { } private void readSettings() { - FileInputStream stream; + InputStream stream; try { - stream = mFile.openRead(); - } catch (FileNotFoundException e) { - Slog.i(TAG, "No existing display settings " + mFile.getBaseFile() - + "; starting empty"); + stream = mStorage.openRead(); + } catch (IOException e) { + Slog.i(TAG, "No existing display settings, starting empty"); return; } boolean success = false; @@ -403,6 +467,8 @@ class DisplayWindowSettings { String tagName = parser.getName(); if (tagName.equals("display")) { readDisplay(parser); + } else if (tagName.equals("config")) { + readConfig(parser); } else { Slog.w(TAG, "Unknown element under <display-settings>: " + parser.getName()); @@ -491,22 +557,26 @@ class DisplayWindowSettings { XmlUtils.skipCurrentTag(parser); } + private void readConfig(XmlPullParser parser) throws NumberFormatException, + XmlPullParserException, IOException { + mIdentifier = getIntAttribute(parser, "identifier"); + XmlUtils.skipCurrentTag(parser); + } + private void writeSettingsIfNeeded(Entry changedEntry, DisplayInfo displayInfo) { - if (changedEntry.isEmpty()) { - boolean removed = mEntries.remove(displayInfo.uniqueId) != null; - // Legacy name might have been in used, so we need to clear it. - removed |= mEntries.remove(displayInfo.name) != null; - if (!removed) { - // The entry didn't exist so nothing is changed and no need to update the file. - return; - } - } else { - mEntries.put(displayInfo.uniqueId, changedEntry); + if (changedEntry.isEmpty() && !removeEntry(displayInfo)) { + // The entry didn't exist so nothing is changed and no need to update the file. + return; } - FileOutputStream stream; + mEntries.put(getIdentifier(displayInfo), changedEntry); + writeSettings(); + } + + private void writeSettings() { + OutputStream stream; try { - stream = mFile.startWrite(); + stream = mStorage.startWrite(); } catch (IOException e) { Slog.w(TAG, "Failed to write display settings: " + e); return; @@ -516,8 +586,13 @@ class DisplayWindowSettings { XmlSerializer out = new FastXmlSerializer(); out.setOutput(stream, StandardCharsets.UTF_8.name()); out.startDocument(null, true); + out.startTag(null, "display-settings"); + out.startTag(null, "config"); + out.attribute(null, "identifier", Integer.toString(mIdentifier)); + out.endTag(null, "config"); + for (Entry entry : mEntries.values()) { out.startTag(null, "display"); out.attribute(null, "name", entry.mName); @@ -578,10 +653,66 @@ class DisplayWindowSettings { out.endTag(null, "display-settings"); out.endDocument(); - mFile.finishWrite(stream); + mStorage.finishWrite(stream, true /* success */); } catch (IOException e) { - Slog.w(TAG, "Failed to write display settings, restoring backup.", e); - mFile.failWrite(stream); + Slog.w(TAG, "Failed to write display window settings.", e); + mStorage.finishWrite(stream, false /* success */); + } + } + + /** + * Removes an entry from {@link #mEntries} cache. Looks up by new and previously used + * identifiers. + */ + private boolean removeEntry(DisplayInfo displayInfo) { + // Remove entry based on primary identifier. + boolean removed = mEntries.remove(getIdentifier(displayInfo)) != null; + // Ensure that legacy entries are cleared as well. + removed |= mEntries.remove(displayInfo.uniqueId) != null; + removed |= mEntries.remove(displayInfo.name) != null; + return removed; + } + + /** Gets the identifier of choice for the current config. */ + private String getIdentifier(DisplayInfo displayInfo) { + if (mIdentifier == IDENTIFIER_PORT && displayInfo.address != null) { + // Config suggests using port as identifier for physical displays. + if (displayInfo.address instanceof DisplayAddress.Physical) { + return "port:" + ((DisplayAddress.Physical) displayInfo.address).getPort(); + } + } + return displayInfo.uniqueId; + } + + private static class AtomicFileStorage implements SettingPersister { + private final AtomicFile mAtomicFile; + + AtomicFileStorage() { + final File folder = new File(Environment.getDataDirectory(), "system"); + mAtomicFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays"); + } + + @Override + public InputStream openRead() throws FileNotFoundException { + return mAtomicFile.openRead(); + } + + @Override + public OutputStream startWrite() throws IOException { + return mAtomicFile.startWrite(); + } + + @Override + public void finishWrite(OutputStream os, boolean success) { + if (!(os instanceof FileOutputStream)) { + throw new IllegalArgumentException("Unexpected OutputStream as argument: " + os); + } + FileOutputStream fos = (FileOutputStream) os; + if (success) { + mAtomicFile.finishWrite(fos); + } else { + mAtomicFile.failWrite(fos); + } } } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index dceed28d4c08..1b4aa26f7fb1 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -471,6 +471,20 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio } } + boolean hasActivityInVisibleTask() { + for (int i = mActivities.size() - 1; i >= 0; --i) { + TaskRecord task = mActivities.get(i).getTaskRecord(); + if (task == null) { + continue; + } + ActivityRecord topActivity = task.getTopActivity(); + if (topActivity != null && topActivity.visible) { + return true; + } + } + return false; + } + /** * Update the top resuming activity in process for pre-Q apps, only the top-most visible * activities are allowed to be resumed per process. diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 7df7ef3bae87..0b47b29e8d44 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -1700,8 +1700,12 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass gnssNavigationMessageIface = gnssNavigationMessage; } - if (gnssHal_V2_0 != nullptr) { - // TODO: getExtensionGnssMeasurement_1_1 from gnssHal_V2_0 + // Allow all causal combinations between IGnss.hal and IGnssMeasurement.hal. That means, + // 2.0@IGnss can be paired with {1.0, 1,1, 2.0}@IGnssMeasurement + // 1.1@IGnss can be paired {1.0, 1.1}@IGnssMeasurement + // 1.0@IGnss is paired with 1.0@IGnssMeasurement + gnssMeasurementIface = nullptr; + if (gnssHal_V2_0 != nullptr && gnssMeasurementIface == nullptr) { auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0(); if (!gnssMeasurement.isOk()) { ALOGD("Unable to get a handle to GnssMeasurement_V2_0"); @@ -1710,13 +1714,8 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass gnssMeasurementIface_V1_1 = gnssMeasurementIface_V2_0; gnssMeasurementIface = gnssMeasurementIface_V2_0; } - auto gnssCorrections = gnssHal_V2_0->getExtensionMeasurementCorrections(); - if (!gnssCorrections.isOk()) { - ALOGD("Unable to get a handle to GnssMeasurementCorrections interface"); - } else { - gnssCorrectionsIface = gnssCorrections; - } - } else if (gnssHal_V1_1 != nullptr) { + } + if (gnssHal_V1_1 != nullptr && gnssMeasurementIface == nullptr) { auto gnssMeasurement = gnssHal_V1_1->getExtensionGnssMeasurement_1_1(); if (!gnssMeasurement.isOk()) { ALOGD("Unable to get a handle to GnssMeasurement_V1_1"); @@ -1724,16 +1723,26 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass gnssMeasurementIface_V1_1 = gnssMeasurement; gnssMeasurementIface = gnssMeasurementIface_V1_1; } - } else { - auto gnssMeasurement_V1_0 = gnssHal->getExtensionGnssMeasurement(); - if (!gnssMeasurement_V1_0.isOk()) { + } + if (gnssMeasurementIface == nullptr) { + auto gnssMeasurement = gnssHal->getExtensionGnssMeasurement(); + if (!gnssMeasurement.isOk()) { ALOGD("Unable to get a handle to GnssMeasurement"); } else { - gnssMeasurementIface = gnssMeasurement_V1_0; + gnssMeasurementIface = gnssMeasurement; } } if (gnssHal_V2_0 != nullptr) { + auto gnssCorrections = gnssHal_V2_0->getExtensionMeasurementCorrections(); + if (!gnssCorrections.isOk()) { + ALOGD("Unable to get a handle to GnssMeasurementCorrections interface"); + } else { + gnssCorrectionsIface = gnssCorrections; + } + } + + if (gnssHal_V2_0 != nullptr) { auto gnssDebug = gnssHal_V2_0->getExtensionGnssDebug_2_0(); if (!gnssDebug.isOk()) { ALOGD("Unable to get a handle to GnssDebug_V2_0"); diff --git a/services/net/Android.bp b/services/net/Android.bp index 67fbdc4d95f2..7ef0ac4e1b84 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -69,7 +69,7 @@ java_library_static { srcs: [ ":framework-annotations", "java/android/net/IpMemoryStoreClient.java", - "java/android/net/ipmemorystore/**.java", + "java/android/net/ipmemorystore/**/*.java", ], static_libs: [ "ipmemorystore-aidl-interfaces-java", diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java index 7c91b6459fc8..7a40e449aaec 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java @@ -26,6 +26,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -57,6 +58,8 @@ import static org.mockito.Mockito.atLeastOnce; import android.app.ActivityManager; import android.app.AlarmManager; import android.app.IActivityManager; +import android.app.IAlarmCompleteListener; +import android.app.IAlarmListener; import android.app.IUidObserver; import android.app.PendingIntent; import android.app.usage.UsageStatsManagerInternal; @@ -67,6 +70,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PowerManager; +import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.provider.Settings; @@ -231,7 +235,7 @@ public class AlarmManagerServiceTest { doReturn(Looper.getMainLooper()).when(Looper::myLooper); when(mMockContext.getContentResolver()).thenReturn(mMockResolver); - doReturn("min_futurity=0").when(() -> + doReturn("min_futurity=0,min_interval=0").when(() -> Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS)); mInjector = new Injector(mMockContext); mService = new AlarmManagerService(mMockContext, mInjector); @@ -249,6 +253,7 @@ public class AlarmManagerServiceTest { // Other boot phases don't matter mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); assertEquals(0, mService.mConstants.MIN_FUTURITY); + assertEquals(0, mService.mConstants.MIN_INTERVAL); mAppStandbyWindow = mService.mConstants.APP_STANDBY_WINDOW; ArgumentCaptor<UsageStatsManagerInternal.AppIdleStateChangeListener> captor = ArgumentCaptor.forClass(UsageStatsManagerInternal.AppIdleStateChangeListener.class); @@ -257,15 +262,28 @@ public class AlarmManagerServiceTest { } private void setTestAlarm(int type, long triggerTime, PendingIntent operation) { - setTestAlarm(type, triggerTime, operation, TEST_CALLING_UID); + setTestAlarm(type, triggerTime, operation, 0, TEST_CALLING_UID); } - private void setTestAlarm(int type, long triggerTime, PendingIntent operation, int callingUid) { - mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, 0, + private void setRepeatingTestAlarm(int type, long firstTrigger, long interval, + PendingIntent pi) { + setTestAlarm(type, firstTrigger, pi, interval, TEST_CALLING_UID); + } + + private void setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval, + int callingUid) { + mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, interval, operation, null, "test", AlarmManager.FLAG_STANDALONE, null, null, callingUid, TEST_CALLING_PACKAGE); } + private void setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener) { + mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, 0, + null, listener, "test", AlarmManager.FLAG_STANDALONE, null, null, + TEST_CALLING_UID, TEST_CALLING_PACKAGE); + } + + private PendingIntent getNewMockPendingIntent() { return getNewMockPendingIntent(TEST_CALLING_UID); } @@ -738,14 +756,14 @@ public class AlarmManagerServiceTest { @Test public void alarmCountKeyedOnCallingUid() { final int mockCreatorUid = 431412; - final PendingIntent pi = getNewMockPendingIntent(mockCreatorUid); - setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 5, pi); + setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 5, + getNewMockPendingIntent(mockCreatorUid)); assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); assertEquals(-1, mService.mAlarmsPerUid.get(mockCreatorUid, -1)); } @Test - public void alarmCountOnSet() { + public void alarmCountOnSetPi() { final int numAlarms = 103; final int[] types = {RTC_WAKEUP, RTC, ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME}; for (int i = 1; i <= numAlarms; i++) { @@ -755,7 +773,21 @@ public class AlarmManagerServiceTest { } @Test - public void alarmCountOnExpiration() throws InterruptedException { + public void alarmCountOnSetListener() { + final int numAlarms = 103; + final int[] types = {RTC_WAKEUP, RTC, ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME}; + for (int i = 1; i <= numAlarms; i++) { + setTestAlarmWithListener(types[i % 4], mNowElapsedTest + i, new IAlarmListener.Stub() { + @Override + public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { + } + }); + assertEquals(i, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + } + } + + @Test + public void alarmCountOnExpirationPi() throws InterruptedException { final int numAlarms = 8; // This test is slow for (int i = 0; i < numAlarms; i++) { setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent()); @@ -770,6 +802,86 @@ public class AlarmManagerServiceTest { } @Test + public void alarmCountOnExpirationListener() throws InterruptedException { + final int numAlarms = 8; // This test is slow + for (int i = 0; i < numAlarms; i++) { + setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 10, + new IAlarmListener.Stub() { + @Override + public void doAlarm(IAlarmCompleteListener callback) + throws RemoteException { + } + }); + } + int expired = 0; + while (expired < numAlarms) { + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + expired++; + assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); + } + } + + @Test + public void alarmCountOnExceptionWhileSendingPi() throws Exception { + final int numAlarms = 5; // This test is slow + for (int i = 0; i < numAlarms; i++) { + final PendingIntent pi = getNewMockPendingIntent(); + doThrow(PendingIntent.CanceledException.class).when(pi).send(eq(mMockContext), eq(0), + any(), any(), any(), any(), any()); + setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, pi); + } + int expired = 0; + while (expired < numAlarms) { + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + expired++; + assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); + } + } + + @Test + public void alarmCountOnExceptionWhileCallingListener() throws Exception { + final int numAlarms = 5; // This test is slow + for (int i = 0; i < numAlarms; i++) { + final IAlarmListener listener = new IAlarmListener.Stub() { + @Override + public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { + throw new RemoteException("For testing behavior on exception"); + } + }; + setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 10, listener); + } + int expired = 0; + while (expired < numAlarms) { + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + expired++; + assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); + } + } + + @Test + public void alarmCountForRepeatingAlarms() throws Exception { + final long interval = 1231; + final long firstTrigger = mNowElapsedTest + 321; + final PendingIntent pi = getNewMockPendingIntent(); + setRepeatingTestAlarm(ELAPSED_REALTIME, firstTrigger, interval, pi); + assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + + for (int i = 0; i < 5; i++) { + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + } + doThrow(PendingIntent.CanceledException.class).when(pi).send(eq(mMockContext), eq(0), + any(), any(), any(), any(), any()); + mNowElapsedTest = mTestTimer.getElapsed(); + mTestTimer.expire(); + assertEquals(-1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, -1)); + } + + @Test public void alarmCountOnUidRemoved() { final int numAlarms = 10; for (int i = 0; i < numAlarms; i++) { @@ -798,7 +910,7 @@ public class AlarmManagerServiceTest { for (int i = 0; i < numAlarms; i++) { int mockUid = UserHandle.getUid(mockUserId, 1234 + i); setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, - getNewMockPendingIntent(mockUid), mockUid); + getNewMockPendingIntent(mockUid), 0, mockUid); } assertEquals(numAlarms, mService.mAlarmsPerUid.size()); mService.removeUserLocked(mockUserId); @@ -820,6 +932,12 @@ public class AlarmManagerServiceTest { } } + @Test + public void alarmCountOnInvalidSet() { + setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, null); + assertEquals(-1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, -1)); + } + @After public void tearDown() { if (mMockingSession != null) { diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index bd7774a64019..5b1970004971 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -85,10 +85,11 @@ import android.security.keystore.AttestationUtils; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.test.MoreAsserts; -import android.test.suitebuilder.annotation.SmallTest; import android.util.ArraySet; import android.util.Pair; +import androidx.test.filters.SmallTest; + import com.android.internal.R; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index 3d02576c8e7f..2fbeebdb4937 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -56,7 +56,7 @@ import java.util.ArrayList; import java.util.Arrays; -public class BaseLockSettingsServiceTests extends AndroidTestCase { +public abstract class BaseLockSettingsServiceTests extends AndroidTestCase { protected static final int PRIMARY_USER_ID = 0; protected static final int MANAGED_PROFILE_USER_ID = 12; protected static final int TURNED_OFF_PROFILE_USER_ID = 17; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java index ca4330fa7a5d..d2a914527880 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java @@ -26,6 +26,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.os.RemoteException; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; @@ -40,6 +43,8 @@ import java.util.ArrayList; * By default, those tests run without caching. Untrusted credential reset depends on caching so * this class included those tests. */ +@SmallTest +@Presubmit public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { @Override diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java index 255e694bffaf..7ebc7454d995 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java @@ -26,8 +26,11 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; import android.os.RemoteException; +import android.platform.test.annotations.Presubmit; import android.service.gatekeeper.GateKeeperResponse; +import androidx.test.filters.SmallTest; + import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; import com.android.server.locksettings.FakeGateKeeperService.VerifyHandle; @@ -36,6 +39,8 @@ import com.android.server.locksettings.LockSettingsStorage.CredentialHash; /** * runtest frameworks-services -c com.android.server.locksettings.LockSettingsServiceTests */ +@SmallTest +@Presubmit public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { @Override diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java index fcfc6d2267c5..c00d33b431c3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java @@ -21,7 +21,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; import static com.android.internal.widget.LockPatternUtils.stringToPattern; -import static junit.framework.Assert.*; +import static junit.framework.Assert.assertEquals; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.any; @@ -30,6 +30,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static java.io.FileDescriptor.err; +import static java.io.FileDescriptor.in; +import static java.io.FileDescriptor.out; + import android.app.ActivityManager; import android.content.Context; import android.os.Binder; @@ -51,8 +55,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import static java.io.FileDescriptor.*; - /** * Test class for {@link LockSettingsShellCommand}. * diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java index 6e1f35784c7d..8af4edda3b8b 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java @@ -29,11 +29,14 @@ import android.database.sqlite.SQLiteDatabase; import android.os.FileUtils; import android.os.UserManager; import android.os.storage.StorageManager; +import android.platform.test.annotations.Presubmit; import android.test.AndroidTestCase; import android.util.Log; import android.util.Log.TerribleFailure; import android.util.Log.TerribleFailureHandler; +import androidx.test.filters.SmallTest; + import com.android.internal.widget.LockPatternUtils; import com.android.server.PersistentDataBlockManagerInternal; import com.android.server.locksettings.LockSettingsStorage.CredentialHash; @@ -48,6 +51,8 @@ import java.util.concurrent.CountDownLatch; /** * runtest frameworks-services -c com.android.server.locksettings.LockSettingsStorageTests */ +@SmallTest +@Presubmit public class LockSettingsStorageTests extends AndroidTestCase { private static final int SOME_USER_ID = 1034; private final byte[] PASSWORD_0 = "thepassword0".getBytes(); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTests.java index 1d5a99b8af04..31526b55411c 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTests.java @@ -16,8 +16,11 @@ package com.android.server.locksettings; +import android.platform.test.annotations.Presubmit; import android.test.AndroidTestCase; +import androidx.test.filters.SmallTest; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.HashMap; @@ -25,6 +28,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +@SmallTest +@Presubmit public class PasswordSlotManagerTests extends AndroidTestCase { PasswordSlotManagerTestable mManager; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java index fc2dcb9cc83b..29d0fc1f43d1 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java @@ -16,10 +16,15 @@ package com.android.server.locksettings; +import android.platform.test.annotations.Presubmit; import android.test.AndroidTestCase; +import androidx.test.filters.SmallTest; + import com.android.internal.util.HexDump; +@SmallTest +@Presubmit public class SP800DeriveTests extends AndroidTestCase { public void testFixedInput() throws Exception { // CAVP: https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/key-derivation diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index 5a9ca0f88287..0273f7651207 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -33,6 +33,9 @@ import static org.mockito.Mockito.verify; import android.app.admin.PasswordMetrics; import android.os.RemoteException; import android.os.UserHandle; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; @@ -48,6 +51,8 @@ import java.util.ArrayList; /** * runtest frameworks-services -c com.android.server.locksettings.SyntheticPasswordTests */ +@SmallTest +@Presubmit public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public static final byte[] PAYLOAD = new byte[] {1, 2, -1, -2, 55}; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java index 5e567044fba6..abbf01681c87 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java @@ -1,5 +1,11 @@ package com.android.server.locksettings; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; + +@SmallTest +@Presubmit public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests { @Override diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 987d46a697c2..a9eb6ec5db1e 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -4324,4 +4324,36 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(IMPORTANCE_LOW, r.getAssistantImportance()); assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment()); } + + public void testAreNotificationsEnabledForPackage_crossUser() throws Exception { + try { + mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), + mUid + UserHandle.PER_USER_RANGE); + fail("Cannot call cross user without permission"); + } catch (SecurityException e) { + // pass + } + + // cross user, with permission, no problem + TestablePermissions perms = mContext.getTestablePermissions(); + perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), + mUid + UserHandle.PER_USER_RANGE); + } + + public void testAreBubblesAllowedForPackage_crossUser() throws Exception { + try { + mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(), + mUid + UserHandle.PER_USER_RANGE); + fail("Cannot call cross user without permission"); + } catch (SecurityException e) { + // pass + } + + // cross user, with permission, no problem + TestablePermissions perms = mContext.getTestablePermissions(); + perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(), + mUid + UserHandle.PER_USER_RANGE); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java index 9a8a732a9da8..652ea7d32953 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; @@ -40,7 +42,9 @@ import static org.mockito.Matchers.eq; import android.app.WindowConfiguration; import android.platform.test.annotations.Presubmit; +import android.util.Xml; import android.view.Display; +import android.view.DisplayAddress; import android.view.DisplayInfo; import android.view.Surface; @@ -53,14 +57,22 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.MockitoSession; +import org.xmlpull.v1.XmlPullParser; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; /** * Tests for the {@link DisplayWindowSettings} class. * * Build/Install/Run: - * atest FrameworksServicesTests:DisplayWindowSettingsTests + * atest WmTests:DisplayWindowSettingsTests */ @SmallTest @Presubmit @@ -69,12 +81,14 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { private static final File TEST_FOLDER = getInstrumentation().getTargetContext().getCacheDir(); private DisplayWindowSettings mTarget; - DisplayInfo mPrivateDisplayInfo; + private DisplayInfo mPrivateDisplayInfo; private DisplayContent mPrimaryDisplay; private DisplayContent mSecondaryDisplay; private DisplayContent mPrivateDisplay; + private TestStorage mStorage; + @Before public void setUp() throws Exception { deleteRecursively(TEST_FOLDER); @@ -83,7 +97,8 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mWm.setIsPc(false); mWm.setForceDesktopModeOnExternalDisplays(false); - mTarget = new DisplayWindowSettings(mWm, TEST_FOLDER); + mStorage = new TestStorage(); + mTarget = new DisplayWindowSettings(mWm, mStorage); mPrimaryDisplay = mWm.getDefaultDisplayContentLocked(); mSecondaryDisplay = mDisplayContent; @@ -143,7 +158,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mTarget.applySettingsToDisplayLocked(mPrimaryDisplay); - assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM, + assertEquals(WINDOWING_MODE_FREEFORM, mPrimaryDisplay.getWindowingMode()); } @@ -185,7 +200,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mTarget.applySettingsToDisplayLocked(mSecondaryDisplay); - assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM, + assertEquals(WINDOWING_MODE_FREEFORM, mSecondaryDisplay.getWindowingMode()); } @@ -196,7 +211,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mTarget.applySettingsToDisplayLocked(mSecondaryDisplay); - assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM, + assertEquals(WINDOWING_MODE_FREEFORM, mSecondaryDisplay.getWindowingMode()); } @@ -474,6 +489,171 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mockitoSession.finishMocking(); } + @Test + public void testReadingDisplaySettingsFromStorage() { + final String displayIdentifier = mSecondaryDisplay.getDisplayInfo().uniqueId; + prepareDisplaySettings(displayIdentifier); + + readAndAssertDisplaySettings(mPrimaryDisplay); + } + + @Test + public void testReadingDisplaySettingsFromStorage_LegacyDisplayId() { + final String displayIdentifier = mPrimaryDisplay.getDisplayInfo().name; + prepareDisplaySettings(displayIdentifier); + + readAndAssertDisplaySettings(mPrimaryDisplay); + } + + @Test + public void testReadingDisplaySettingsFromStorage_LegacyDisplayId_UpdateAfterAccess() + throws Exception { + // Store display settings with legacy display identifier. + final String displayIdentifier = mPrimaryDisplay.getDisplayInfo().name; + prepareDisplaySettings(displayIdentifier); + + // Update settings with new value, should trigger write to injector. + final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage); + settings.setRemoveContentModeLocked(mPrimaryDisplay, REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY); + assertEquals("Settings value must be updated", REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY, + settings.getRemoveContentModeLocked(mPrimaryDisplay)); + assertTrue(mStorage.wasWriteSuccessful()); + + // Verify that display identifier was updated. + final String newDisplayIdentifier = getStoredDisplayAttributeValue("name"); + assertEquals("Display identifier must be updated to use uniqueId", + mPrimaryDisplay.getDisplayInfo().uniqueId, newDisplayIdentifier); + } + + @Test + public void testReadingDisplaySettingsFromStorage_UsePortAsId() { + final DisplayAddress.Physical displayAddress = DisplayAddress.fromPhysicalDisplayId(123456); + mPrimaryDisplay.getDisplayInfo().address = displayAddress; + + final String displayIdentifier = "port:" + displayAddress.getPort(); + prepareDisplaySettings(displayIdentifier, true /* usePortAsId */); + + readAndAssertDisplaySettings(mPrimaryDisplay); + } + + @Test + public void testReadingDisplaySettingsFromStorage_UsePortAsId_IncorrectAddress() { + final String displayIdentifier = mPrimaryDisplay.getDisplayInfo().uniqueId; + prepareDisplaySettings(displayIdentifier, true /* usePortAsId */); + + mPrimaryDisplay.getDisplayInfo().address = DisplayAddress.fromPhysicalDisplayId(123456); + + // Verify that the entry is not matched and default settings are returned instead. + final DisplayWindowSettings settings = new DisplayWindowSettings(mWm); + assertNotEquals("Default setting must be returned for new entry", + WINDOWING_MODE_PINNED, settings.getWindowingModeLocked(mPrimaryDisplay)); + } + + @Test + public void testWritingDisplaySettingsToStorage() throws Exception { + // Write some settings to storage. + final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage); + settings.setShouldShowSystemDecorsLocked(mSecondaryDisplay, true); + settings.setShouldShowImeLocked(mSecondaryDisplay, true); + assertTrue(mStorage.wasWriteSuccessful()); + + // Verify that settings were stored correctly. + assertEquals("Attribute value must be stored", mSecondaryDisplay.getDisplayInfo().uniqueId, + getStoredDisplayAttributeValue("name")); + assertEquals("Attribute value must be stored", "true", + getStoredDisplayAttributeValue("shouldShowSystemDecors")); + assertEquals("Attribute value must be stored", "true", + getStoredDisplayAttributeValue("shouldShowIme")); + } + + @Test + public void testWritingDisplaySettingsToStorage_UsePortAsId() throws Exception { + // Store config to use port as identifier. + final DisplayAddress.Physical displayAddress = DisplayAddress.fromPhysicalDisplayId(123456); + mSecondaryDisplay.getDisplayInfo().address = displayAddress; + prepareDisplaySettings(null /* displayIdentifier */, true /* usePortAsId */); + + // Write some settings. + final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage); + settings.setShouldShowSystemDecorsLocked(mSecondaryDisplay, true); + settings.setShouldShowImeLocked(mSecondaryDisplay, true); + assertTrue(mStorage.wasWriteSuccessful()); + + // Verify that settings were stored correctly. + assertEquals("Attribute value must be stored", "port:" + displayAddress.getPort(), + getStoredDisplayAttributeValue("name")); + assertEquals("Attribute value must be stored", "true", + getStoredDisplayAttributeValue("shouldShowSystemDecors")); + assertEquals("Attribute value must be stored", "true", + getStoredDisplayAttributeValue("shouldShowIme")); + } + + /** + * Prepares display settings and stores in {@link #mStorage}. Uses provided display identifier + * and stores windowingMode=WINDOWING_MODE_PINNED. + */ + private void prepareDisplaySettings(String displayIdentifier) { + prepareDisplaySettings(displayIdentifier, false /* usePortAsId */); + } + + private void prepareDisplaySettings(String displayIdentifier, boolean usePortAsId) { + String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<display-settings>\n"; + if (usePortAsId) { + contents += " <config identifier=\"1\"/>\n"; + } + if (displayIdentifier != null) { + contents += " <display\n" + + " name=\"" + displayIdentifier + "\"\n" + + " windowingMode=\"" + WINDOWING_MODE_PINNED + "\"/>\n"; + } + contents += "</display-settings>\n"; + + final InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8)); + mStorage.setReadStream(is); + } + + private void readAndAssertDisplaySettings(DisplayContent displayContent) { + final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage); + assertEquals("Stored setting must be read", + WINDOWING_MODE_PINNED, settings.getWindowingModeLocked(displayContent)); + assertEquals("Not stored setting must be set to default value", + REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY, + settings.getRemoveContentModeLocked(displayContent)); + } + + private String getStoredDisplayAttributeValue(String attr) throws Exception { + try (InputStream stream = mStorage.openRead()) { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(stream, StandardCharsets.UTF_8.name()); + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + // Do nothing. + } + + if (type != XmlPullParser.START_TAG) { + throw new IllegalStateException("no start tag found"); + } + + int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("display")) { + return parser.getAttributeValue(null, attr); + } + } + } finally { + mStorage.closeRead(); + } + return null; + } + private static void assertOverscan(DisplayContent display, int left, int top, int right, int bottom) { final DisplayInfo info = display.getDisplayInfo(); @@ -490,7 +670,11 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { * path that also means the previous state must be written correctly. */ private void applySettingsToDisplayByNewInstance(DisplayContent display) { - new DisplayWindowSettings(mWm, TEST_FOLDER).applySettingsToDisplayLocked(display); + // Assert that prior write completed successfully. + assertTrue(mStorage.wasWriteSuccessful()); + + // Read and apply settings. + new DisplayWindowSettings(mWm, mStorage).applySettingsToDisplayLocked(display); } private static boolean deleteRecursively(File file) { @@ -506,4 +690,81 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { } return fullyDeleted; } + + /** In-memory storage implementation. */ + public class TestStorage implements DisplayWindowSettings.SettingPersister { + private InputStream mReadStream; + private ByteArrayOutputStream mWriteStream; + + private boolean mWasSuccessful; + + /** + * Returns input stream for reading. By default tries forward the output stream if previous + * write was successful. + * @see #closeRead() + */ + @Override + public InputStream openRead() throws FileNotFoundException { + if (mReadStream == null && mWasSuccessful) { + mReadStream = new ByteArrayInputStream(mWriteStream.toByteArray()); + } + if (mReadStream == null) { + throw new FileNotFoundException(); + } + if (mReadStream.markSupported()) { + mReadStream.mark(Integer.MAX_VALUE); + } + return mReadStream; + } + + /** Must be called after each {@link #openRead} to reset the position in the stream. */ + void closeRead() throws IOException { + if (mReadStream == null) { + throw new FileNotFoundException(); + } + if (mReadStream.markSupported()) { + mReadStream.reset(); + } + mReadStream = null; + } + + /** + * Creates new or resets existing output stream for write. Automatically closes previous + * read stream, since following reads should happen based on this new write. + */ + @Override + public OutputStream startWrite() throws IOException { + if (mWriteStream == null) { + mWriteStream = new ByteArrayOutputStream(); + } else { + mWriteStream.reset(); + } + if (mReadStream != null) { + closeRead(); + } + return mWriteStream; + } + + @Override + public void finishWrite(OutputStream os, boolean success) { + mWasSuccessful = success; + try { + os.close(); + } catch (IOException e) { + // This method can't throw IOException since the super implementation doesn't, so + // we just wrap it in a RuntimeException so we end up crashing the test all the + // same. + throw new RuntimeException(e); + } + } + + /** Override the read stream of the injector. By default it uses current write stream. */ + private void setReadStream(InputStream is) { + mReadStream = is; + } + + private boolean wasWriteSuccessful() { + return mWasSuccessful; + } + } } diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java index 8feed7fdb785..a783a4007da1 100644 --- a/services/usage/java/com/android/server/usage/IntervalStats.java +++ b/services/usage/java/com/android/server/usage/IntervalStats.java @@ -66,7 +66,7 @@ public class IntervalStats { public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>(); public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>(); public Configuration activeConfiguration; - public EventList events = new EventList(); + public final EventList events = new EventList(); // A string cache. This is important as when we're parsing XML files, we don't want to // keep hundreds of strings that have the same contents. We will read the string @@ -82,7 +82,7 @@ public class IntervalStats { public void commitTime(long timeStamp) { if (curStartTime != 0) { - duration += timeStamp - duration; + duration += timeStamp - curStartTime; curStartTime = 0; } } @@ -305,7 +305,9 @@ public class IntervalStats { UsageStats usageStats = getOrCreateUsageStats(packageName); usageStats.update(className, timeStamp, eventType, instanceId); } - endTime = timeStamp; + if (timeStamp > endTime) { + endTime = timeStamp; + } } /** @@ -328,6 +330,9 @@ public class IntervalStats { event.mNotificationChannelId = getCachedStringRef(event.mNotificationChannelId); } events.insert(event); + if (event.mTimeStamp > endTime) { + endTime = event.mTimeStamp; + } } void updateChooserCounts(String packageName, String category, String action) { @@ -360,8 +365,9 @@ public class IntervalStats { configStats.mActivationCount += 1; activeConfiguration = configStats.mConfiguration; } - - endTime = timeStamp; + if (timeStamp > endTime) { + endTime = timeStamp; + } } void incrementAppLaunchCount(String packageName) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java index 485a79d63862..c55bb3cf0ffe 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java +++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java @@ -1166,7 +1166,8 @@ public class UsageStatsDatabase { if (beingRestored == null) return null; beingRestored.activeConfiguration = onDevice.activeConfiguration; beingRestored.configurations.putAll(onDevice.configurations); - beingRestored.events = onDevice.events; + beingRestored.events.clear(); + beingRestored.events.merge(onDevice.events); return beingRestored; } diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 9498e161ff61..26bfcc944400 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -334,7 +334,7 @@ class UserUsageStatsService { final IntervalStats diskStats = mDatabase.getLatestUsageStats( INTERVAL_DAILY); StringBuilder sb = new StringBuilder(256); - sb.append("Last 24 hours of UsageStats missing! timeRange : "); + sb.append("Recent UsageStats missing! timeRange : "); sb.append(beginTime); sb.append(", "); sb.append(endTime); diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index dde805777a0b..09046a679c37 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -27,10 +27,6 @@ import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.app.ActivityThread; import android.app.PendingIntent; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothMapClient; -import android.bluetooth.BluetoothProfile; import android.content.ActivityNotFoundException; import android.content.ContentValues; import android.content.Context; @@ -43,7 +39,6 @@ import android.os.Build; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; -import android.telecom.PhoneAccount; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; @@ -76,7 +71,6 @@ import java.util.concurrent.Executor; */ public final class SmsManager { private static final String TAG = "SmsManager"; - private static final boolean DBG = false; /** * A psuedo-subId that represents the default subId at any given time. The actual subId it @@ -357,42 +351,11 @@ public final class SmsManager { throw new IllegalArgumentException("Invalid message body"); } - // A Manager code accessing another manager is *not* acceptable, in Android. - // In this particular case, it is unavoidable because of the following: - // If the subscription for this SmsManager instance belongs to a remote SIM - // then a listener to get BluetoothMapClient proxy needs to be started up. - // Doing that is possible only in a foreground thread or as a system user. - // i.e., Can't be done in ISms service. - // For that reason, SubscriptionManager needs to be accessed here to determine - // if the subscription belongs to a remote SIM. - // Ideally, there should be another API in ISms to service messages going thru - // remote SIM subscriptions (and ISms should be tweaked to be able to access - // BluetoothMapClient proxy) - Context context = ActivityThread.currentApplication().getApplicationContext(); - SubscriptionManager manager = (SubscriptionManager) context - .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); - int subId = getSubscriptionId(); - SubscriptionInfo info = manager.getActiveSubscriptionInfo(subId); - if (DBG) { - Log.d(TAG, "for subId: " + subId + ", subscription-info: " + info); - } - - /* If the Subscription associated with this SmsManager instance belongs to a remote-sim, - * then send the message thru the remote-sim subscription. - */ - if (info != null - && info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) { - if (DBG) Log.d(TAG, "sending message thru bluetooth"); - sendTextMessageBluetooth(destinationAddress, scAddress, text, sentIntent, - deliveryIntent, info); - return; - } - try { // If the subscription is invalid or default, we will use the default phone to send the // SMS and possibly fail later in the SMS sending process. - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendTextForSubscriber(subId, ActivityThread.currentPackageName(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, text, sentIntent, deliveryIntent, persistMessage); @@ -401,82 +364,6 @@ public final class SmsManager { } } - private void sendTextMessageBluetooth(String destAddr, String scAddress, - String text, PendingIntent sentIntent, PendingIntent deliveryIntent, - SubscriptionInfo info) { - BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); - if (btAdapter == null) { - // No bluetooth service on this platform? - sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_NO_SERVICE); - return; - } - BluetoothDevice device = btAdapter.getRemoteDevice(info.getIccId()); - if (device == null) { - if (DBG) Log.d(TAG, "Bluetooth device addr invalid: " + info.getIccId()); - sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_NO_SERVICE); - return; - } - btAdapter.getProfileProxy(ActivityThread.currentApplication().getApplicationContext(), - new MapMessageSender(destAddr, text, device, sentIntent, deliveryIntent), - BluetoothProfile.MAP_CLIENT); - } - - private class MapMessageSender implements BluetoothProfile.ServiceListener { - final Uri[] mDestAddr; - private String mMessage; - final BluetoothDevice mDevice; - final PendingIntent mSentIntent; - final PendingIntent mDeliveryIntent; - MapMessageSender(final String destAddr, final String message, final BluetoothDevice device, - final PendingIntent sentIntent, final PendingIntent deliveryIntent) { - super(); - mDestAddr = new Uri[] {new Uri.Builder() - .appendPath(destAddr) - .scheme(PhoneAccount.SCHEME_TEL) - .build()}; - mMessage = message; - mDevice = device; - mSentIntent = sentIntent; - mDeliveryIntent = deliveryIntent; - } - - @Override - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (DBG) Log.d(TAG, "Service connected"); - if (profile != BluetoothProfile.MAP_CLIENT) return; - BluetoothMapClient mapProfile = (BluetoothMapClient) proxy; - if (mMessage != null) { - if (DBG) Log.d(TAG, "Sending message thru bluetooth"); - mapProfile.sendMessage(mDevice, mDestAddr, mMessage, mSentIntent, mDeliveryIntent); - mMessage = null; - } - BluetoothAdapter.getDefaultAdapter() - .closeProfileProxy(BluetoothProfile.MAP_CLIENT, mapProfile); - } - - @Override - public void onServiceDisconnected(int profile) { - if (mMessage != null) { - if (DBG) Log.d(TAG, "Bluetooth disconnected before sending the message"); - sendErrorInPendingIntent(mSentIntent, SmsManager.RESULT_ERROR_NO_SERVICE); - mMessage = null; - } - } - } - - private void sendErrorInPendingIntent(PendingIntent intent, int errorCode) { - if (intent == null) { - return; - } - try { - intent.send(errorCode); - } catch (PendingIntent.CanceledException e) { - // PendingIntent is cancelled. ignore sending this error code back to - // caller. - if (DBG) Log.d(TAG, "PendingIntent.CanceledException: " + e.getMessage()); - } - } - /** * Send a text based SMS without writing it into the SMS Provider. * @@ -526,8 +413,8 @@ public final class SmsManager { } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendTextForSubscriberWithSelfPermissions(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendTextForSubscriberWithSelfPermissions(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, text, sentIntent, deliveryIntent, persistMessage); @@ -610,9 +497,9 @@ public final class SmsManager { } try { - ISms iccISms = getISmsServiceOrThrow(); - if (iccISms != null) { - iccISms.sendTextForSubscriberWithOptions(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + if (iSms != null) { + iSms.sendTextForSubscriberWithOptions(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, text, sentIntent, deliveryIntent, persistMessage, priority, expectMore, validityPeriod); @@ -671,9 +558,9 @@ public final class SmsManager { "Invalid pdu format. format must be either 3gpp or 3gpp2"); } try { - ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - if (iccISms != null) { - iccISms.injectSmsPduForSubscriber( + ISms iSms = ISms.Stub.asInterface(ServiceManager.getService("isms")); + if (iSms != null) { + iSms.injectSmsPduForSubscriber( getSubscriptionId(), pdu, format, receivedIntent); } } catch (RemoteException ex) { @@ -759,8 +646,8 @@ public final class SmsManager { if (parts.size() > 1) { try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendMultipartTextForSubscriber(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendMultipartTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, parts, sentIntents, deliveryIntents, persistMessage); @@ -891,9 +778,9 @@ public final class SmsManager { if (parts.size() > 1) { try { - ISms iccISms = getISmsServiceOrThrow(); - if (iccISms != null) { - iccISms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + if (iSms != null) { + iSms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, parts, sentIntents, deliveryIntents, persistMessage, priority, expectMore, validityPeriod); @@ -979,8 +866,8 @@ public final class SmsManager { } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, destinationPort & 0xFFFF, data, sentIntent, deliveryIntent); } catch (RemoteException ex) { @@ -1006,8 +893,8 @@ public final class SmsManager { } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(), + ISms iSms = getISmsServiceOrThrow(); + iSms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(), ActivityThread.currentPackageName(), destinationAddress, scAddress, destinationPort & 0xFFFF, data, sentIntent, deliveryIntent); } catch (RemoteException ex) { @@ -1069,9 +956,9 @@ public final class SmsManager { boolean isSmsSimPickActivityNeeded = false; final Context context = ActivityThread.currentApplication().getApplicationContext(); try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - isSmsSimPickActivityNeeded = iccISms.isSmsSimPickActivityNeeded(subId); + ISms iSms = getISmsService(); + if (iSms != null) { + isSmsSimPickActivityNeeded = iSms.isSmsSimPickActivityNeeded(subId); } } catch (RemoteException ex) { Log.e(TAG, "Exception in getSubscriptionId"); @@ -1102,11 +989,11 @@ public final class SmsManager { * the service does not exist. */ private static ISms getISmsServiceOrThrow() { - ISms iccISms = getISmsService(); - if (iccISms == null) { + ISms iSms = getISmsService(); + if (iSms == null) { throw new UnsupportedOperationException("Sms is not supported"); } - return iccISms; + return iSms; } private static ISms getISmsService() { @@ -1135,9 +1022,9 @@ public final class SmsManager { throw new IllegalArgumentException("pdu is NULL"); } try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.copyMessageToIccEfForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.copyMessageToIccEfForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), status, pdu, smsc); } @@ -1166,9 +1053,9 @@ public final class SmsManager { Arrays.fill(pdu, (byte)0xff); try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), messageIndex, STATUS_ON_ICC_FREE, pdu); } @@ -1198,9 +1085,9 @@ public final class SmsManager { boolean success = false; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), messageIndex, newStatus, pdu); } @@ -1225,9 +1112,9 @@ public final class SmsManager { List<SmsRawData> records = null; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - records = iccISms.getAllMessagesFromIccEfForSubscriber( + ISms iSms = getISmsService(); + if (iSms != null) { + records = iSms.getAllMessagesFromIccEfForSubscriber( getSubscriptionId(), ActivityThread.currentPackageName()); } @@ -1262,9 +1149,9 @@ public final class SmsManager { boolean success = false; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.enableCellBroadcastForSubscriber( + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.enableCellBroadcastForSubscriber( getSubscriptionId(), messageIdentifier, ranType); } } catch (RemoteException ex) { @@ -1298,9 +1185,9 @@ public final class SmsManager { boolean success = false; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.disableCellBroadcastForSubscriber( + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.disableCellBroadcastForSubscriber( getSubscriptionId(), messageIdentifier, ranType); } } catch (RemoteException ex) { @@ -1341,9 +1228,9 @@ public final class SmsManager { throw new IllegalArgumentException("endMessageId < startMessageId"); } try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(), startMessageId, endMessageId, ranType); } } catch (RemoteException ex) { @@ -1384,9 +1271,9 @@ public final class SmsManager { throw new IllegalArgumentException("endMessageId < startMessageId"); } try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - success = iccISms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(), + ISms iSms = getISmsService(); + if (iSms != null) { + success = iSms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(), startMessageId, endMessageId, ranType); } } catch (RemoteException ex) { @@ -1436,9 +1323,9 @@ public final class SmsManager { public boolean isImsSmsSupported() { boolean boSupported = false; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - boSupported = iccISms.isImsSmsSupportedForSubscriber(getSubscriptionId()); + ISms iSms = getISmsService(); + if (iSms != null) { + boSupported = iSms.isImsSmsSupportedForSubscriber(getSubscriptionId()); } } catch (RemoteException ex) { // ignore it @@ -1461,9 +1348,9 @@ public final class SmsManager { public String getImsSmsFormat() { String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN; try { - ISms iccISms = getISmsService(); - if (iccISms != null) { - format = iccISms.getImsSmsFormatForSubscriber(getSubscriptionId()); + ISms iSms = getISmsService(); + if (iSms != null) { + format = iSms.getImsSmsFormatForSubscriber(getSubscriptionId()); } } catch (RemoteException ex) { // ignore it @@ -1477,10 +1364,10 @@ public final class SmsManager { * @return the default SMS subscription id */ public static int getDefaultSmsSubscriptionId() { - ISms iccISms = null; + ISms iSms = null; try { - iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - return iccISms.getPreferredSmsSubscription(); + iSms = ISms.Stub.asInterface(ServiceManager.getService("isms")); + return iSms.getPreferredSmsSubscription(); } catch (RemoteException ex) { return -1; } catch (NullPointerException ex) { @@ -1496,10 +1383,10 @@ public final class SmsManager { */ @UnsupportedAppUsage public boolean isSMSPromptEnabled() { - ISms iccISms = null; + ISms iSms = null; try { - iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); - return iccISms.isSMSPromptEnabled(); + iSms = ISms.Stub.asInterface(ServiceManager.getService("isms")); + return iSms.isSMSPromptEnabled(); } catch (RemoteException ex) { return false; } catch (NullPointerException ex) { @@ -1976,8 +1863,8 @@ public final class SmsManager { throw new IllegalArgumentException("Empty message URI"); } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendStoredText( + ISms iSms = getISmsServiceOrThrow(); + iSms.sendStoredText( getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, scAddress, sentIntent, deliveryIntent); } catch (RemoteException ex) { @@ -2024,8 +1911,8 @@ public final class SmsManager { throw new IllegalArgumentException("Empty message URI"); } try { - ISms iccISms = getISmsServiceOrThrow(); - iccISms.sendStoredMultipartText( + ISms iSms = getISmsServiceOrThrow(); + iSms.sendStoredMultipartText( getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, scAddress, sentIntents, deliveryIntents); } catch (RemoteException ex) { diff --git a/tests/TouchLatency/app/build.gradle b/tests/TouchLatency/app/build.gradle index 2594322e3727..04a878896f47 100644 --- a/tests/TouchLatency/app/build.gradle +++ b/tests/TouchLatency/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "com.prefabulated.touchlatency" - minSdkVersion 21 + minSdkVersion 28 targetSdkVersion 28 versionCode 1 versionName "1.0" diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java index 360c22f832b3..ba77a74974d1 100644 --- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java +++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java @@ -24,11 +24,15 @@ import android.graphics.Paint.Align; import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; +import android.view.Display; +import android.view.Display.Mode; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.os.Trace; +import android.view.Window; +import android.view.WindowManager; import java.math.RoundingMode; import java.text.DecimalFormat; @@ -219,14 +223,30 @@ class TouchLatencyView extends View implements View.OnTouchListener { } public class TouchLatencyActivity extends Activity { + private Mode mDisplayModes[]; + private int mCurrentModeIndex; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + Trace.beginSection("TouchLatencyActivity onCreate"); setContentView(R.layout.activity_touch_latency); mTouchView = findViewById(R.id.canvasView); + + WindowManager wm = getWindowManager(); + Display display = wm.getDefaultDisplay(); + mDisplayModes = display.getSupportedModes(); + Mode currentMode = getWindowManager().getDefaultDisplay().getMode(); + + for (int i = 0; i < mDisplayModes.length; i++) { + if (currentMode.getModeId() == mDisplayModes[i].getModeId()) { + mCurrentModeIndex = i; + break; + } + } + Trace.endSection(); } @@ -236,10 +256,35 @@ public class TouchLatencyActivity extends Activity { Trace.beginSection("TouchLatencyActivity onCreateOptionsMenu"); // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_touch_latency, menu); + if (mDisplayModes.length > 1) { + MenuItem menuItem = menu.findItem(R.id.display_mode); + Mode currentMode = getWindowManager().getDefaultDisplay().getMode(); + updateDisplayMode(menuItem, currentMode); + } Trace.endSection(); return true; } + + private void updateDisplayMode(MenuItem menuItem, Mode displayMode) { + int fps = (int) displayMode.getRefreshRate(); + menuItem.setTitle(fps + "hz"); + menuItem.setVisible(true); + } + + public void changeDisplayMode(MenuItem item) { + Window w = getWindow(); + WindowManager.LayoutParams params = w.getAttributes(); + + int modeIndex = (mCurrentModeIndex + 1) % mDisplayModes.length; + params.preferredDisplayModeId = mDisplayModes[modeIndex].getModeId(); + w.setAttributes(params); + + updateDisplayMode(item, mDisplayModes[modeIndex]); + mCurrentModeIndex = modeIndex; + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { Trace.beginSection("TouchLatencyActivity onOptionsItemSelected"); @@ -251,6 +296,8 @@ public class TouchLatencyActivity extends Activity { //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { mTouchView.changeMode(item); + } else if (id == R.id.display_mode) { + changeDisplayMode(item); } Trace.endSection(); diff --git a/tests/TouchLatency/app/src/main/res/layout/activity_touch_latency.xml b/tests/TouchLatency/app/src/main/res/layout/activity_touch_latency.xml index 8d20ff24bfe5..625757610154 100644 --- a/tests/TouchLatency/app/src/main/res/layout/activity_touch_latency.xml +++ b/tests/TouchLatency/app/src/main/res/layout/activity_touch_latency.xml @@ -18,6 +18,7 @@ android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" + android:keepScreenOn="true" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".TouchLatencyActivity"> <com.prefabulated.touchlatency.TouchLatencyView diff --git a/tests/TouchLatency/app/src/main/res/menu/menu_touch_latency.xml b/tests/TouchLatency/app/src/main/res/menu/menu_touch_latency.xml index 5aef72e8d383..52be91900ae8 100644 --- a/tests/TouchLatency/app/src/main/res/menu/menu_touch_latency.xml +++ b/tests/TouchLatency/app/src/main/res/menu/menu_touch_latency.xml @@ -15,6 +15,14 @@ --> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context=".TouchLatencyActivity"> - <item android:id="@+id/action_settings" android:title="@string/mode" - android:orderInCategory="100" android:showAsAction="always" /> + <item + android:id="@+id/action_settings" + android:orderInCategory="101" + android:showAsAction="always" + android:title="@string/mode"/> + <item + android:id="@+id/display_mode" + android:showAsAction="ifRoom" + android:title="@string/display_mode" + android:visible="false"/> </menu> diff --git a/tests/TouchLatency/app/src/main/res/values/strings.xml b/tests/TouchLatency/app/src/main/res/values/strings.xml index b97f095d501e..771992c8e5d3 100644 --- a/tests/TouchLatency/app/src/main/res/values/strings.xml +++ b/tests/TouchLatency/app/src/main/res/values/strings.xml @@ -17,4 +17,5 @@ <string name="app_name">Touch Latency</string> <string name="mode">Touch</string> + <string name="display_mode">Mode</string> </resources> diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 2fac8e0963e8..b35de59d7fcc 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -4066,8 +4066,6 @@ public class ConnectivityServiceTest { // TODO: 1. Move this outside of ConnectivityServiceTest. // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService. // 3. Mock ipsec service. - // 4. Find a free port instead of a fixed port. - final int srcPort = 12345; final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); @@ -4078,7 +4076,8 @@ public class ConnectivityServiceTest { final int invalidKaInterval = 9; final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); - final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort); + final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(); + final int srcPort = testSocket.getPort(); LinkProperties lp = new LinkProperties(); lp.setInterfaceName("wlan12"); @@ -4198,6 +4197,7 @@ public class ConnectivityServiceTest { // Check that keepalive slots start from 1 and increment. The first one gets slot 1. mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); + int srcPort2 = 0; try (SocketKeepalive ka = mCm.createSocketKeepalive( myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { ka.start(validKaInterval); @@ -4205,7 +4205,8 @@ public class ConnectivityServiceTest { // The second one gets slot 2. mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); - final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789); + final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(); + srcPort2 = testSocket2.getPort(); TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor); try (SocketKeepalive ka2 = mCm.createSocketKeepalive( myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) { @@ -4223,6 +4224,10 @@ public class ConnectivityServiceTest { } } + // Check that there is no port leaked after all keepalives and sockets are closed. + assertFalse(isUdpPortInUse(srcPort)); + assertFalse(isUdpPortInUse(srcPort2)); + mWiFiNetworkAgent.disconnect(); waitFor(mWiFiNetworkAgent.getDisconnectedCV()); mWiFiNetworkAgent = null; @@ -4305,7 +4310,6 @@ public class ConnectivityServiceTest { } private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception { - final int srcPort = 12345; final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0"); final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); @@ -4324,7 +4328,8 @@ public class ConnectivityServiceTest { // Prepare the target file descriptor, keep only one instance. final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); - final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort); + final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(); + final int srcPort = testSocket.getPort(); final ParcelFileDescriptor testPfd = ParcelFileDescriptor.dup(testSocket.getFileDescriptor()); testSocket.close(); diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp index f6c9c0e86fe4..3b3fe196736d 100644 --- a/tools/incident_section_gen/main.cpp +++ b/tools/incident_section_gen/main.cpp @@ -408,10 +408,16 @@ static bool generateSectionListCpp(Descriptor const* descriptor) { for (int i=0; i<descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); - if (field->type() != FieldDescriptor::TYPE_MESSAGE && field->type() != FieldDescriptor::TYPE_STRING) { + if (field->type() != FieldDescriptor::TYPE_MESSAGE + && field->type() != FieldDescriptor::TYPE_STRING) { continue; } + const SectionFlags s = getSectionFlags(field); + if (s.userdebug_and_eng_only()) { + printf("#if ALLOW_RESTRICTED_SECTIONS\n"); + } + switch (s.type()) { case SECTION_NONE: continue; @@ -424,8 +430,7 @@ static bool generateSectionListCpp(Descriptor const* descriptor) { printf(" NULL),\n"); break; case SECTION_DUMPSYS: - printf(" new DumpsysSection(%d, %s,", field->number(), - s.userdebug_and_eng_only() ? "true" : "false"); + printf(" new DumpsysSection(%d, ", field->number()); splitAndPrint(s.args()); printf(" NULL),\n"); break; @@ -438,9 +443,13 @@ static bool generateSectionListCpp(Descriptor const* descriptor) { printf(" NULL),\n"); break; case SECTION_TOMBSTONE: - printf(" new TombstoneSection(%d, \"%s\"),\n", field->number(), s.args().c_str()); + printf(" new TombstoneSection(%d, \"%s\"),\n", field->number(), + s.args().c_str()); break; } + if (s.userdebug_and_eng_only()) { + printf("#endif\n"); + } } printf(" NULL };\n"); diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp index daee6d6be048..a5b56a42bfbe 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -512,7 +512,7 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &at fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n"); fprintf(out, " }\n"); fprintf(out, " if (ret < 0) {\n"); - fprintf(out, " note_log_drop(ret);\n"); + fprintf(out, " note_log_drop(ret, code);\n"); fprintf(out, " }\n"); fprintf(out, " return ret;\n"); fprintf(out, "}\n"); @@ -620,7 +620,7 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &at fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n"); fprintf(out, " }\n"); fprintf(out, " if (ret < 0) {\n"); - fprintf(out, " note_log_drop(ret);\n"); + fprintf(out, " note_log_drop(ret, code);\n"); fprintf(out, " }\n"); fprintf(out, " return ret;\n\n"); fprintf(out, "}\n"); |