Merge "AudioService: fix audio mode lock" into qt-dev
diff --git a/Android.bp b/Android.bp
index c3025e8..b4110fa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -920,6 +920,7 @@
"core/java/com/android/internal/util/RingBufferIndices.java",
"core/java/com/android/internal/util/State.java",
"core/java/com/android/internal/util/StateMachine.java",
+ "core/java/com/android/internal/util/TrafficStatsConstants.java",
"core/java/com/android/internal/util/WakeupMessage.java",
"core/java/android/net/shared/*.java",
]
diff --git a/api/current.txt b/api/current.txt
index 34ba3fc..f602c9a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -224,6 +224,7 @@
field public static final int __removed3 = 16844187; // 0x101059b
field public static final int __removed4 = 16844188; // 0x101059c
field public static final int __removed5 = 16844189; // 0x101059d
+ field public static final int __removed6 = 16844182; // 0x1010596
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -750,7 +751,6 @@
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
field public static final int importantForAutofill = 16844120; // 0x1010558
- field public static final int importantForContentCapture = 16844182; // 0x1010596
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -6235,14 +6235,14 @@
}
public class TaskInfo {
- field public android.content.ComponentName baseActivity;
- field public android.content.Intent baseIntent;
+ field @Nullable public android.content.ComponentName baseActivity;
+ field @NonNull public android.content.Intent baseIntent;
field public boolean isRunning;
field public int numActivities;
- field public android.content.ComponentName origActivity;
- field public android.app.ActivityManager.TaskDescription taskDescription;
+ field @Nullable public android.content.ComponentName origActivity;
+ field @Nullable public android.app.ActivityManager.TaskDescription taskDescription;
field public int taskId;
- field public android.content.ComponentName topActivity;
+ field @Nullable public android.content.ComponentName topActivity;
}
public class TaskStackBuilder {
@@ -25138,25 +25138,6 @@
field public static final int TYPE_STRING = 4; // 0x4
}
- public final class MediaItem2 implements android.os.Parcelable {
- method public int describeContents();
- method public long getEndPosition();
- method @Nullable public android.media.MediaMetadata getMetadata();
- method public long getStartPosition();
- method public void setMetadata(@Nullable android.media.MediaMetadata);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.MediaItem2> CREATOR;
- field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
- }
-
- public static final class MediaItem2.Builder {
- ctor public MediaItem2.Builder();
- method @NonNull public android.media.MediaItem2 build();
- method @NonNull public android.media.MediaItem2.Builder setEndPosition(long);
- method @NonNull public android.media.MediaItem2.Builder setMetadata(@Nullable android.media.MediaMetadata);
- method @NonNull public android.media.MediaItem2.Builder setStartPosition(long);
- }
-
public final class MediaMetadata implements android.os.Parcelable {
method public boolean containsKey(String);
method public int describeContents();
@@ -26177,8 +26158,8 @@
ctor public Session2Command(@NonNull String, @Nullable android.os.Bundle);
method public int describeContents();
method public int getCommandCode();
- method @Nullable public String getCustomCommand();
- method @Nullable public android.os.Bundle getExtras();
+ method @Nullable public String getCustomAction();
+ method @Nullable public android.os.Bundle getCustomExtras();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Command> CREATOR;
@@ -38625,6 +38606,7 @@
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_BATTERY_SETTINGS = "android.settings.APP_BATTERY_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";
@@ -41776,7 +41758,7 @@
method public int getDisabledShowContext();
method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
method public android.os.IBinder onBind(android.content.Intent);
- method @Nullable public java.util.Set<java.lang.String> onGetSupportedVoiceActions(@NonNull java.util.Set<java.lang.String>);
+ method @NonNull public java.util.Set<java.lang.String> onGetSupportedVoiceActions(@NonNull java.util.Set<java.lang.String>);
method public void onLaunchVoiceAssistFromKeyguard();
method public void onReady();
method public void onShutdown();
@@ -47818,6 +47800,10 @@
method public boolean equals(android.util.DisplayMetrics);
method public void setTo(android.util.DisplayMetrics);
method public void setToDefaults();
+ field public static final int DENSITY_140 = 140; // 0x8c
+ field public static final int DENSITY_180 = 180; // 0xb4
+ field public static final int DENSITY_200 = 200; // 0xc8
+ field public static final int DENSITY_220 = 220; // 0xdc
field public static final int DENSITY_260 = 260; // 0x104
field public static final int DENSITY_280 = 280; // 0x118
field public static final int DENSITY_300 = 300; // 0x12c
@@ -50201,7 +50187,6 @@
method @android.view.ViewDebug.CapturedViewProperty @IdRes public int getId();
method @android.view.ViewDebug.ExportedProperty(category="accessibility", mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, to="noHideDescendants")}) public int getImportantForAccessibility();
method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS, to="yesExcludeDescendants"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS, to="noExcludeDescendants")}) public int getImportantForAutofill();
- method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS, to="yesExcludeDescendants"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS, to="noExcludeDescendants")}) public int getImportantForContentCapture();
method public boolean getKeepScreenOn();
method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
method @android.view.ViewDebug.ExportedProperty(category="accessibility") @IdRes public int getLabelFor();
@@ -50342,7 +50327,6 @@
method @android.view.ViewDebug.ExportedProperty public boolean isHovered();
method public boolean isImportantForAccessibility();
method public final boolean isImportantForAutofill();
- method public final boolean isImportantForContentCapture();
method public boolean isInEditMode();
method public boolean isInLayout();
method @android.view.ViewDebug.ExportedProperty public boolean isInTouchMode();
@@ -50417,7 +50401,6 @@
method @CallSuper public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public void onProvideAutofillStructure(android.view.ViewStructure, int);
method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
- method public void onProvideContentCaptureStructure(@NonNull android.view.ViewStructure, int);
method public void onProvideStructure(android.view.ViewStructure);
method public void onProvideVirtualStructure(android.view.ViewStructure);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -50543,7 +50526,6 @@
method public void setId(@IdRes int);
method public void setImportantForAccessibility(int);
method public void setImportantForAutofill(int);
- method public void setImportantForContentCapture(int);
method public void setKeepScreenOn(boolean);
method public void setKeyboardNavigationCluster(boolean);
method public void setLabelFor(@IdRes int);
@@ -50722,11 +50704,6 @@
field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0; // 0x0
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 2; // 0x2
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 1; // 0x1
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -51532,6 +51509,7 @@
method public android.transition.Transition getSharedElementReturnTransition();
method public boolean getSharedElementsUseOverlay();
method @ColorInt public abstract int getStatusBarColor();
+ method @NonNull public java.util.List<android.graphics.Rect> getSystemGestureExclusionRects();
method public long getTransitionBackgroundFadeDuration();
method public android.transition.TransitionManager getTransitionManager();
method public abstract int getVolumeControlStream();
@@ -51610,6 +51588,7 @@
method public void setSoftInputMode(int);
method public abstract void setStatusBarColor(@ColorInt int);
method public void setSustainedPerformanceMode(boolean);
+ method public void setSystemGestureExclusionRects(@NonNull java.util.List<android.graphics.Rect>);
method public abstract void setTitle(CharSequence);
method @Deprecated public abstract void setTitleColor(@ColorInt int);
method public void setTransitionBackgroundFadeDuration(long);
@@ -52834,7 +52813,7 @@
method @Nullable public java.util.Set<android.view.contentcapture.ContentCaptureCondition> getContentCaptureConditions();
method @Nullable public android.content.ComponentName getServiceComponentName();
method public boolean isContentCaptureEnabled();
- method public void removeUserData(@NonNull android.view.contentcapture.UserDataRemovalRequest);
+ method public void removeData(@NonNull android.view.contentcapture.DataRemovalRequest);
method public void setContentCaptureEnabled(boolean);
}
@@ -52845,6 +52824,7 @@
method @Nullable public final android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
method @NonNull public final android.view.contentcapture.ContentCaptureSessionId getContentCaptureSessionId();
method @NonNull public android.view.autofill.AutofillId newAutofillId(@NonNull android.view.autofill.AutofillId, long);
+ method @NonNull public final android.view.ViewStructure newViewStructure(@NonNull android.view.View);
method @NonNull public final android.view.ViewStructure newVirtualViewStructure(@NonNull android.view.autofill.AutofillId, long);
method public final void notifyViewAppeared(@NonNull android.view.ViewStructure);
method public final void notifyViewDisappeared(@NonNull android.view.autofill.AutofillId);
@@ -52859,24 +52839,24 @@
field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureSessionId> CREATOR;
}
- public final class UserDataRemovalRequest implements android.os.Parcelable {
+ public final class DataRemovalRequest implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.LocusIdRequest> getLocusIdRequests();
+ method @NonNull public java.util.List<android.view.contentcapture.DataRemovalRequest.LocusIdRequest> getLocusIdRequests();
method @NonNull public String getPackageName();
method public boolean isForEverything();
method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.UserDataRemovalRequest> CREATOR;
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.DataRemovalRequest> CREATOR;
field public static final int FLAG_IS_PREFIX = 1; // 0x1
}
- public static final class UserDataRemovalRequest.Builder {
- ctor public UserDataRemovalRequest.Builder();
- method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, int);
- method @NonNull public android.view.contentcapture.UserDataRemovalRequest build();
- method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder forEverything();
+ public static final class DataRemovalRequest.Builder {
+ ctor public DataRemovalRequest.Builder();
+ method @NonNull public android.view.contentcapture.DataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, int);
+ method @NonNull public android.view.contentcapture.DataRemovalRequest build();
+ method @NonNull public android.view.contentcapture.DataRemovalRequest.Builder forEverything();
}
- public final class UserDataRemovalRequest.LocusIdRequest {
+ public final class DataRemovalRequest.LocusIdRequest {
method @NonNull public int getFlags();
method @NonNull public android.content.LocusId getLocusId();
}
@@ -53426,6 +53406,7 @@
method public int describeContents();
method @Nullable public String getCallingPackageName();
method @NonNull public java.util.List<android.view.textclassifier.ConversationActions.Message> getConversation();
+ method @NonNull public android.os.Bundle getExtras();
method @Nullable public java.util.List<java.lang.String> getHints();
method @IntRange(from=0xffffffff) public int getMaxSuggestions();
method @NonNull public android.view.textclassifier.TextClassifier.EntityConfig getTypeConfig();
@@ -53438,6 +53419,7 @@
public static final class ConversationActions.Request.Builder {
ctor public ConversationActions.Request.Builder(@NonNull java.util.List<android.view.textclassifier.ConversationActions.Message>);
method @NonNull public android.view.textclassifier.ConversationActions.Request build();
+ method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setExtras(@Nullable android.os.Bundle);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setHints(@Nullable java.util.List<java.lang.String>);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(@IntRange(from=0xffffffff) int);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(@Nullable android.view.textclassifier.TextClassifier.EntityConfig);
@@ -53634,29 +53616,23 @@
method @NonNull public android.view.textclassifier.TextClassifier.EntityConfig.Builder setIncludedTypes(@Nullable java.util.Collection<java.lang.String>);
}
- public final class TextClassifierEvent implements android.os.Parcelable {
+ public abstract class TextClassifierEvent implements android.os.Parcelable {
method public int describeContents();
method @NonNull public int[] getActionIndices();
method @NonNull public String[] getEntityTypes();
method public int getEventCategory();
method @Nullable public android.view.textclassifier.TextClassificationContext getEventContext();
method public int getEventIndex();
- method public long getEventTime();
method public int getEventType();
method @NonNull public android.os.Bundle getExtras();
- method @Nullable public String getLanguage();
- method public int getRelativeSuggestedWordEndIndex();
- method public int getRelativeSuggestedWordStartIndex();
- method public int getRelativeWordEndIndex();
- method public int getRelativeWordStartIndex();
+ method @Nullable public String getModelName();
method @Nullable public String getResultId();
- method public float getScore();
+ method @NonNull public float[] getScores();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CATEGORY_CONVERSATION_ACTIONS = 3; // 0x3
field public static final int CATEGORY_LANGUAGE_DETECTION = 4; // 0x4
field public static final int CATEGORY_LINKIFY = 2; // 0x2
field public static final int CATEGORY_SELECTION = 1; // 0x1
- field public static final int CATEGORY_UNDEFINED = 0; // 0x0
field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent> CREATOR;
field public static final int TYPE_ACTIONS_GENERATED = 20; // 0x14
field public static final int TYPE_ACTIONS_SHOWN = 6; // 0x6
@@ -53678,25 +53654,63 @@
field public static final int TYPE_SMART_ACTION = 13; // 0xd
field public static final int TYPE_SMART_SELECTION_MULTI = 4; // 0x4
field public static final int TYPE_SMART_SELECTION_SINGLE = 3; // 0x3
- field public static final int TYPE_UNDEFINED = 0; // 0x0
}
- public static final class TextClassifierEvent.Builder {
- ctor public TextClassifierEvent.Builder(int, int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent build();
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setActionIndices(@NonNull int...);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEntityTypes(@NonNull java.lang.String...);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventContext(@Nullable android.view.textclassifier.TextClassificationContext);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventTime(long);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setExtras(@NonNull android.os.Bundle);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setLanguage(@Nullable String);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeSuggestedWordEndIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeSuggestedWordStartIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeWordEndIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeWordStartIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setResultId(@Nullable String);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setScore(float);
+ public abstract static class TextClassifierEvent.Builder<T extends android.view.textclassifier.TextClassifierEvent.Builder<T>> {
+ method @NonNull public T setActionIndices(@NonNull int...);
+ method @NonNull public T setEntityTypes(@NonNull java.lang.String...);
+ method @NonNull public T setEventContext(@Nullable android.view.textclassifier.TextClassificationContext);
+ method @NonNull public T setEventIndex(int);
+ method @NonNull public T setExtras(@NonNull android.os.Bundle);
+ method @NonNull public T setModelName(@Nullable String);
+ method @NonNull public T setResultId(@Nullable String);
+ method @NonNull public T setScores(@NonNull float...);
+ }
+
+ public static final class TextClassifierEvent.ConversationActionsEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent> CREATOR;
+ }
+
+ public static final class TextClassifierEvent.ConversationActionsEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent.Builder> {
+ ctor public TextClassifierEvent.ConversationActionsEvent.Builder(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent build();
+ }
+
+ public static final class TextClassifierEvent.LanguageDetectionEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+ method @Nullable public android.icu.util.ULocale getLocale();
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent> CREATOR;
+ }
+
+ public static final class TextClassifierEvent.LanguageDetectionEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent.Builder> {
+ ctor public TextClassifierEvent.LanguageDetectionEvent.Builder(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent build();
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent.Builder setLocale(@Nullable android.icu.util.ULocale);
+ }
+
+ public static final class TextClassifierEvent.TextLinkifyEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent> CREATOR;
+ }
+
+ public static final class TextClassifierEvent.TextLinkifyEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent.Builder> {
+ ctor public TextClassifierEvent.TextLinkifyEvent.Builder(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent build();
+ }
+
+ public static final class TextClassifierEvent.TextSelectionEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+ method public int getRelativeSuggestedWordEndIndex();
+ method public int getRelativeSuggestedWordStartIndex();
+ method public int getRelativeWordEndIndex();
+ method public int getRelativeWordStartIndex();
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.TextSelectionEvent> CREATOR;
+ }
+
+ public static final class TextClassifierEvent.TextSelectionEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder> {
+ ctor public TextClassifierEvent.TextSelectionEvent.Builder(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent build();
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeSuggestedWordEndIndex(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeSuggestedWordStartIndex(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeWordEndIndex(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeWordStartIndex(int);
}
public final class TextLanguage implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9e730db..b60e850 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -604,7 +604,7 @@
public final class Vr2dDisplayProperties implements android.os.Parcelable {
ctor public Vr2dDisplayProperties(int, int, int);
method public int describeContents();
- method public void dump(java.io.PrintWriter, String);
+ method public void dump(@NonNull java.io.PrintWriter, @NonNull String);
method public int getAddedFlags();
method public int getDpi();
method public int getHeight();
@@ -615,26 +615,26 @@
field public static final int FLAG_VIRTUAL_DISPLAY_ENABLED = 1; // 0x1
}
- public static class Vr2dDisplayProperties.Builder {
+ public static final class Vr2dDisplayProperties.Builder {
ctor public Vr2dDisplayProperties.Builder();
- method public android.app.Vr2dDisplayProperties.Builder addFlags(int);
- method public android.app.Vr2dDisplayProperties build();
- method public android.app.Vr2dDisplayProperties.Builder removeFlags(int);
- method public android.app.Vr2dDisplayProperties.Builder setDimensions(int, int, int);
- method public android.app.Vr2dDisplayProperties.Builder setEnabled(boolean);
+ method @NonNull public android.app.Vr2dDisplayProperties.Builder addFlags(int);
+ method @NonNull public android.app.Vr2dDisplayProperties build();
+ method @NonNull public android.app.Vr2dDisplayProperties.Builder removeFlags(int);
+ method @NonNull public android.app.Vr2dDisplayProperties.Builder setDimensions(int, int, int);
+ method @NonNull public android.app.Vr2dDisplayProperties.Builder setEnabled(boolean);
}
public class VrManager {
method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public int getVr2dDisplayId();
method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public boolean isPersistentVrModeEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public boolean isVrModeEnabled();
- method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public void registerVrStateCallback(@NonNull java.util.concurrent.Executor, android.app.VrStateCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public void registerVrStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.VrStateCallback);
method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setAndBindVrCompositor(android.content.ComponentName);
method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setPersistentVrModeEnabled(boolean);
method @RequiresPermission("android.permission.ACCESS_VR_MANAGER") public void setStandbyEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setVr2dDisplayProperties(android.app.Vr2dDisplayProperties);
- method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setVrInputMethod(android.content.ComponentName);
- method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public void unregisterVrStateCallback(android.app.VrStateCallback);
+ method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setVr2dDisplayProperties(@NonNull android.app.Vr2dDisplayProperties);
+ method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setVrInputMethod(@Nullable android.content.ComponentName);
+ method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public void unregisterVrStateCallback(@NonNull android.app.VrStateCallback);
}
public abstract class VrStateCallback {
@@ -1092,12 +1092,14 @@
}
public static final class AppTarget.Builder {
- ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+ ctor @Deprecated public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+ ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
+ ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
method @NonNull public android.app.prediction.AppTarget build();
method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
- method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
- method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
+ method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
+ method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
}
public final class AppTargetEvent implements android.os.Parcelable {
@@ -4226,9 +4228,12 @@
method public static void setThreadStatsTagApp();
method public static void setThreadStatsTagBackup();
method public static void setThreadStatsTagRestore();
- field public static final int TAG_SYSTEM_DHCP = -192; // 0xffffff40
- field public static final int TAG_SYSTEM_DHCP_SERVER = -186; // 0xffffff46
- field public static final int TAG_SYSTEM_PROBE = -190; // 0xffffff42
+ field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = -113; // 0xffffff8f
+ field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = -128; // 0xffffff80
+ field public static final int TAG_NETWORK_STACK_RANGE_END = -257; // 0xfffffeff
+ field public static final int TAG_NETWORK_STACK_RANGE_START = -768; // 0xfffffd00
+ field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = -241; // 0xffffff0f
+ field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = -256; // 0xffffff00
}
public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
@@ -5822,7 +5827,6 @@
public final class DeviceConfig {
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(@NonNull String, @NonNull String, float);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(@NonNull String, @NonNull String, int);
@@ -5830,7 +5834,6 @@
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
field public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
@@ -5863,10 +5866,6 @@
method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
}
- public static interface DeviceConfig.OnPropertyChangedListener {
- method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
- }
-
public static class DeviceConfig.Properties {
method public boolean getBoolean(@NonNull String, boolean);
method public float getFloat(@NonNull String, float);
@@ -6274,7 +6273,6 @@
public abstract class AttentionService extends android.app.Service {
ctor public AttentionService();
- method public final void disableSelf();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onCancelAttentionCheck(@NonNull android.service.attention.AttentionService.AttentionCallback);
method public abstract void onCheckAttention(@NonNull android.service.attention.AttentionService.AttentionCallback);
@@ -6395,9 +6393,9 @@
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
+ method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
- method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 5d74e17..8f71122 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -125,6 +125,19 @@
}
+package android.provider {
+
+ public final class DeviceConfig {
+ method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+ method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+ }
+
+ public static interface DeviceConfig.OnPropertyChangedListener {
+ method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
+ }
+
+}
+
package android.service.notification {
public abstract class NotificationListenerService extends android.app.Service {
diff --git a/api/test-current.txt b/api/test-current.txt
index a0de7f3..f76b383 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -498,12 +498,13 @@
}
public static final class AppTarget.Builder {
- ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+ ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
+ ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
method @NonNull public android.app.prediction.AppTarget build();
method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
- method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
- method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
+ method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
+ method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
}
public final class AppTargetEvent implements android.os.Parcelable {
@@ -1105,6 +1106,7 @@
method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
+ field public static final int SUCCESS = 0; // 0x0
}
public static final class AudioRecord.MetricsConstants {
@@ -1130,22 +1132,6 @@
field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate";
}
- public final class BufferingParams implements android.os.Parcelable {
- method public int describeContents();
- method public int getInitialMarkMs();
- method public int getResumePlaybackMarkMs();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.BufferingParams> CREATOR;
- }
-
- public static class BufferingParams.Builder {
- ctor public BufferingParams.Builder();
- ctor public BufferingParams.Builder(android.media.BufferingParams);
- method public android.media.BufferingParams build();
- method public android.media.BufferingParams.Builder setInitialMarkMs(int);
- method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int);
- }
-
public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size);
ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size);
@@ -1242,8 +1228,10 @@
method public int detachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
method public int getFocusDuckingBehavior();
method public int getStatus();
+ method public boolean removeUidDeviceAffinity(int);
method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setRegistration(String);
+ method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
method public String toLogFriendlyString();
field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
@@ -1460,9 +1448,6 @@
method public static long getLoopbackRxPackets();
method public static long getLoopbackTxBytes();
method public static long getLoopbackTxPackets();
- field public static final int TAG_SYSTEM_DHCP = -192; // 0xffffff40
- field public static final int TAG_SYSTEM_DHCP_SERVER = -186; // 0xffffff46
- field public static final int TAG_SYSTEM_PROBE = -190; // 0xffffff42
}
}
@@ -2213,7 +2198,6 @@
public final class DeviceConfig {
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static float getFloat(@NonNull String, @NonNull String, float);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static int getInt(@NonNull String, @NonNull String, int);
@@ -2221,7 +2205,6 @@
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(@NonNull String, @NonNull String);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getString(@NonNull String, @NonNull String, @Nullable String);
method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
field public static final String NAMESPACE_AUTOFILL = "autofill";
@@ -2235,10 +2218,6 @@
method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
}
- public static interface DeviceConfig.OnPropertyChangedListener {
- method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
- }
-
public static class DeviceConfig.Properties {
method public boolean getBoolean(@NonNull String, boolean);
method public float getFloat(@NonNull String, float);
@@ -2552,9 +2531,9 @@
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
+ method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
- method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
diff --git a/api/test-removed.txt b/api/test-removed.txt
index d802177..83a5708 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -1 +1,14 @@
// Signature format: 2.0
+package android.provider {
+
+ public final class DeviceConfig {
+ method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+ method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+ }
+
+ public static interface DeviceConfig.OnPropertyChangedListener {
+ method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
+ }
+
+}
+
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index 47617e0..bb8d927 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -16,6 +16,7 @@
#include <sys/stat.h> // umask
#include <sys/types.h> // umask
+
#include <fstream>
#include <memory>
#include <ostream>
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index 677c6fa..b7ae9d0 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -31,15 +31,14 @@
#include "androidfw/ResourceUtils.h"
#include "androidfw/StringPiece.h"
#include "androidfw/Util.h"
-#include "utils/String16.h"
-#include "utils/String8.h"
-
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
#include "idmap2/Result.h"
#include "idmap2/SysTrace.h"
#include "idmap2/Xml.h"
#include "idmap2/ZipFile.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
using android::ApkAssets;
using android::ApkAssetsCookie;
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index d8867fe..8794908 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -23,12 +23,11 @@
#include <string>
#include <vector>
+#include "Commands.h"
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Result.h"
#include "idmap2/SysTrace.h"
-#include "Commands.h"
-
using android::idmap2::CommandLineOptions;
using android::idmap2::Result;
using android::idmap2::Unit;
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 55b1003..fa9a77a 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -15,6 +15,7 @@
*/
#include <dirent.h>
+
#include <fstream>
#include <memory>
#include <ostream>
@@ -24,8 +25,8 @@
#include <utility>
#include <vector>
+#include "Commands.h"
#include "android-base/properties.h"
-
#include "idmap2/CommandLineOptions.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
@@ -35,8 +36,6 @@
#include "idmap2/Xml.h"
#include "idmap2/ZipFile.h"
-#include "Commands.h"
-
using android::idmap2::CommandLineOptions;
using android::idmap2::Error;
using android::idmap2::Idmap;
@@ -211,7 +210,9 @@
const auto create_ok = Create(create_args);
if (!create_ok) {
- return Error(create_ok.GetError(), "failed to create idmap");
+ LOG(WARNING) << "failed to create idmap for overlay apk path \"" << overlay.apk_path
+ << "\": " << create_ok.GetError().GetMessage();
+ continue;
}
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 4f65379..8ee79f6 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idmap2d/Idmap2Service.h"
+
#include <sys/stat.h> // umask
#include <sys/types.h> // umask
#include <unistd.h>
@@ -28,15 +30,12 @@
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "binder/IPCThreadState.h"
-#include "utils/String8.h"
-
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
#include "idmap2/Policies.h"
#include "idmap2/SysTrace.h"
-
-#include "idmap2d/Idmap2Service.h"
+#include "utils/String8.h"
using android::IPCThreadState;
using android::binder::Status;
diff --git a/cmds/idmap2/idmap2d/Main.cpp b/cmds/idmap2/idmap2d/Main.cpp
index 4393dcc..2707049 100644
--- a/cmds/idmap2/idmap2d/Main.cpp
+++ b/cmds/idmap2/idmap2d/Main.cpp
@@ -21,13 +21,11 @@
#include <binder/ProcessState.h>
#include <cstdlib> // EXIT_{FAILURE,SUCCESS}
-
#include <iostream>
#include <sstream>
-#include "android-base/macros.h"
-
#include "Idmap2Service.h"
+#include "android-base/macros.h"
using android::BinderService;
using android::IPCThreadState;
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 5cc0664b..ebbb5ffc 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -52,11 +52,9 @@
#include <vector>
#include "android-base/macros.h"
-
#include "androidfw/ApkAssets.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
-
#include "idmap2/Policies.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h
index cd76b84..90c698c 100644
--- a/cmds/idmap2/include/idmap2/Policies.h
+++ b/cmds/idmap2/include/idmap2/Policies.h
@@ -17,11 +17,10 @@
#include <string>
#include <vector>
+#include "Result.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
-#include "Result.h"
-
#ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
#define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index c388f4b..5111bb2 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -21,7 +21,6 @@
#include <memory>
#include "androidfw/AssetManager2.h"
-
#include "idmap2/Idmap.h"
namespace android {
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index 7e33b3b..2e543d4 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -22,7 +22,6 @@
#include <string>
#include "androidfw/AssetManager2.h"
-
#include "idmap2/Idmap.h"
namespace android {
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
index 1d81c48..8797a78 100644
--- a/cmds/idmap2/include/idmap2/ResourceUtils.h
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -21,7 +21,6 @@
#include <string>
#include "androidfw/AssetManager2.h"
-
#include "idmap2/Idmap.h"
#include "idmap2/Result.h"
#include "idmap2/ZipFile.h"
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index 9651328..dee2d21 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -14,14 +14,14 @@
* limitations under the License.
*/
+#include "idmap2/BinaryStreamVisitor.h"
+
#include <algorithm>
#include <cstring>
#include <string>
#include "android-base/macros.h"
-#include "idmap2/BinaryStreamVisitor.h"
-
namespace android::idmap2 {
void BinaryStreamVisitor::Write16(uint16_t value) {
diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
index d5fd2ce..5b0ae92 100644
--- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp
+++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idmap2/CommandLineOptions.h"
+
#include <algorithm>
#include <iomanip>
#include <iostream>
@@ -24,8 +26,6 @@
#include <vector>
#include "android-base/macros.h"
-
-#include "idmap2/CommandLineOptions.h"
#include "idmap2/Result.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp
index a9b68cd..3e8e329 100644
--- a/cmds/idmap2/libidmap2/FileUtils.cpp
+++ b/cmds/idmap2/libidmap2/FileUtils.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idmap2/FileUtils.h"
+
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
@@ -33,8 +35,6 @@
#include "android-base/stringprintf.h"
#include "private/android_filesystem_config.h"
-#include "idmap2/FileUtils.h"
-
namespace android::idmap2::utils {
std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 49470b4..aec1a6f 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idmap2/Idmap.h"
+
#include <algorithm>
#include <iostream>
#include <iterator>
@@ -28,14 +30,12 @@
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "androidfw/AssetManager2.h"
-#include "utils/String16.h"
-#include "utils/String8.h"
-
-#include "idmap2/Idmap.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
#include "idmap2/SysTrace.h"
#include "idmap2/ZipFile.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp
index 7c45556..0a0cecf 100644
--- a/cmds/idmap2/libidmap2/Policies.cpp
+++ b/cmds/idmap2/libidmap2/Policies.cpp
@@ -14,15 +14,15 @@
* limitations under the License.
*/
+#include "idmap2/Policies.h"
+
#include <iterator>
#include <map>
#include <string>
#include <vector>
#include "androidfw/ResourceTypes.h"
-
#include "idmap2/Idmap.h"
-#include "idmap2/Policies.h"
#include "idmap2/Result.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index fc967799..fbf2c77 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
+#include "idmap2/PrettyPrintVisitor.h"
+
#include <string>
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "androidfw/ApkAssets.h"
-
-#include "idmap2/PrettyPrintVisitor.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 1149c90..dd14fd4 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -14,14 +14,14 @@
* limitations under the License.
*/
+#include "idmap2/RawPrintVisitor.h"
+
#include <cstdarg>
#include <string>
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "androidfw/ApkAssets.h"
-
-#include "idmap2/RawPrintVisitor.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp
index a24836d..71ba3f0 100644
--- a/cmds/idmap2/libidmap2/ResourceUtils.cpp
+++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
+#include "idmap2/ResourceUtils.h"
+
#include <memory>
#include <string>
#include "androidfw/StringPiece.h"
#include "androidfw/Util.h"
-
-#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
#include "idmap2/Xml.h"
#include "idmap2/ZipFile.h"
diff --git a/cmds/idmap2/libidmap2/Result.cpp b/cmds/idmap2/libidmap2/Result.cpp
index 471dab2..1eac25f 100644
--- a/cmds/idmap2/libidmap2/Result.cpp
+++ b/cmds/idmap2/libidmap2/Result.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
+#include "idmap2/Result.h"
+
#include <cstdarg>
#include "android-base/stringprintf.h"
-#include "idmap2/Result.h"
-
namespace android::idmap2 {
// NOLINTNEXTLINE(cert-dcl50-cpp)
diff --git a/cmds/idmap2/libidmap2/Xml.cpp b/cmds/idmap2/libidmap2/Xml.cpp
index 0075a92..2645868 100644
--- a/cmds/idmap2/libidmap2/Xml.cpp
+++ b/cmds/idmap2/libidmap2/Xml.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
+#include "idmap2/Xml.h"
+
#include <map>
#include <memory>
#include <string>
#include <utility>
-#include "idmap2/Xml.h"
-
namespace android::idmap2 {
std::unique_ptr<const Xml> Xml::Create(const uint8_t* data, size_t size, bool copyData) {
diff --git a/cmds/idmap2/libidmap2/ZipFile.cpp b/cmds/idmap2/libidmap2/ZipFile.cpp
index 0f07324..812fd6e 100644
--- a/cmds/idmap2/libidmap2/ZipFile.cpp
+++ b/cmds/idmap2/libidmap2/ZipFile.cpp
@@ -14,11 +14,12 @@
* limitations under the License.
*/
+#include "idmap2/ZipFile.h"
+
#include <memory>
#include <string>
#include "idmap2/Result.h"
-#include "idmap2/ZipFile.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 9a5b633..9cdc86c 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -19,17 +19,14 @@
#include <string>
#include <utility>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "androidfw/ApkAssets.h"
#include "androidfw/Idmap.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/Idmap.h"
-#include "TestHelpers.h"
-
using ::testing::NotNull;
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
index d567af6..6e83fc9 100644
--- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp
+++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
@@ -25,19 +25,16 @@
#include <string>
#include <vector>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "android-base/file.h"
#include "androidfw/ApkAssets.h"
#include "androidfw/Idmap.h"
#include "androidfw/LoadedArsc.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
-#include "TestHelpers.h"
-
namespace android::idmap2 {
TEST(CommandLineOptionsTests, Flag) {
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 34a0097..f4a306e 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -15,19 +15,17 @@
*/
#include <dirent.h>
+
#include <set>
#include <string>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
-#include "private/android_filesystem_config.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/FileUtils.h"
-
-#include "TestHelpers.h"
+#include "private/android_filesystem_config.h"
using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 91bc4dd..c18744c 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -34,16 +34,13 @@
#include <string>
#include <vector>
+#include "TestHelpers.h"
+#include "androidfw/PosixUtils.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
-#include "androidfw/PosixUtils.h"
-#include "private/android_filesystem_config.h"
-
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
-
-#include "TestHelpers.h"
+#include "private/android_filesystem_config.h"
using ::android::util::ExecuteBinary;
using ::testing::NotNull;
@@ -264,6 +261,24 @@
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
ASSERT_EQ(result->stdout, "");
+
+ // the signature idmap failing to generate should not cause scanning to fail
+ // clang-format off
+ result = ExecuteBinary({"idmap2",
+ "scan",
+ "--input-directory", GetTestDataPath(),
+ "--recursive",
+ "--target-package-name", "test.target",
+ "--target-apk-path", GetTargetApkPath(),
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
+ // clang-format on
+ ASSERT_THAT(result, NotNull());
+ ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+ ASSERT_EQ(result->stdout, expected.str());
+ unlink(idmap_static_no_name_path.c_str());
+ unlink(idmap_static_2_path.c_str());
+ unlink(idmap_static_1_path.c_str());
}
TEST_F(Idmap2BinaryTests, Lookup) {
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 621f503..90fe9a7 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -15,7 +15,6 @@
*/
#include <cstdio> // fclose
-
#include <fstream>
#include <memory>
#include <sstream>
@@ -23,18 +22,15 @@
#include <utility>
#include <vector>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "android-base/macros.h"
#include "androidfw/ApkAssets.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
-#include "TestHelpers.h"
-
using ::testing::IsNull;
using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/Main.cpp b/cmds/idmap2/tests/Main.cpp
index 2b13fed..3e753e9 100644
--- a/cmds/idmap2/tests/Main.cpp
+++ b/cmds/idmap2/tests/Main.cpp
@@ -16,11 +16,9 @@
#include <string>
-#include "android-base/file.h"
-
-#include "gtest/gtest.h"
-
#include "TestHelpers.h"
+#include "android-base/file.h"
+#include "gtest/gtest.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp
index a76da53..e30da76 100644
--- a/cmds/idmap2/tests/PoliciesTests.cpp
+++ b/cmds/idmap2/tests/PoliciesTests.cpp
@@ -16,9 +16,8 @@
#include <string>
-#include "gtest/gtest.h"
-
#include "TestHelpers.h"
+#include "gtest/gtest.h"
#include "idmap2/Policies.h"
using android::idmap2::PolicyBitmask;
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 27a3880..c412504 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -18,18 +18,15 @@
#include <sstream>
#include <string>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "androidfw/ApkAssets.h"
#include "androidfw/Idmap.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/Idmap.h"
#include "idmap2/Policies.h"
#include "idmap2/PrettyPrintVisitor.h"
-#include "TestHelpers.h"
-
using ::testing::NotNull;
using android::ApkAssets;
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 7372148..64518fd 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -19,14 +19,12 @@
#include <sstream>
#include <string>
+#include "TestHelpers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
#include "idmap2/Idmap.h"
#include "idmap2/RawPrintVisitor.h"
-#include "TestHelpers.h"
-
using ::testing::NotNull;
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp
index ad78685..9ed807c 100644
--- a/cmds/idmap2/tests/ResourceUtilsTests.cpp
+++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp
@@ -17,15 +17,13 @@
#include <memory>
#include <string>
+#include "TestHelpers.h"
+#include "androidfw/ApkAssets.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
-#include "androidfw/ApkAssets.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
-#include "TestHelpers.h"
-
using ::testing::NotNull;
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/ResultTests.cpp b/cmds/idmap2/tests/ResultTests.cpp
index 5f4daed..cbced0a 100644
--- a/cmds/idmap2/tests/ResultTests.cpp
+++ b/cmds/idmap2/tests/ResultTests.cpp
@@ -20,7 +20,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
#include "idmap2/Result.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index 45525a5..adea329 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -19,6 +19,9 @@
#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
namespace android::idmap2 {
const unsigned char idmap_raw_data[] = {
diff --git a/cmds/idmap2/tests/XmlTests.cpp b/cmds/idmap2/tests/XmlTests.cpp
index fe79d8f..df63211 100644
--- a/cmds/idmap2/tests/XmlTests.cpp
+++ b/cmds/idmap2/tests/XmlTests.cpp
@@ -16,13 +16,11 @@
#include <cstdio> // fclose
-#include "idmap2/Xml.h"
-#include "idmap2/ZipFile.h"
-
+#include "TestHelpers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
-#include "TestHelpers.h"
+#include "idmap2/Xml.h"
+#include "idmap2/ZipFile.h"
using ::testing::IsNull;
using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/ZipFileTests.cpp b/cmds/idmap2/tests/ZipFileTests.cpp
index 79be43c..3fca436 100644
--- a/cmds/idmap2/tests/ZipFileTests.cpp
+++ b/cmds/idmap2/tests/ZipFileTests.cpp
@@ -17,13 +17,11 @@
#include <cstdio> // fclose
#include <string>
-#include "idmap2/Result.h"
-#include "idmap2/ZipFile.h"
-
+#include "TestHelpers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
-#include "TestHelpers.h"
+#include "idmap2/Result.h"
+#include "idmap2/ZipFile.h"
using ::testing::IsNull;
using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
index 9e6a453..5df0bea 100644
--- a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
@@ -19,5 +19,7 @@
<application android:hasCode="false"/>
<overlay
android:targetPackage="test.target"
- android:targetName="TestResources"/>
+ android:targetName="TestResources"
+ android:isStatic="true"
+ android:priority="10"/>
</manifest>
diff --git a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
index b2c490d..51e19de 100644
--- a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
+++ b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
Binary files differ
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 55d3fba..d28108c 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -268,7 +268,8 @@
TouchGestureClassified touch_gesture_classified = 177;
HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
StyleUIChanged style_ui_changed = 179;
- PrivacyIndicatorsInteracted privacy_indicators_interacted = 180;
+ PrivacyIndicatorsInteracted privacy_indicators_interacted =
+ 180 [(log_from_module) = "permissioncontroller"];
AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"];
AppMovedStorageReported app_moved_storage_reported = 183;
@@ -340,6 +341,7 @@
SystemIonHeapSize system_ion_heap_size = 10056;
AppsOnExternalStorageInfo apps_on_external_storage_info = 10057;
FaceSettings face_settings = 10058;
+ CoolingDevice cooling_device = 10059;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -410,17 +412,25 @@
* frameworks/base/services/core/java/com/android/server/stats/StatsCompanionService.java
*/
message ThermalThrottlingStateChanged {
+ // The type of temperature being reported (CPU, GPU, SKIN, etc)
optional android.os.TemperatureTypeEnum sensor_type = 1;
+ // Throttling state, this field is DEPRECATED
enum State {
UNKNOWN = 0;
- START = 1;
- STOP = 2;
+ START = 1; // START indicated that throttling was triggered.
+ STOP = 2; // STOP indicates that throttling was cleared.
}
-
optional State state = 2;
+ // Temperature in deci degrees celsius
optional float temperature = 3;
+
+ // Severity of throttling
+ optional android.os.ThrottlingSeverityEnum severity = 4;
+
+ // Thermistor name
+ optional string sensor_name = 5;
}
/**
@@ -3957,8 +3967,7 @@
* Pulls the temperature of various parts of the device.
* The units are tenths of a degree Celsius. Eg: 30.3C is reported as 303.
*
- * Pulled from:
- * frameworks/base/cmds/statsd/src/external/ResourceThermalManagerPuller.cpp
+ * Pulled from StatsCompanionService.java
*/
message Temperature {
// The type of temperature being reported. Eg. CPU, GPU, SKIN, BATTERY, BCL_.
@@ -3970,6 +3979,9 @@
// Temperature in tenths of a degree C.
// For BCL, it is decimillivolt, decimilliamps, and percentage * 10.
optional int32 temperature_deci_celsius = 3;
+
+ // Relative severity of the throttling, see enum definition.
+ optional android.os.ThrottlingSeverityEnum severity = 4;
}
/**
@@ -5947,3 +5959,19 @@
// Whether or not a diverse set of poses are required during enrollment.
optional bool unlock_diversity_required = 6;
}
+
+/**
+ * Logs cooling devices maintained by the kernel.
+ *
+ * Pulled from StatsCompanionService.java
+ */
+message CoolingDevice {
+ // The type of cooling device being reported. Eg. CPU, GPU...
+ optional android.os.CoolingTypeEnum device_location = 1;
+ // The name of the cooling device source. Eg. CPU0
+ optional string device_name = 2;
+ // Current throttle state of the cooling device. The value can any unsigned
+ // integer between 0 and max_state defined in its driver. 0 means device is
+ // not in throttling, higher value means deeper throttling.
+ optional int32 state = 3;
+}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 51839c4..ca73059 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -159,6 +159,9 @@
// temperature
{android::util::TEMPERATURE,
{.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
+ // cooling_device
+ {android::util::COOLING_DEVICE,
+ {.puller = new StatsCompanionServicePuller(android::util::COOLING_DEVICE)}},
// binder_calls
{android::util::BINDER_CALLS,
{.additiveFields = {4, 5, 6, 8, 12},
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 5f972c9..6e935e1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -127,7 +127,6 @@
import android.view.autofill.IAutofillWindowPresenter;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
@@ -724,7 +723,7 @@
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback,
- AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
+ AutofillManager.AutofillClient {
private static final String TAG = "Activity";
private static final boolean DEBUG_LIFECYCLE = false;
@@ -1124,12 +1123,6 @@
return this;
}
- /** @hide */
- @Override
- public final ContentCaptureClient getContentCaptureClient() {
- return this;
- }
-
/**
* Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
* lifecycle callbacks for only this Activity.
@@ -6509,12 +6502,6 @@
return getComponentName();
}
- /** @hide */
- @Override
- public final ComponentName contentCaptureClientGetComponentName() {
- return getComponentName();
- }
-
/**
* Retrieve a {@link SharedPreferences} object for accessing preferences
* that are private to this activity. This simply calls the underlying
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 143361f..5e5611b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -16,6 +16,7 @@
package android.app;
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
@@ -27,6 +28,8 @@
import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
@@ -193,6 +196,7 @@
import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
final class RemoteServiceException extends AndroidRuntimeException {
public RemoteServiceException(String msg) {
@@ -225,6 +229,11 @@
public static final boolean DEBUG_ORDER = false;
private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
/**
+ * If the activity doesn't become idle in time, the timeout will ensure to apply the pending top
+ * process state.
+ */
+ private static final long PENDING_TOP_PROCESS_STATE_TIMEOUT = 1000;
+ /**
* The delay to release the provider when it has no more references. It reduces the number of
* transactions for acquiring and releasing provider if the client accesses the provider
* frequently in a short time.
@@ -242,6 +251,11 @@
// Whether to invoke an activity callback after delivering new configuration.
private static final boolean REPORT_TO_ACTIVITY = true;
+ /** Use foreground GC policy (less pause time) and higher JIT weight. */
+ private static final int VM_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
+ /** Use background GC policy and default JIT threshold. */
+ private static final int VM_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
+
/**
* Denotes an invalid sequence number corresponding to a process state change.
*/
@@ -296,6 +310,11 @@
// Number of activities that are currently visible on-screen.
@UnsupportedAppUsage
int mNumVisibleActivities = 0;
+ private final AtomicInteger mNumLaunchingActivities = new AtomicInteger();
+ @GuardedBy("mAppThread")
+ private int mLastProcessState = PROCESS_STATE_UNKNOWN;
+ @GuardedBy("mAppThread")
+ private int mPendingProcessState = PROCESS_STATE_UNKNOWN;
ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
private int mLastSessionId;
@UnsupportedAppUsage
@@ -873,17 +892,6 @@
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
- private int mLastProcessState = -1;
-
- private void updatePendingConfiguration(Configuration config) {
- synchronized (mResourcesManager) {
- if (mPendingConfiguration == null ||
- mPendingConfiguration.isOtherSeqNewer(config)) {
- mPendingConfiguration = config;
- }
- }
- }
-
public final void scheduleSleeping(IBinder token, boolean sleeping) {
sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
}
@@ -1560,27 +1568,6 @@
updateProcessState(state, true);
}
- public void updateProcessState(int processState, boolean fromIpc) {
- synchronized (this) {
- if (mLastProcessState != processState) {
- mLastProcessState = processState;
- // Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants.
- final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
- final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
- int dalvikProcessState = DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE;
- // TODO: Tune this since things like gmail sync are important background but not jank perceptible.
- if (processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- dalvikProcessState = DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE;
- }
- VMRuntime.getRuntime().updateProcessState(dalvikProcessState);
- if (false) {
- Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
- + (fromIpc ? " (from ipc": ""));
- }
- }
- }
- }
-
/**
* Updates {@link #mNetworkBlockSeq}. This is used by ActivityManagerService to inform
* the main thread that it needs to wait for the network rules to get updated before
@@ -1661,16 +1648,6 @@
}
}
- @Override
- public void updatePendingConfiguration(Configuration config) {
- mAppThread.updatePendingConfiguration(config);
- }
-
- @Override
- public void updateProcessState(int processState, boolean fromIpc) {
- mAppThread.updateProcessState(processState, fromIpc);
- }
-
class H extends Handler {
public static final int BIND_APPLICATION = 110;
@UnsupportedAppUsage
@@ -1995,6 +1972,7 @@
if (stopProfiling) {
mProfiler.stopProfiling();
}
+ applyPendingProcessState();
return false;
}
}
@@ -2939,6 +2917,68 @@
return mActivities.get(token);
}
+ @Override
+ public void updatePendingConfiguration(Configuration config) {
+ synchronized (mResourcesManager) {
+ if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(config)) {
+ mPendingConfiguration = config;
+ }
+ }
+ }
+
+ @Override
+ public void updateProcessState(int processState, boolean fromIpc) {
+ synchronized (mAppThread) {
+ if (mLastProcessState == processState) {
+ return;
+ }
+ mLastProcessState = processState;
+ // Defer the top state for VM to avoid aggressive JIT compilation affecting activity
+ // launch time.
+ if (processState == ActivityManager.PROCESS_STATE_TOP
+ && mNumLaunchingActivities.get() > 0) {
+ mPendingProcessState = processState;
+ mH.postDelayed(this::applyPendingProcessState, PENDING_TOP_PROCESS_STATE_TIMEOUT);
+ } else {
+ mPendingProcessState = PROCESS_STATE_UNKNOWN;
+ updateVmProcessState(processState);
+ }
+ if (localLOGV) {
+ Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
+ + (fromIpc ? " (from ipc" : ""));
+ }
+ }
+ }
+
+ /** Update VM state based on ActivityManager.PROCESS_STATE_* constants. */
+ private void updateVmProcessState(int processState) {
+ // TODO: Tune this since things like gmail sync are important background but not jank
+ // perceptible.
+ final int state = processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+ ? VM_PROCESS_STATE_JANK_PERCEPTIBLE
+ : VM_PROCESS_STATE_JANK_IMPERCEPTIBLE;
+ VMRuntime.getRuntime().updateProcessState(state);
+ }
+
+ private void applyPendingProcessState() {
+ synchronized (mAppThread) {
+ if (mPendingProcessState == PROCESS_STATE_UNKNOWN) {
+ return;
+ }
+ final int pendingState = mPendingProcessState;
+ mPendingProcessState = PROCESS_STATE_UNKNOWN;
+ // Only apply the pending state if the last state doesn't change.
+ if (pendingState == mLastProcessState) {
+ updateVmProcessState(pendingState);
+ }
+ }
+ }
+
+ @Override
+ public void countLaunchingActivities(int num) {
+ mNumLaunchingActivities.getAndAdd(num);
+ }
+
@UnsupportedAppUsage
public final void sendActivityResult(
IBinder token, String id, int requestCode,
@@ -4509,7 +4549,7 @@
if (!show && !r.stopped) {
performStopActivityInner(r, null /* stopInfo */, show, false /* saveState */,
false /* finalStateRequest */, "handleWindowVisibility");
- } else if (show && r.stopped) {
+ } else if (show && r.getLifecycleState() == ON_STOP) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -4570,7 +4610,7 @@
private void onCoreSettingsChange() {
if (updateDebugViewAttributeState()) {
// request all activities to relaunch for the changes to take place
- relaunchAllActivities();
+ relaunchAllActivities(false /* preserveWindows */);
}
}
@@ -4587,10 +4627,13 @@
return previousState != View.sDebugViewAttributes;
}
- private void relaunchAllActivities() {
+ private void relaunchAllActivities(boolean preserveWindows) {
for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
- final Activity activity = entry.getValue().activity;
- if (!activity.mFinished) {
+ final ActivityClientRecord r = entry.getValue();
+ if (!r.activity.mFinished) {
+ if (preserveWindows && r.window != null) {
+ r.mPreserveWindow = true;
+ }
scheduleRelaunchActivity(entry.getKey());
}
}
@@ -5423,7 +5466,8 @@
}
}
- void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
+ @VisibleForTesting(visibility = PACKAGE)
+ public void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
// Updates triggered by package installation go through a package update
// receiver. Here we try to capture ApplicationInfo changes that are
// caused by other sources, such as overlays. That means we want to be as conservative
@@ -5469,7 +5513,8 @@
newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
handleConfigurationChanged(newConfig, null);
- relaunchAllActivities();
+ // Preserve windows to avoid black flickers when overlays change.
+ relaunchAllActivities(true /* preserveWindows */);
}
static void freeTextLayoutCachesIfNeeded(int configDiff) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 6f92244..227703d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -823,9 +823,11 @@
public static final int OP_LEGACY_STORAGE = 87;
/** @hide Accessing accessibility features */
public static final int OP_ACCESS_ACCESSIBILITY = 88;
+ /** @hide Read the device identifiers (IMEI / MEID, IMSI, SIM / Build serial) */
+ public static final int OP_READ_DEVICE_IDENTIFIERS = 89;
/** @hide */
@UnsupportedAppUsage
- public static final int _NUM_OP = 89;
+ public static final int _NUM_OP = 90;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1099,6 +1101,8 @@
/** @hide Interact with accessibility. */
@SystemApi
public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
+ /** @hide Read device identifiers */
+ public static final String OPSTR_READ_DEVICE_IDENTIFIERS = "android:read_device_identifiers";
// Warning: If an permission is added here it also has to be added to
// com.android.packageinstaller.permission.utils.EventLogger
@@ -1259,6 +1263,7 @@
OP_WRITE_MEDIA_IMAGES, // WRITE_MEDIA_IMAGES
OP_LEGACY_STORAGE, // LEGACY_STORAGE
OP_ACCESS_ACCESSIBILITY, // ACCESS_ACCESSIBILITY
+ OP_READ_DEVICE_IDENTIFIERS, // READ_DEVICE_IDENTIFIERS
};
/**
@@ -1354,6 +1359,7 @@
OPSTR_WRITE_MEDIA_IMAGES,
OPSTR_LEGACY_STORAGE,
OPSTR_ACCESS_ACCESSIBILITY,
+ OPSTR_READ_DEVICE_IDENTIFIERS,
};
/**
@@ -1450,6 +1456,7 @@
"WRITE_MEDIA_IMAGES",
"LEGACY_STORAGE",
"ACCESS_ACCESSIBILITY",
+ "READ_DEVICE_IDENTIFIERS",
};
/**
@@ -1547,6 +1554,7 @@
null, // no permission for OP_WRITE_MEDIA_IMAGES
null, // no permission for OP_LEGACY_STORAGE
null, // no permission for OP_ACCESS_ACCESSIBILITY
+ null, // no direct permission for OP_READ_DEVICE_IDENTIFIERS
};
/**
@@ -1644,6 +1652,7 @@
null, // WRITE_MEDIA_IMAGES
null, // LEGACY_STORAGE
null, // ACCESS_ACCESSIBILITY
+ null, // READ_DEVICE_IDENTIFIERS
};
/**
@@ -1740,6 +1749,7 @@
false, // WRITE_MEDIA_IMAGES
false, // LEGACY_STORAGE
false, // ACCESS_ACCESSIBILITY
+ false, // READ_DEVICE_IDENTIFIERS
};
/**
@@ -1835,6 +1845,7 @@
AppOpsManager.MODE_ERRORED, // WRITE_MEDIA_IMAGES
AppOpsManager.MODE_DEFAULT, // LEGACY_STORAGE
AppOpsManager.MODE_ALLOWED, // ACCESS_ACCESSIBILITY
+ AppOpsManager.MODE_ERRORED, // READ_DEVICE_IDENTIFIERS
};
/**
@@ -1934,6 +1945,7 @@
false, // WRITE_MEDIA_IMAGES
false, // LEGACY_STORAGE
false, // ACCESS_ACCESSIBILITY
+ false, // READ_DEVICE_IDENTIFIERS
};
/**
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 9dc8b45..d308adc 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -78,6 +78,8 @@
/** Set current process state. */
public abstract void updateProcessState(int processState, boolean fromIpc);
+ /** Count how many activities are launching. */
+ public abstract void countLaunchingActivities(int num);
// Execute phase related logic and handlers. Methods here execute actual lifecycle transactions
// and deliver callbacks.
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index 14c58e7..def1f45 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -27,5 +27,15 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "file_patterns": ["(/|^)ActivityThreadClientTest.java"],
+ "name": "FrameworksMockingCoreTests"
+ },
+ {
+ "file_patterns": ["(/|^)ActivityThreadTest.java"],
+ "name": "FrameworksCoreTests"
+ }
]
}
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index dd00e5a..de64db9 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -16,6 +16,8 @@
package android.app;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
@@ -58,23 +60,27 @@
* The base intent of the task (generally the intent that launched the task). This intent can
* be used to relaunch the task (if it is no longer running) or brought to the front if it is.
*/
+ @NonNull
public Intent baseIntent;
/**
* The component of the first activity in the task, can be considered the "application" of this
* task.
*/
+ @Nullable
public ComponentName baseActivity;
/**
* The component of the top activity in the task, currently showing to the user.
*/
+ @Nullable
public ComponentName topActivity;
/**
* The component of the target activity if this task was started from an activity alias.
* Otherwise, this is null.
*/
+ @Nullable
public ComponentName origActivity;
/**
@@ -82,6 +88,7 @@
* alias).
* @hide
*/
+ @Nullable
public ComponentName realActivity;
/**
@@ -106,6 +113,7 @@
* The recent activity values for the highest activity in the stack to have set the values.
* {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
*/
+ @Nullable
public ActivityManager.TaskDescription taskDescription;
/**
@@ -126,6 +134,7 @@
* The current configuration of the task.
* @hide
*/
+ @NonNull
@UnsupportedAppUsage
public final Configuration configuration = new Configuration();
diff --git a/core/java/android/app/Vr2dDisplayProperties.java b/core/java/android/app/Vr2dDisplayProperties.java
index bcb8592..fc200bf 100644
--- a/core/java/android/app/Vr2dDisplayProperties.java
+++ b/core/java/android/app/Vr2dDisplayProperties.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -136,7 +137,7 @@
/**
* Prints out dump info.
*/
- public void dump(PrintWriter pw, String prefix) {
+ public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
pw.println(prefix + toString());
}
@@ -188,7 +189,7 @@
/**
* Convenience class for creating Vr2dDisplayProperties.
*/
- public static class Builder {
+ public static final class Builder {
private int mAddedFlags = 0;
private int mRemovedFlags = 0;
@@ -203,6 +204,7 @@
/**
* Sets the dimensions to use for the virtual display.
*/
+ @NonNull
public Builder setDimensions(int width, int height, int dpi) {
mWidth = width;
mHeight = height;
@@ -213,6 +215,7 @@
/**
* Toggles the virtual display functionality for 2D activities in VR.
*/
+ @NonNull
public Builder setEnabled(boolean enabled) {
if (enabled) {
addFlags(FLAG_VIRTUAL_DISPLAY_ENABLED);
@@ -225,6 +228,7 @@
/**
* Adds property flags.
*/
+ @NonNull
public Builder addFlags(@Vr2dDisplayFlag int flags) {
mAddedFlags |= flags;
mRemovedFlags &= ~flags;
@@ -234,6 +238,7 @@
/**
* Removes property flags.
*/
+ @NonNull
public Builder removeFlags(@Vr2dDisplayFlag int flags) {
mRemovedFlags |= flags;
mAddedFlags &= ~flags;
@@ -243,6 +248,7 @@
/**
* Builds the Vr2dDisplayProperty instance.
*/
+ @NonNull
public Vr2dDisplayProperties build() {
return new Vr2dDisplayProperties(mWidth, mHeight, mDpi, mAddedFlags, mRemovedFlags);
}
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 5f1a94c..c74f8c3 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -2,6 +2,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -71,7 +72,7 @@
android.Manifest.permission.ACCESS_VR_STATE
})
public void registerVrStateCallback(@NonNull @CallbackExecutor Executor executor,
- VrStateCallback callback) {
+ @NonNull VrStateCallback callback) {
if (callback == null || mCallbackMap.containsKey(callback)) {
return;
}
@@ -99,7 +100,7 @@
android.Manifest.permission.RESTRICTED_VR_ACCESS,
android.Manifest.permission.ACCESS_VR_STATE
})
- public void unregisterVrStateCallback(VrStateCallback callback) {
+ public void unregisterVrStateCallback(@NonNull VrStateCallback callback) {
CallbackEntry entry = mCallbackMap.remove(callback);
if (entry != null) {
try {
@@ -175,7 +176,7 @@
*/
@RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
public void setVr2dDisplayProperties(
- Vr2dDisplayProperties vr2dDisplayProp) {
+ @NonNull Vr2dDisplayProperties vr2dDisplayProp) {
try {
mService.setVr2dDisplayProperties(vr2dDisplayProp);
} catch (RemoteException e) {
@@ -220,7 +221,7 @@
* @param componentName not used
*/
@RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
- public void setVrInputMethod(ComponentName componentName) {
+ public void setVrInputMethod(@Nullable ComponentName componentName) {
}
/**
diff --git a/core/java/android/app/prediction/AppPredictor.java b/core/java/android/app/prediction/AppPredictor.java
index 3f2f209..cd635d6 100644
--- a/core/java/android/app/prediction/AppPredictor.java
+++ b/core/java/android/app/prediction/AppPredictor.java
@@ -271,7 +271,9 @@
if (mCloseGuard != null) {
mCloseGuard.warnIfOpen();
}
- destroy();
+ if (!mIsClosed.get()) {
+ destroy();
+ }
} finally {
super.finalize();
}
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index ed45b2f..61e4569 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -204,24 +204,49 @@
private int mRank;
/**
- * @param id A unique id for this launchable target.
+ * @deprecated Use the other Builder constructors.
* @hide
*/
+ @Deprecated
@SystemApi
- @TestApi
public Builder(@NonNull AppTargetId id) {
mId = id;
}
/**
- * Sets the target to be an app.
- *
- * @param packageName PackageName of the app
+ * @param id A unique id for this launchable target.
+ * @param packageName PackageName of the target.
* @param user The UserHandle of the user which this target belongs to.
- *
- * @throws IllegalArgumentException is the target is already set
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public Builder(@NonNull AppTargetId id, @NonNull String packageName,
+ @NonNull UserHandle user) {
+ mId = Preconditions.checkNotNull(id);
+ mPackageName = Preconditions.checkNotNull(packageName);
+ mUser = Preconditions.checkNotNull(user);
+ }
+
+ /**
+ * @param id A unique id for this launchable target.
+ * @param info The ShortcutInfo that represents this launchable target.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public Builder(@NonNull AppTargetId id, @NonNull ShortcutInfo info) {
+ mId = Preconditions.checkNotNull(id);
+ mShortcutInfo = Preconditions.checkNotNull(info);
+ mPackageName = info.getPackage();
+ mUser = info.getUserHandle();
+ }
+
+ /**
+ * @deprecated Use the appropriate constructor.
*/
@NonNull
+ @Deprecated
public Builder setTarget(@NonNull String packageName, @NonNull UserHandle user) {
if (mPackageName != null) {
throw new IllegalArgumentException("Target is already set");
@@ -232,11 +257,10 @@
}
/**
- * Sets the target to be a ShortcutInfo.
- *
- * @throws IllegalArgumentException is the target is already set
+ * @deprecated Use the appropriate constructor.
*/
@NonNull
+ @Deprecated
public Builder setTarget(@NonNull ShortcutInfo info) {
setTarget(info.getPackage(), info.getUserHandle());
mShortcutInfo = Preconditions.checkNotNull(info);
@@ -244,7 +268,7 @@
}
/**
- * Sets the className for the target
+ * Sets the className for the target.
*/
@NonNull
public Builder setClassName(@NonNull String className) {
@@ -253,7 +277,7 @@
}
/**
- * Sets the rank of the for the target.
+ * Sets the rank of the target.
*/
@NonNull
public Builder setRank(@IntRange(from = 0) int rank) {
@@ -274,7 +298,7 @@
@NonNull
public AppTarget build() {
if (mPackageName == null) {
- throw new IllegalStateException("No target set");
+ throw new IllegalStateException("No target is set");
}
return new AppTarget(mId, mPackageName, mUser, mShortcutInfo, mClassName, mRank);
}
diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java
index 027e152..394a0d6 100644
--- a/core/java/android/app/role/RoleControllerManager.java
+++ b/core/java/android/app/role/RoleControllerManager.java
@@ -52,7 +52,10 @@
private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();
+ private static volatile ComponentName sRemoteServiceComponentName;
+
private static final Object sRemoteServicesLock = new Object();
+
/**
* Global remote services (per user) used by all {@link RoleControllerManager managers}.
*/
@@ -62,18 +65,36 @@
@NonNull
private final RemoteService mRemoteService;
- public RoleControllerManager(@NonNull Context context, @NonNull Handler handler) {
+ /**
+ * Initialize the remote service component name once so that we can avoid acquiring the
+ * PackageManagerService lock in constructor.
+ *
+ * @see #createWithInitializedRemoteServiceComponentName(Handler, Context)
+ */
+ public static void initializeRemoteServiceComponentName(@NonNull Context context) {
+ sRemoteServiceComponentName = getRemoteServiceComponentName(context);
+ }
+
+ /**
+ * Create a {@link RoleControllerManager} instance with the initialized remote service component
+ * name so that we can avoid acquiring the PackageManagerService lock in constructor.
+ *
+ * @see #initializeRemoteServiceComponentName(Context)
+ */
+ @NonNull
+ public static RoleControllerManager createWithInitializedRemoteServiceComponentName(
+ @NonNull Handler handler, @NonNull Context context) {
+ return new RoleControllerManager(sRemoteServiceComponentName, handler, context);
+ }
+
+ private RoleControllerManager(@NonNull ComponentName remoteServiceComponentName,
+ @NonNull Handler handler, @NonNull Context context) {
synchronized (sRemoteServicesLock) {
int userId = context.getUserId();
RemoteService remoteService = sRemoteServices.get(userId);
if (remoteService == null) {
- Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
- PackageManager packageManager = context.getPackageManager();
- intent.setPackage(packageManager.getPermissionControllerPackageName());
- ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
-
remoteService = new RemoteService(context.getApplicationContext(),
- resolveInfo.getComponentInfo().getComponentName(), handler, userId);
+ remoteServiceComponentName, handler, userId);
sRemoteServices.put(userId, remoteService);
}
mRemoteService = remoteService;
@@ -81,7 +102,16 @@
}
public RoleControllerManager(@NonNull Context context) {
- this(context, context.getMainThreadHandler());
+ this(getRemoteServiceComponentName(context), context.getMainThreadHandler(), context);
+ }
+
+ @NonNull
+ private static ComponentName getRemoteServiceComponentName(@NonNull Context context) {
+ Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
+ PackageManager packageManager = context.getPackageManager();
+ intent.setPackage(packageManager.getPermissionControllerPackageName());
+ ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
+ return resolveInfo.getComponentInfo().getComponentName();
}
/**
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index db22f8d..cdf5d49 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -66,6 +66,7 @@
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
+ client.countLaunchingActivities(1);
client.updateProcessState(mProcState, false);
client.updatePendingConfiguration(mCurConfig);
}
@@ -82,6 +83,12 @@
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
+ @Override
+ public void postExecute(ClientTransactionHandler client, IBinder token,
+ PendingTransactionActions pendingActions) {
+ client.countLaunchingActivities(-1);
+ }
+
// ObjectPoolItem implementation
diff --git a/core/java/android/attention/AttentionManagerInternal.java b/core/java/android/attention/AttentionManagerInternal.java
index fa3d3b8d..941e9e2e 100644
--- a/core/java/android/attention/AttentionManagerInternal.java
+++ b/core/java/android/attention/AttentionManagerInternal.java
@@ -46,13 +46,6 @@
*/
public abstract void cancelAttentionCheck(AttentionCallbackInternal callback);
- /**
- * Disables the dependants.
- *
- * Example: called if the service does not have sufficient permissions to perform the task.
- */
- public abstract void disableSelf();
-
/** Internal interface for attention callback. */
public abstract static class AttentionCallbackInternal {
/**
diff --git a/core/java/android/content/AutofillOptions.java b/core/java/android/content/AutofillOptions.java
index f59bc98..8fb9501 100644
--- a/core/java/android/content/AutofillOptions.java
+++ b/core/java/android/content/AutofillOptions.java
@@ -24,7 +24,7 @@
import android.util.ArraySet;
import android.util.Log;
import android.view.autofill.AutofillManager;
-import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
+import android.view.autofill.AutofillManager.AutofillClient;
import java.io.PrintWriter;
@@ -73,10 +73,10 @@
public boolean isAugmentedAutofillEnabled(@NonNull Context context) {
if (!augmentedAutofillEnabled) return false;
- final ContentCaptureClient contentCaptureClient = context.getContentCaptureClient();
- if (contentCaptureClient == null) return false;
+ final AutofillClient autofillClient = context.getAutofillClient();
+ if (autofillClient == null) return false;
- final ComponentName component = contentCaptureClient.contentCaptureClientGetComponentName();
+ final ComponentName component = autofillClient.autofillClientGetComponentName();
return whitelistedActivitiesForAugmentedAutofill == null
|| whitelistedActivitiesForAugmentedAutofill.contains(component);
}
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index a41b5d3..c201e4d 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -17,7 +17,6 @@
package android.content;
import android.annotation.UnsupportedAppUsage;
-import android.content.ContentProvider;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
@@ -59,6 +58,7 @@
private final ContentValues mValuesBackReferences;
private final Map<Integer, Integer> mSelectionArgsBackReferences;
private final boolean mYieldAllowed;
+ private final boolean mFailureAllowed;
private final static String TAG = "ContentProviderOperation";
@@ -76,6 +76,7 @@
mSelectionArgsBackReferences = builder.mSelectionArgsBackReferences;
mValuesBackReferences = builder.mValuesBackReferences;
mYieldAllowed = builder.mYieldAllowed;
+ mFailureAllowed = builder.mFailureAllowed;
}
private ContentProviderOperation(Parcel source) {
@@ -98,6 +99,7 @@
}
}
mYieldAllowed = source.readInt() != 0;
+ mFailureAllowed = source.readInt() != 0;
}
/** @hide */
@@ -111,6 +113,7 @@
mSelectionArgsBackReferences = cpo.mSelectionArgsBackReferences;
mValuesBackReferences = cpo.mValuesBackReferences;
mYieldAllowed = cpo.mYieldAllowed;
+ mFailureAllowed = cpo.mFailureAllowed;
}
public void writeToParcel(Parcel dest, int flags) {
@@ -157,6 +160,7 @@
dest.writeInt(0);
}
dest.writeInt(mYieldAllowed ? 1 : 0);
+ dest.writeInt(mFailureAllowed ? 1 : 0);
}
/**
@@ -212,6 +216,11 @@
return mYieldAllowed;
}
+ /** {@hide} */
+ public boolean isFailureAllowed() {
+ return mFailureAllowed;
+ }
+
/** @hide exposed for unit tests */
@UnsupportedAppUsage
public int getType() {
@@ -290,19 +299,35 @@
*/
public ContentProviderResult apply(ContentProvider provider, ContentProviderResult[] backRefs,
int numBackRefs) throws OperationApplicationException {
+ if (mFailureAllowed) {
+ try {
+ return applyInternal(provider, backRefs, numBackRefs);
+ } catch (Exception e) {
+ return new ContentProviderResult(e.getMessage());
+ }
+ } else {
+ return applyInternal(provider, backRefs, numBackRefs);
+ }
+ }
+
+ private ContentProviderResult applyInternal(ContentProvider provider,
+ ContentProviderResult[] backRefs, int numBackRefs)
+ throws OperationApplicationException {
ContentValues values = resolveValueBackReferences(backRefs, numBackRefs);
String[] selectionArgs =
resolveSelectionArgsBackReferences(backRefs, numBackRefs);
if (mType == TYPE_INSERT) {
- Uri newUri = provider.insert(mUri, values);
- if (newUri == null) {
- throw new OperationApplicationException("insert failed");
+ final Uri newUri = provider.insert(mUri, values);
+ if (newUri != null) {
+ return new ContentProviderResult(newUri);
+ } else {
+ throw new OperationApplicationException(
+ "Insert into " + mUri + " returned no result");
}
- return new ContentProviderResult(newUri);
}
- int numRows;
+ final int numRows;
if (mType == TYPE_DELETE) {
numRows = provider.delete(mUri, mSelection, selectionArgs);
} else if (mType == TYPE_UPDATE) {
@@ -328,7 +353,6 @@
final String expectedValue = values.getAsString(projection[i]);
if (!TextUtils.equals(cursorValue, expectedValue)) {
// Throw exception when expected values don't match
- Log.e(TAG, this.toString());
throw new OperationApplicationException("Found value " + cursorValue
+ " when expected " + expectedValue + " for column "
+ projection[i]);
@@ -340,13 +364,12 @@
cursor.close();
}
} else {
- Log.e(TAG, this.toString());
throw new IllegalStateException("bad type, " + mType);
}
if (mExpectedCount != null && mExpectedCount != numRows) {
- Log.e(TAG, this.toString());
- throw new OperationApplicationException("wrong number of rows: " + numRows);
+ throw new OperationApplicationException(
+ "Expected " + mExpectedCount + " rows but actual " + numRows);
}
return new ContentProviderResult(numRows);
@@ -491,6 +514,7 @@
private ContentValues mValuesBackReferences;
private Map<Integer, Integer> mSelectionArgsBackReferences;
private boolean mYieldAllowed;
+ private boolean mFailureAllowed;
/** Create a {@link Builder} of a given type. The uri must not be null. */
private Builder(int type, Uri uri) {
@@ -683,5 +707,11 @@
mYieldAllowed = yieldAllowed;
return this;
}
+
+ /** {@hide} */
+ public Builder withFailureAllowed(boolean failureAllowed) {
+ mFailureAllowed = failureAllowed;
+ return this;
+ }
}
}
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index d90173c..b301011 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -16,10 +16,11 @@
package android.content;
-import android.content.ContentProvider;
import android.net.Uri;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
/**
* Contains the result of the application of a {@link ContentProviderOperation}. It is guaranteed
@@ -28,26 +29,44 @@
public class ContentProviderResult implements Parcelable {
public final Uri uri;
public final Integer count;
+ /** {@hide} */
+ public final String failure;
public ContentProviderResult(Uri uri) {
- if (uri == null) throw new IllegalArgumentException("uri must not be null");
- this.uri = uri;
- this.count = null;
+ this(Preconditions.checkNotNull(uri), null, null);
}
public ContentProviderResult(int count) {
+ this(null, count, null);
+ }
+
+ /** {@hide} */
+ public ContentProviderResult(String failure) {
+ this(null, null, failure);
+ }
+
+ /** {@hide} */
+ public ContentProviderResult(Uri uri, Integer count, String failure) {
+ this.uri = uri;
this.count = count;
- this.uri = null;
+ this.failure = failure;
}
public ContentProviderResult(Parcel source) {
- int type = source.readInt();
- if (type == 1) {
- count = source.readInt();
+ if (source.readInt() != 0) {
+ uri = Uri.CREATOR.createFromParcel(source);
+ } else {
uri = null;
+ }
+ if (source.readInt() != 0) {
+ count = source.readInt();
} else {
count = null;
- uri = Uri.CREATOR.createFromParcel(source);
+ }
+ if (source.readInt() != 0) {
+ failure = source.readString();
+ } else {
+ failure = null;
}
}
@@ -55,37 +74,63 @@
public ContentProviderResult(ContentProviderResult cpr, int userId) {
uri = ContentProvider.maybeAddUserId(cpr.uri, userId);
count = cpr.count;
+ failure = cpr.failure;
}
+ @Override
public void writeToParcel(Parcel dest, int flags) {
- if (uri == null) {
+ if (uri != null) {
+ dest.writeInt(1);
+ uri.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+ if (count != null) {
dest.writeInt(1);
dest.writeInt(count);
} else {
- dest.writeInt(2);
- uri.writeToParcel(dest, 0);
+ dest.writeInt(0);
+ }
+ if (failure != null) {
+ dest.writeInt(1);
+ dest.writeString(failure);
+ } else {
+ dest.writeInt(0);
}
}
+ @Override
public int describeContents() {
return 0;
}
public static final @android.annotation.NonNull Creator<ContentProviderResult> CREATOR =
new Creator<ContentProviderResult>() {
+ @Override
public ContentProviderResult createFromParcel(Parcel source) {
return new ContentProviderResult(source);
}
+ @Override
public ContentProviderResult[] newArray(int size) {
return new ContentProviderResult[size];
}
};
+ @Override
public String toString() {
+ final StringBuilder sb = new StringBuilder("ContentProviderResult(");
if (uri != null) {
- return "ContentProviderResult(uri=" + uri.toString() + ")";
+ sb.append("uri=" + uri + " ");
}
- return "ContentProviderResult(count=" + count + ")";
+ if (count != null) {
+ sb.append("count=" + count + " ");
+ }
+ if (uri != null) {
+ sb.append("failure=" + failure + " ");
+ }
+ sb.deleteCharAt(sb.length() - 1);
+ sb.append(")");
+ return sb.toString();
}
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5a844aa..0ba457e 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -70,7 +70,6 @@
import android.view.ViewDebug;
import android.view.WindowManager;
import android.view.autofill.AutofillManager.AutofillClient;
-import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.view.textclassifier.TextClassificationManager;
import java.io.File;
@@ -5414,14 +5413,6 @@
/**
* @hide
*/
- @Nullable
- public ContentCaptureClient getContentCaptureClient() {
- return null;
- }
-
- /**
- * @hide
- */
public final boolean isAutofillCompatibilityEnabled() {
final AutofillOptions options = getAutofillOptions();
return options != null && options.compatModeEnabled;
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
index 0604f6a6..4b02085 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
@@ -374,4 +374,15 @@
public boolean isUidAllowedOnDisplay(int displayId, int uid) {
return mImpl.isUidAllowedOnDisplay(displayId, uid);
}
+
+ /**
+ * Can be called by MSIME to activate/deactivate a client when it is gaining/losing focus
+ * respectively.
+ *
+ * @param clientId client ID to activate/deactivate.
+ * @param active {@code true} to activate a client.
+ */
+ public void setActive(int clientId, boolean active) {
+ mImpl.setActive(clientId, active);
+ }
}
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
index bbe3a7f..04db8d6 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
@@ -190,4 +190,8 @@
boolean isUidAllowedOnDisplay(int displayId, int uid) {
return mPrivOps.isUidAllowedOnDisplay(displayId, uid);
}
+
+ void setActive(int clientId, boolean active) {
+ mPrivOps.setActive(clientId, active);
+ }
}
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index b6c4fe2..68826cb 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -197,7 +197,7 @@
final FileDescriptor queryfd;
try {
queryfd = resNetworkSend((network != null
- ? network.netId : NETID_UNSET), query, query.length, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), query, query.length, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -238,7 +238,7 @@
final FileDescriptor queryfd;
try {
queryfd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, nsClass, nsType, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), domain, nsClass, nsType, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -346,7 +346,8 @@
if (queryIpv6) {
try {
v6fd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_AAAA, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET),
+ domain, CLASS_IN, TYPE_AAAA, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -365,7 +366,8 @@
if (queryIpv4) {
try {
v4fd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_A, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET),
+ domain, CLASS_IN, TYPE_A, flags);
} catch (ErrnoException e) {
if (queryIpv6) resNetworkCancel(v6fd); // Closes fd, marks it invalid.
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
@@ -423,7 +425,7 @@
final FileDescriptor queryfd;
try {
queryfd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, nsType, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), domain, CLASS_IN, nsType, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index b8d7cf1..a55d9d0 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -20,6 +20,8 @@
import android.os.SystemClock;
import android.util.Log;
+import com.android.internal.util.TrafficStatsConstants;
+
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
@@ -99,7 +101,8 @@
public boolean requestTime(InetAddress address, int port, int timeout, Network network) {
DatagramSocket socket = null;
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP);
+ final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_NTP);
try {
socket = new DatagramSocket();
network.bindSocket(socket);
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 49c6f74..4332d8a 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -90,6 +90,42 @@
public static final int UID_TETHERING = -5;
/**
+ * Tag values in this range are reserved for the network stack. The network stack is
+ * running as UID {@link android.os.Process.NETWORK_STACK_UID} when in the mainline
+ * module separate process, and as the system UID otherwise.
+ */
+ /** @hide */
+ @SystemApi
+ public static final int TAG_NETWORK_STACK_RANGE_START = 0xFFFFFD00;
+ /** @hide */
+ @SystemApi
+ public static final int TAG_NETWORK_STACK_RANGE_END = 0xFFFFFEFF;
+
+ /**
+ * Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used internally by system services
+ * like DownloadManager when performing traffic on behalf of an application.
+ */
+ // Please note there is no enforcement of these constants, so do not rely on them to
+ // determine that the caller is a system caller.
+ /** @hide */
+ @SystemApi
+ public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = 0xFFFFFF00;
+ /** @hide */
+ @SystemApi
+ public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = 0xFFFFFF0F;
+
+ /**
+ * Tag values between these ranges are reserved for the network stack to do traffic
+ * on behalf of applications. It is a subrange of the range above.
+ */
+ /** @hide */
+ @SystemApi
+ public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = 0xFFFFFF80;
+ /** @hide */
+ @SystemApi
+ public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = 0xFFFFFF8F;
+
+ /**
* Default tag value for {@link DownloadManager} traffic.
*
* @hide
@@ -127,26 +163,9 @@
*/
public static final int TAG_SYSTEM_APP = 0xFFFFFF05;
+ // TODO : remove this constant when Wifi code is updated
/** @hide */
- @SystemApi
- @TestApi
- public static final int TAG_SYSTEM_DHCP = 0xFFFFFF40;
- /** @hide */
- public static final int TAG_SYSTEM_NTP = 0xFFFFFF41;
- /** @hide */
- @SystemApi
- @TestApi
public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42;
- /** @hide */
- public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF43;
- /** @hide */
- public static final int TAG_SYSTEM_GPS = 0xFFFFFF44;
- /** @hide */
- public static final int TAG_SYSTEM_PAC = 0xFFFFFF45;
- /** @hide */
- @SystemApi
- @TestApi
- public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFF46;
private static INetworkStatsService sStatsService;
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 166de3f..6c498c7 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -493,6 +493,7 @@
* @param onPropertyChangedListener The listener to add.
* @hide
* @see #removeOnPropertyChangedListener(OnPropertyChangedListener)
+ * @removed
*/
@SystemApi
@TestApi
@@ -569,6 +570,7 @@
* @param onPropertyChangedListener The listener to remove.
* @hide
* @see #addOnPropertyChangedListener(String, Executor, OnPropertyChangedListener)
+ * @removed
*/
@SystemApi
@TestApi
@@ -737,6 +739,7 @@
* Override {@link #onPropertyChanged(String, String, String)} to handle callbacks for changes.
*
* @hide
+ * @removed
*/
@SystemApi
@TestApi
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0491c73..488f417 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -955,18 +955,16 @@
"android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
/**
- * Activity Action: Open the advanced power usage details page of an associated app.
+ * Activity Action: Open the battery details page of an associated app.
* <p>
* Input: Intent's data URI set with an application name, using the
* "package" schema (like "package:com.my.app")
* <p>
* Output: Nothing.
- *
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL =
- "android.settings.VIEW_ADVANCED_POWER_USAGE_DETAIL";
+ public static final String ACTION_APP_BATTERY_SETTINGS =
+ "android.settings.APP_BATTERY_SETTINGS";
/**
* Activity Action: Show screen for controlling background data
@@ -1533,6 +1531,9 @@
/**
* Activity Action: Show More default apps settings.
* <p>
+ * If a Settings activity handles this intent action, a "More defaults" entry will be shown in
+ * the Default apps settings, and clicking it will launch that activity.
+ * <p>
* In some cases, a matching Activity may not exist, so ensure you safeguard against this.
* <p>
* Input: Nothing.
@@ -5801,6 +5802,14 @@
"autofill_field_classification";
/**
+ * Boolean indicating if the dark mode dialog shown on first toggle has been seen.
+ *
+ * @hide
+ */
+ public static final String DARK_MODE_DIALOG_SEEN =
+ "dark_mode_dialog_seen";
+
+ /**
* Defines value returned by {@link android.service.autofill.UserData#getMaxUserDataSize()}.
*
* @hide
@@ -8139,7 +8148,14 @@
public static final String FACE_UNLOCK_ATTENTION_REQUIRED =
"face_unlock_attention_required";
- private static final Validator FACE_UNLOCK_ATTENTION_REQUIRED_VALIDATOR = BOOLEAN_VALIDATOR;
+ /**
+ * Whether or not face unlock requires a diverse set of poses during enrollment. This is a
+ * cached value, the source of truth is obtained through the HAL.
+ * @hide
+ */
+ public static final String FACE_UNLOCK_DIVERSITY_REQUIRED =
+ "face_unlock_diversity_required";
+
/**
* Whether or not face unlock is allowed for apps (through BiometricPrompt).
@@ -8797,7 +8813,6 @@
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
FACE_UNLOCK_KEYGUARD_ENABLED,
FACE_UNLOCK_DISMISSES_KEYGUARD,
- FACE_UNLOCK_ATTENTION_REQUIRED,
FACE_UNLOCK_APP_ENABLED,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
ASSIST_GESTURE_ENABLED,
@@ -8842,6 +8857,7 @@
SILENCE_NOTIFICATION_GESTURE_COUNT,
SILENCE_CALL_GESTURE_COUNT,
SILENCE_TIMER_GESTURE_COUNT,
+ DARK_MODE_DIALOG_SEEN
};
/**
@@ -8964,8 +8980,6 @@
VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
- VALIDATORS.put(FACE_UNLOCK_ATTENTION_REQUIRED,
- FACE_UNLOCK_ATTENTION_REQUIRED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
@@ -9024,6 +9038,7 @@
VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR);
+ VALIDATORS.put(DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR);
}
/**
diff --git a/core/java/android/service/attention/AttentionService.java b/core/java/android/service/attention/AttentionService.java
index 6172ce5..49ab5db 100644
--- a/core/java/android/service/attention/AttentionService.java
+++ b/core/java/android/service/attention/AttentionService.java
@@ -21,13 +21,11 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
-import android.attention.AttentionManagerInternal;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.android.internal.util.Preconditions;
-import com.android.server.LocalServices;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -132,19 +130,6 @@
}
/**
- * Disables the dependants.
- *
- * Example: called if the service does not have sufficient permissions to perform the task.
- */
- public final void disableSelf() {
- AttentionManagerInternal attentionManager = LocalServices.getService(
- AttentionManagerInternal.class);
- if (attentionManager != null) {
- attentionManager.disableSelf();
- }
- }
-
- /**
* Checks the user attention and calls into the provided callback.
*
* @param callback the callback to return the result to
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 5be73b9..02ce873 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -46,9 +46,9 @@
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureSession;
import android.view.contentcapture.ContentCaptureSessionId;
+import android.view.contentcapture.DataRemovalRequest;
import android.view.contentcapture.IContentCaptureDirectManager;
import android.view.contentcapture.MainContentCaptureSession;
-import android.view.contentcapture.UserDataRemovalRequest;
import com.android.internal.os.IResultReceiver;
@@ -86,11 +86,28 @@
* <code><{@link
* android.R.styleable#ContentCaptureService content-capture-service}></code> tag.
*
- * <p>This is a a sample XML file configuring a ContentCaptureService:
- * <pre> <content-capture-service
- * android:settingsActivity="foo.bar.SettingsActivity"
- * . . .
- * /></pre>
+ * <p>Here's an example of how to use it on {@code AndroidManifest.xml}:
+ *
+ * <pre>
+ * <service android:name=".MyContentCaptureService"
+ * android:permission="android.permission.BIND_CONTENT_CAPTURE_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.service.contentcapture.ContentCaptureService" />
+ * </intent-filter>
+ *
+ * <meta-data
+ * android:name="android.content_capture"
+ * android:resource="@xml/my_content_capture_service"/>
+ * </service>
+ * </pre>
+ *
+ * <p>And then on {@code res/xml/my_content_capture_service.xml}:
+ *
+ * <pre>
+ * <content-capture-service xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:settingsActivity="my.package.MySettingsActivity">
+ * </content-capture-service>
+ * </pre>
*/
public static final String SERVICE_META_DATA = "android.content_capture";
@@ -138,7 +155,7 @@
}
@Override
- public void onUserDataRemovalRequest(UserDataRemovalRequest request) {
+ public void onDataRemovalRequest(DataRemovalRequest request) {
mHandler.sendMessage(
obtainMessage(ContentCaptureService::handleOnUserDataRemovalRequest,
ContentCaptureService.this, request));
@@ -288,12 +305,12 @@
}
/**
- * Notifies the service that the app requested to remove data associated with the user.
+ * Notifies the service that the app requested to remove content capture data.
*
- * @param request the user data requested to be removed
+ * @param request the content capture data requested to be removed
*/
- public void onUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
- if (sVerbose) Log.v(TAG, "onUserDataRemovalRequest()");
+ public void onDataRemovalRequest(@NonNull DataRemovalRequest request) {
+ if (sVerbose) Log.v(TAG, "onDataRemovalRequest()");
}
/**
@@ -449,8 +466,8 @@
onDestroyContentCaptureSession(new ContentCaptureSessionId(sessionId));
}
- private void handleOnUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
- onUserDataRemovalRequest(request);
+ private void handleOnUserDataRemovalRequest(@NonNull DataRemovalRequest request) {
+ onDataRemovalRequest(request);
}
private void handleOnActivityEvent(@NonNull ActivityEvent event) {
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
index 03e1b78..a7578af9 100644
--- a/core/java/android/service/contentcapture/IContentCaptureService.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -21,7 +21,7 @@
import android.service.contentcapture.ActivityEvent;
import android.service.contentcapture.SnapshotData;
import android.view.contentcapture.ContentCaptureContext;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
import com.android.internal.os.IResultReceiver;
@@ -39,6 +39,6 @@
in IResultReceiver clientReceiver, int initialState);
void onSessionFinished(int sessionId);
void onActivitySnapshot(int sessionId, in SnapshotData snapshotData);
- void onUserDataRemovalRequest(in UserDataRemovalRequest request);
+ void onDataRemovalRequest(in DataRemovalRequest request);
void onActivityEvent(in ActivityEvent event);
}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index e3e63e5..0de17ca 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -17,7 +17,6 @@
package android.service.voice;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.UnsupportedAppUsage;
import android.app.Service;
@@ -41,6 +40,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
@@ -211,11 +211,11 @@
*
* @param voiceActions A set of checked voice actions.
* @return Returns a subset of checked voice actions. Additional voice actions in the
- * returned set will be ignored. Returns null or empty set if no actions are supported.
+ * returned set will be ignored. Returns empty set if no actions are supported.
*/
- @Nullable
+ @NonNull
public Set<String> onGetSupportedVoiceActions(@NonNull Set<String> voiceActions) {
- return null;
+ return Collections.emptySet();
}
@Override
@@ -272,7 +272,7 @@
try {
Set<String> voiceActionsSet = new ArraySet<>(voiceActions);
Set<String> resultSet = onGetSupportedVoiceActions(voiceActionsSet);
- callback.onComplete(resultSet == null ? null : new ArrayList<>(resultSet));
+ callback.onComplete(new ArrayList<>(resultSet));
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 6f27447..5b5f3b8 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -123,7 +123,7 @@
/**
* Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked
- * from an Android automotive system Ui.
+ * from an Android automotive system UI.
*/
public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 1 << 7;
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index f2747cf..1bcfc05 100755
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -34,11 +34,32 @@
public static final int DENSITY_LOW = 120;
/**
+ * Intermediate density for screens that sit between {@link #DENSITY_LOW} (120dpi) and
+ * {@link #DENSITY_MEDIUM} (160dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_MEDIUM} assets for them.
+ */
+ public static final int DENSITY_140 = 140;
+
+ /**
* Standard quantized DPI for medium-density screens.
*/
public static final int DENSITY_MEDIUM = 160;
/**
+ * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+ * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+ */
+ public static final int DENSITY_180 = 180;
+
+ /**
+ * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+ * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+ */
+ public static final int DENSITY_200 = 200;
+
+ /**
* This is a secondary density, added for some common screen configurations.
* It is recommended that applications not generally target this as a first
* class density -- that is, don't supply specific graphics for this
@@ -58,6 +79,13 @@
public static final int DENSITY_TV = 213;
/**
+ * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+ * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+ */
+ public static final int DENSITY_220 = 220;
+
+ /**
* Standard quantized DPI for high-density screens.
*/
public static final int DENSITY_HIGH = 240;
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index feff9db..f2aaead 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -63,7 +63,6 @@
DEFAULT_FLAGS.put(FORCE_GLOBAL_ACTIONS_GRID_ENABLED, "false");
DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
DEFAULT_FLAGS.put(PIXEL_WALLPAPER_CATEGORY_SWITCH, "false");
- DEFAULT_FLAGS.put("settings_wifi_details_saved_screen", "true");
DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
}
diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java
index 8eccc04..6fcdd71 100644
--- a/core/java/android/view/GestureExclusionTracker.java
+++ b/core/java/android/view/GestureExclusionTracker.java
@@ -20,6 +20,8 @@
import android.annotation.Nullable;
import android.graphics.Rect;
+import com.android.internal.util.Preconditions;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
@@ -31,6 +33,8 @@
*/
class GestureExclusionTracker {
private boolean mGestureExclusionViewsChanged = false;
+ private boolean mRootGestureExclusionRectsChanged = false;
+ private List<Rect> mRootGestureExclusionRects = Collections.emptyList();
private List<GestureExclusionViewInfo> mGestureExclusionViewInfos = new ArrayList<>();
private List<Rect> mGestureExclusionRects = Collections.emptyList();
@@ -59,9 +63,9 @@
@Nullable
public List<Rect> computeChangedRects() {
- boolean changed = false;
+ boolean changed = mRootGestureExclusionRectsChanged;
final Iterator<GestureExclusionViewInfo> i = mGestureExclusionViewInfos.iterator();
- final List<Rect> rects = new ArrayList<>();
+ final List<Rect> rects = new ArrayList<>(mRootGestureExclusionRects);
while (i.hasNext()) {
final GestureExclusionViewInfo info = i.next();
switch (info.update()) {
@@ -79,6 +83,7 @@
}
if (changed || mGestureExclusionViewsChanged) {
mGestureExclusionViewsChanged = false;
+ mRootGestureExclusionRectsChanged = false;
if (!mGestureExclusionRects.equals(rects)) {
mGestureExclusionRects = rects;
return rects;
@@ -87,6 +92,17 @@
return null;
}
+ public void setRootSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ Preconditions.checkNotNull(rects, "rects must not be null");
+ mRootGestureExclusionRects = rects;
+ mRootGestureExclusionRectsChanged = true;
+ }
+
+ @NonNull
+ public List<Rect> getRootSystemGestureExclusionRects() {
+ return mRootGestureExclusionRects;
+ }
+
private static class GestureExclusionViewInfo {
public static final int CHANGED = 0;
public static final int UNCHANGED = 1;
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 2ba1e01..d415387 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -85,6 +85,7 @@
@Override
public void onWindowFocusLost() {
mHasWindowFocus = false;
+ getImm().unregisterImeConsumer(this);
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 51bcbbd..096c988 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1377,59 +1377,6 @@
*/
public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
- /** @hide */
- @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
- IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
- IMPORTANT_FOR_CONTENT_CAPTURE_YES,
- IMPORTANT_FOR_CONTENT_CAPTURE_NO,
- IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
- IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ContentCaptureImportance {}
-
- /**
- * Automatically determine whether a view is important for content capture.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
-
- /**
- * The view is important for content capture, and its children (if any) will be traversed.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
-
- /**
- * The view is not important for content capture, but its children (if any) will be traversed.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
-
- /**
- * The view is important for content capture, but its children (if any) will not be traversed.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
-
- /**
- * The view is not important for content capture, and its children (if any) will not be
- * traversed.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
-
-
/**
* This view is enabled. Interpretation varies by subclass.
* Use with ENABLED_MASK when calling setFlags.
@@ -3402,55 +3349,6 @@
/* End of masks for mPrivateFlags3 */
- /*
- * Masks for mPrivateFlags4, as generated by dumpFlags():
- *
- * |-------|-------|-------|-------|
- * 1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
- * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
- * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
- * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
- * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
- * 11 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
- * |-------|-------|-------|-------|
- */
-
- /**
- * Mask for obtaining the bits which specify how to determine
- * whether a view is important for autofill.
- *
- * <p>NOTE: the important for content capture values were the first flags added and are set in
- * the rightmost position, so we don't need to shift them
- */
- private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
- IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
- | IMPORTANT_FOR_CONTENT_CAPTURE_NO
- | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
- | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
-
- /*
- * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
- * should be called.
- *
- * The idea is to call notifyAppeared() after the view is layout and visible, then call
- * notifyDisappeared() when it's gone (without known when it was removed from the parent).
- */
- private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
- private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
-
- /*
- * Flags used to cache the value returned by isImportantForContentCapture while the view
- * hierarchy is being traversed.
- */
- private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
- private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
-
- private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
- PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
- | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
-
- /* End of masks for mPrivateFlags4 */
-
/** @hide */
protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
/** @hide */
@@ -4074,8 +3972,6 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
int mPrivateFlags3;
- private int mPrivateFlags4;
-
/**
* This view's request for the visibility of the status bar.
* @hide
@@ -5808,11 +5704,6 @@
setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
}
break;
- case R.styleable.View_importantForContentCapture:
- if (a.peekValue(attr) != null) {
- setImportantForContentCapture(a.getInt(attr,
- IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
- }
case R.styleable.View_defaultFocusHighlightEnabled:
if (a.peekValue(attr) != null) {
setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
@@ -8532,62 +8423,6 @@
onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
}
- /**
- * Populates a {@link ViewStructure} for content capture.
- *
- * <p>This method is called after a view is that is eligible for content capture
- * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
- * the user, and the activity rendering the view is enabled for content capture) is laid out and
- * is visible.
- *
- * <p>The populated structure is then passed to the service through
- * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
- *
- * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
- * the node representing this view and return right away, then asynchronously report (not
- * necessarily in the UI thread) when the children nodes appear, disappear or have their text
- * changed by calling
- * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
- * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
- * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
- * respectively. The structure for the a child must be created using
- * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
- * {@code autofillId} for a child can be obtained either through
- * {@code childStructure.getAutofillId()} or
- * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
- *
- * <p>When the virtual view hierarchy represents a web page, you should also:
- *
- * <ul>
- * <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
- * capture events should be generate for that URL.
- * <li>Create a new {@link ContentCaptureSession} child for every HTML element that
- * renders a new URL (like an {@code IFRAME}) and use that session to notify events from
- * that subtree.
- * </ul>
- *
- * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
- * <ul>
- * <li>{@link ViewStructure#setChildCount(int)}
- * <li>{@link ViewStructure#addChildCount(int)}
- * <li>{@link ViewStructure#getChildCount()}
- * <li>{@link ViewStructure#newChild(int)}
- * <li>{@link ViewStructure#asyncNewChild(int)}
- * <li>{@link ViewStructure#asyncCommit()}
- * <li>{@link ViewStructure#setWebDomain(String)}
- * <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
- * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
- * <li>{@link ViewStructure#setDataIsSensitive(boolean)}
- * <li>{@link ViewStructure#setAlpha(float)}
- * <li>{@link ViewStructure#setElevation(float)}
- * <li>{@link ViewStructure#setTransformation(Matrix)}
- *
- * </ul>
- */
- public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
- onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
- }
-
/** @hide */
protected void onProvideStructure(@NonNull ViewStructure structure,
@ViewStructureType int viewFor, int flags) {
@@ -9225,265 +9060,6 @@
}
/**
- * Gets the mode for determining whether this view is important for content capture.
- *
- * <p>See {@link #setImportantForContentCapture(int)} and
- * {@link #isImportantForContentCapture()} for more info about this mode.
- *
- * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
- * {@link #setImportantForContentCapture(int)}.
- *
- * @attr ref android.R.styleable#View_importantForContentCapture
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
- to = "yesExcludeDescendants"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
- to = "noExcludeDescendants")})
- @InspectableProperty(enumMapping = {
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
- name = "yesExcludeDescendants"),
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
- name = "noExcludeDescendants"),
- })
- public @ContentCaptureImportance int getImportantForContentCapture() {
- // NOTE: the important for content capture values were the first flags added and are set in
- // the rightmost position, so we don't need to shift them
- return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
- }
-
- /**
- * Sets the mode for determining whether this view is considered important for content capture.
- *
- * <p>The platform determines the importance for autofill automatically but you
- * can use this method to customize the behavior. Typically, a view that provides text should
- * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
- *
- * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
- * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
- * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
- * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
- *
- * @attr ref android.R.styleable#View_importantForContentCapture
- */
- public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
- // Reset first
- mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
- // Then set again
- // NOTE: the important for content capture values were the first flags added and are set in
- // the rightmost position, so we don't need to shift them
- mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
- }
-
- /**
- * Hints the Android System whether this view is considered important for content capture, based
- * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
- * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
- *
- * <p>See {@link ContentCaptureManager} for more info about content capture.
- *
- * @return whether the view is considered important for content capture.
- *
- * @see #setImportantForContentCapture(int)
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
- */
- public final boolean isImportantForContentCapture() {
- boolean isImportant;
- if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
- isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
- return isImportant;
- }
-
- isImportant = calculateIsImportantForContentCapture();
-
- mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
- if (isImportant) {
- mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
- }
- mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
- return isImportant;
- }
-
- /**
- * Calculates whether the flag is important for content capture so it can be used by
- * {@link #isImportantForContentCapture()} while the tree is traversed.
- */
- private boolean calculateIsImportantForContentCapture() {
- // Check parent mode to ensure we're important
- ViewParent parent = mParent;
- while (parent instanceof View) {
- final int parentImportance = ((View) parent).getImportantForContentCapture();
- if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
- || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
- if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" + this + ") is not important for "
- + "content capture because parent " + parent + "'s importance is "
- + parentImportance);
- }
- return false;
- }
- parent = parent.getParent();
- }
-
- final int importance = getImportantForContentCapture();
-
- // First, check the explicit states.
- if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
- || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
- return true;
- }
- if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
- || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
- if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" + this + ") is not important for content "
- + "capture because its importance is " + importance);
- }
- return false;
- }
-
- // Then use some heuristics to handle AUTO.
- if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
- Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
- + " on view " + this);
- return false;
- }
-
- // View group is important if at least one children also is
- if (this instanceof ViewGroup) {
- final ViewGroup group = (ViewGroup) this;
- for (int i = 0; i < group.getChildCount(); i++) {
- final View child = group.getChildAt(i);
- if (child.isImportantForContentCapture()) {
- return true;
- }
- }
- }
-
- // If the app developer explicitly set hints or autofill hintsfor it, it's important.
- if (getAutofillHints() != null) {
- return true;
- }
-
- // Otherwise, assume it's not important...
- return false;
- }
-
- /**
- * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
- * added, based on whether it's laid out and visible, and without knowing if the parent removed
- * it from the view hierarchy.
- *
- * <p>This method is called from many places (visibility changed, view laid out, view attached
- * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
- * described below:
- *
- * <ol>
- * <li>It should only be called when content capture is enabled for the view.
- * <li>It must call viewAppeared() before viewDisappeared()
- * <li>viewAppearead() can only be called when the view is visible and laidout
- * <li>It should not call the same event twice.
- * </ol>
- */
- private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
- AttachInfo ai = mAttachInfo;
- // Skip it while the view is being laided out for the first time
- if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
-
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW,
- "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName());
- }
- try {
- notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(appeared);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
-
- private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) {
- AttachInfo ai = mAttachInfo;
-
- // First check if context has client, so it saves a service lookup when it doesn't
- if (mContext.getContentCaptureOptions() == null) return;
-
- // Then check if it's enabled in the context...
- final ContentCaptureManager ccm = ai != null ? ai.getContentCaptureManager(mContext)
- : mContext.getSystemService(ContentCaptureManager.class);
- if (ccm == null || !ccm.isContentCaptureEnabled()) return;
-
- // ... and finally at the view level
- // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
- if (!isImportantForContentCapture()) return;
-
- ContentCaptureSession session = getContentCaptureSession();
- if (session == null) return;
-
- if (appeared) {
- if (!isLaidOut() || getVisibility() != VISIBLE
- || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
- + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
- + ", visible=" + (getVisibility() == VISIBLE)
- + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
- & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
- + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
- & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
- }
- return;
- }
- setNotifiedContentCaptureAppeared();
-
- if (ai != null) {
- ai.delayNotifyContentCaptureEvent(session, this, appeared);
- } else {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
- }
- }
- } else {
- if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0
- || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
- + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
- + ", visible=" + (getVisibility() == VISIBLE)
- + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
- & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
- + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
- & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
- }
- return;
- }
- mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
- mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
-
- if (ai != null) {
- ai.delayNotifyContentCaptureEvent(session, this, appeared);
- } else {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
- }
- }
- }
- }
-
- private void setNotifiedContentCaptureAppeared() {
- mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
- mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
- }
-
- /**
* Sets the (optional) {@link ContentCaptureSession} associated with this view.
*
* <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
@@ -9739,68 +9315,6 @@
}
/**
- * Dispatches the initial content capture events for a view structure.
- *
- * @hide
- */
- public void dispatchInitialProvideContentCaptureStructure() {
- AttachInfo ai = mAttachInfo;
- if (ai == null) {
- Log.w(CONTENT_CAPTURE_LOG_TAG,
- "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
- return;
- }
- ContentCaptureManager ccm = ai.mContentCaptureManager;
- if (ccm == null) {
- Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
- + "no ContentCaptureManager for " + this);
- return;
- }
-
- // We must set it before checkign if the view itself is important, because it might
- // initially not be (for example, if it's empty), although that might change later (for
- // example, if important views are added)
- ai.mReadyForContentCaptureUpdates = true;
-
- if (!isImportantForContentCapture()) {
- if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
- Log.d(CONTENT_CAPTURE_LOG_TAG,
- "dispatchProvideContentCaptureStructure(): decorView is not important");
- }
- return;
- }
-
- ai.mContentCaptureManager = ccm;
-
- ContentCaptureSession session = getContentCaptureSession();
- if (session == null) {
- if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
- Log.d(CONTENT_CAPTURE_LOG_TAG,
- "dispatchProvideContentCaptureStructure(): no session for " + this);
- }
- return;
- }
-
- session.internalNotifyViewTreeEvent(/* started= */ true);
- try {
- dispatchProvideContentCaptureStructure();
- } finally {
- session.internalNotifyViewTreeEvent(/* started= */ false);
- }
- }
-
- /** @hide */
- void dispatchProvideContentCaptureStructure() {
- ContentCaptureSession session = getContentCaptureSession();
- if (session != null) {
- ViewStructure structure = session.newViewStructure(this);
- onProvideContentCaptureStructure(structure, /* flags= */ 0);
- setNotifiedContentCaptureAppeared();
- session.notifyViewAppeared(structure);
- }
- }
-
- /**
* @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
*
* Note: Called from the default {@link AccessibilityDelegate}.
@@ -12134,14 +11648,11 @@
}
/**
- * When screen readers (one type of accessibility tool) decide what should be read to the
- * user, they typically look for input focusable ({@link #isFocusable()}) parents of
- * non-focusable text items, and read those focusable parents and their non-focusable children
- * as a unit. In some situations, this behavior is desirable for views that should not take
- * input focus. Setting an item to be screen reader focusable requests that the view be
- * treated as a unit by screen readers without any effect on input focusability. The default
- * value of {@code false} lets screen readers use other signals, like focusable, to determine
- * how to group items.
+ * Sets whether this View should be a focusable element for screen readers
+ * and include non-focusable Views from its subtree when providing feedback.
+ * <p>
+ * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
+ * but does not impact input focus behavior.
*
* @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
* accessibility tools.
@@ -13753,7 +13264,6 @@
public void dispatchStartTemporaryDetach() {
mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
notifyEnterOrExitForAutoFillIfNeeded(false);
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
onStartTemporaryDetach();
}
@@ -13780,7 +13290,6 @@
notifyFocusChangeToInputMethodManager(true /* hasFocus */);
}
notifyEnterOrExitForAutoFillIfNeeded(true);
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
/**
@@ -14372,8 +13881,6 @@
: AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
}
}
-
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
}
/**
@@ -18069,7 +17576,6 @@
}
// Reset content capture caches
- mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
mCachedContentCaptureSession = null;
if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
@@ -20079,7 +19585,6 @@
needGlobalAttributesUpdate(false);
notifyEnterOrExitForAutoFillIfNeeded(true);
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -20129,7 +19634,6 @@
}
notifyEnterOrExitForAutoFillIfNeeded(false);
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
}
/**
@@ -22442,8 +21946,6 @@
mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
notifyEnterOrExitForAutoFillIfNeeded(true);
}
-
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
private boolean hasParentWantsFocus() {
@@ -28650,23 +28152,6 @@
View mTooltipHost;
/**
- * The initial structure has been reported so the view is ready to report updates.
- */
- boolean mReadyForContentCaptureUpdates;
-
- /**
- * Map(keyed by session) of content capture events that need to be notified after the view
- * hierarchy is traversed: value is either the view itself for appearead events, or its
- * autofill id for disappeared.
- */
- SparseArray<ArrayList<Object>> mContentCaptureEvents;
-
- /**
- * Cached reference to the {@link ContentCaptureManager}.
- */
- ContentCaptureManager mContentCaptureManager;
-
- /**
* Creates a new set of attachment information with the specified
* events handler and thread.
*
@@ -28684,31 +28169,6 @@
mRootCallbacks = effectPlayer;
mTreeObserver = new ViewTreeObserver(context);
}
-
- private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
- @NonNull View view, boolean appeared) {
- if (mContentCaptureEvents == null) {
- // Most of the time there will be just one session, so intial capacity is 1
- mContentCaptureEvents = new SparseArray<>(1);
- }
- int sessionId = session.getId();
- // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
- ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
- if (events == null) {
- events = new ArrayList<>();
- mContentCaptureEvents.put(sessionId, events);
- }
- events.add(appeared ? view : view.getAutofillId());
- }
-
- @Nullable
- ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
- if (mContentCaptureManager != null) {
- return mContentCaptureManager;
- }
- mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
- return mContentCaptureManager;
- }
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 937bd1b..d362024 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3606,7 +3606,7 @@
return;
}
- final ChildListForAutoFillOrContentCapture children = getChildrenForAutofill(flags);
+ final ChildListForAutofill children = getChildrenForAutofill(flags);
final int childrenCount = children.size();
structure.setChildCount(childrenCount);
for (int i = 0; i < childrenCount; i++) {
@@ -3617,30 +3617,14 @@
children.recycle();
}
- /** @hide */
- @Override
- public void dispatchProvideContentCaptureStructure() {
- super.dispatchProvideContentCaptureStructure();
-
- if (!isLaidOut()) return;
-
- final ChildListForAutoFillOrContentCapture children = getChildrenForContentCapture();
- final int childrenCount = children.size();
- for (int i = 0; i < childrenCount; i++) {
- final View child = children.get(i);
- child.dispatchProvideContentCaptureStructure();
- }
- children.recycle();
- }
-
/**
* Gets the children for autofill. Children for autofill are the first
* level descendants that are important for autofill. The returned
* child list object is pooled and the caller must recycle it once done.
* @hide */
- private @NonNull ChildListForAutoFillOrContentCapture getChildrenForAutofill(
+ private @NonNull ChildListForAutofill getChildrenForAutofill(
@AutofillFlags int flags) {
- final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture
+ final ChildListForAutofill children = ChildListForAutofill
.obtain();
populateChildrenForAutofill(children, flags);
return children;
@@ -3668,34 +3652,6 @@
}
}
- private @NonNull ChildListForAutoFillOrContentCapture getChildrenForContentCapture() {
- final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture
- .obtain();
- populateChildrenForContentCapture(children);
- return children;
- }
-
- /** @hide */
- private void populateChildrenForContentCapture(ArrayList<View> list) {
- final int childrenCount = mChildrenCount;
- if (childrenCount <= 0) {
- return;
- }
- final ArrayList<View> preorderedList = buildOrderedChildList();
- final boolean customOrder = preorderedList == null
- && isChildrenDrawingOrderEnabled();
- for (int i = 0; i < childrenCount; i++) {
- final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
- final View child = (preorderedList == null)
- ? mChildren[childIndex] : preorderedList.get(childIndex);
- if (child.isImportantForContentCapture()) {
- list.add(child);
- } else if (child instanceof ViewGroup) {
- ((ViewGroup) child).populateChildrenForContentCapture(list);
- }
- }
- }
-
private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList, View[] children,
int childIndex) {
final View child;
@@ -8678,16 +8634,16 @@
/**
* Pooled class that to hold the children for autifill.
*/
- private static class ChildListForAutoFillOrContentCapture extends ArrayList<View> {
+ private static class ChildListForAutofill extends ArrayList<View> {
private static final int MAX_POOL_SIZE = 32;
- private static final Pools.SimplePool<ChildListForAutoFillOrContentCapture> sPool =
+ private static final Pools.SimplePool<ChildListForAutofill> sPool =
new Pools.SimplePool<>(MAX_POOL_SIZE);
- public static ChildListForAutoFillOrContentCapture obtain() {
- ChildListForAutoFillOrContentCapture list = sPool.acquire();
+ public static ChildListForAutofill obtain() {
+ ChildListForAutofill list = sPool.acquire();
if (list == null) {
- list = new ChildListForAutoFillOrContentCapture();
+ list = new ChildListForAutofill();
}
return list;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f3b7ad5..7ad118e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -105,11 +105,7 @@
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
-import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
-import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureSession;
-import android.view.contentcapture.MainContentCaptureSession;
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
@@ -224,21 +220,6 @@
*/
static final int MAX_TRACKBALL_DELAY = 250;
- /**
- * Initial value for {@link #mContentCaptureEnabled}.
- */
- private static final int CONTENT_CAPTURE_ENABLED_NOT_CHECKED = 0;
-
- /**
- * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code true}.
- */
- private static final int CONTENT_CAPTURE_ENABLED_TRUE = 1;
-
- /**
- * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code false}.
- */
- private static final int CONTENT_CAPTURE_ENABLED_FALSE = 2;
-
@UnsupportedAppUsage
static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
@@ -435,10 +416,6 @@
boolean mLayoutRequested;
boolean mFirst;
- @Nullable
- int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED;
- boolean mPerformContentCapture;
-
boolean mReportNextDraw;
boolean mFullRedrawNeeded;
boolean mNewSurfaceNeeded;
@@ -637,7 +614,6 @@
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
- mPerformContentCapture = true; // also true for the first time the view is added
mAdded = false;
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
context);
@@ -2787,55 +2763,9 @@
}
}
- if (mAttachInfo.mContentCaptureEvents != null) {
- notifyContentCatpureEvents();
- }
-
mIsInTraversal = false;
}
- private void notifyContentCatpureEvents() {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents");
- try {
- MainContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager
- .getMainContentCaptureSession();
- for (int i = 0; i < mAttachInfo.mContentCaptureEvents.size(); i++) {
- int sessionId = mAttachInfo.mContentCaptureEvents.keyAt(i);
- mainSession.notifyViewTreeEvent(sessionId, /* started= */ true);
- ArrayList<Object> events = mAttachInfo.mContentCaptureEvents
- .valueAt(i);
- for_each_event: for (int j = 0; j < events.size(); j++) {
- Object event = events.get(j);
- if (event instanceof AutofillId) {
- mainSession.notifyViewDisappeared(sessionId, (AutofillId) event);
- } else if (event instanceof View) {
- View view = (View) event;
- ContentCaptureSession session = view.getContentCaptureSession();
- if (session == null) {
- Log.w(mTag, "no content capture session on view: " + view);
- continue for_each_event;
- }
- int actualId = session.getId();
- if (actualId != sessionId) {
- Log.w(mTag, "content capture session mismatch for view (" + view
- + "): was " + sessionId + " before, it's " + actualId + " now");
- continue for_each_event;
- }
- ViewStructure structure = session.newViewStructure(view);
- view.onProvideContentCaptureStructure(structure, /* flags= */ 0);
- session.notifyViewAppeared(structure);
- } else {
- Log.w(mTag, "invalid content capture event: " + event);
- }
- }
- mainSession.notifyViewTreeEvent(sessionId, /* started= */ false);
- }
- mAttachInfo.mContentCaptureEvents = null;
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
-
private void notifySurfaceDestroyed() {
mSurfaceHolder.ungetCallbacks();
SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
@@ -2966,13 +2896,6 @@
}
}
mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
-
- // NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
- // is lost, so we don't need to to force a flush - there might be other events such as
- // text changes, but these should be flushed independently.
- if (hasWindowFocus) {
- handleContentCaptureFlush();
- }
}
private void fireAccessibilityFocusEventIfHasFocusedNode() {
@@ -3539,86 +3462,6 @@
pendingDrawFinished();
}
}
- if (mPerformContentCapture) {
- performContentCaptureInitialReport();
- }
- }
-
- /**
- * Checks (and caches) if content capture is enabled for this context.
- */
- private boolean isContentCaptureEnabled() {
- switch (mContentCaptureEnabled) {
- case CONTENT_CAPTURE_ENABLED_TRUE:
- return true;
- case CONTENT_CAPTURE_ENABLED_FALSE:
- return false;
- case CONTENT_CAPTURE_ENABLED_NOT_CHECKED:
- final boolean reallyEnabled = isContentCaptureReallyEnabled();
- mContentCaptureEnabled = reallyEnabled ? CONTENT_CAPTURE_ENABLED_TRUE
- : CONTENT_CAPTURE_ENABLED_FALSE;
- return reallyEnabled;
- default:
- Log.w(TAG, "isContentCaptureEnabled(): invalid state " + mContentCaptureEnabled);
- return false;
- }
-
- }
-
- /**
- * Checks (without caching) if content capture is enabled for this context.
- */
- private boolean isContentCaptureReallyEnabled() {
- // First check if context supports it, so it saves a service lookup when it doesn't
- if (mContext.getContentCaptureOptions() == null) return false;
-
- final ContentCaptureManager ccm = mAttachInfo.getContentCaptureManager(mContext);
- // Then check if it's enabled in the contex itself.
- if (ccm == null || !ccm.isContentCaptureEnabled()) return false;
-
- return true;
- }
-
- private void performContentCaptureInitialReport() {
- mPerformContentCapture = false; // One-time offer!
- final View rootView = mView;
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(mTag, "performContentCaptureInitialReport() on " + rootView);
- }
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchContentCapture() for "
- + getClass().getSimpleName());
- }
- try {
- if (!isContentCaptureEnabled()) return;
-
- // Content capture is a go!
- rootView.dispatchInitialProvideContentCaptureStructure();
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
-
- private void handleContentCaptureFlush() {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(mTag, "handleContentCaptureFlush()");
- }
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "flushContentCapture for "
- + getClass().getSimpleName());
- }
- try {
- if (!isContentCaptureEnabled()) return;
-
- final ContentCaptureManager ccm = mAttachInfo.mContentCaptureManager;
- if (ccm == null) {
- Log.w(TAG, "No ContentCapture on AttachInfo");
- return;
- }
- ccm.flush(ContentCaptureSession.FLUSH_REASON_VIEW_ROOT_ENTERED);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
}
private boolean draw(boolean fullRedrawNeeded) {
@@ -3986,6 +3829,24 @@
}
/**
+ * Set the root-level system gesture exclusion rects. These are added to those provided by
+ * the root's view hierarchy.
+ */
+ public void setRootSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ mGestureExclusionTracker.setRootSystemGestureExclusionRects(rects);
+ mHandler.sendEmptyMessage(MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED);
+ }
+
+ /**
+ * Returns the root-level system gesture exclusion rects. These do not include those provided by
+ * the root's view hierarchy.
+ */
+ @NonNull
+ public List<Rect> getRootSystemGestureExclusionRects() {
+ return mGestureExclusionTracker.getRootSystemGestureExclusionRects();
+ }
+
+ /**
* Requests that the root render node is invalidated next time we perform a draw, such that
* {@link WindowCallbacks#onPostDraw} gets called.
*/
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index fc9d8c2..b0ec621 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -48,6 +48,7 @@
import android.transition.TransitionManager;
import android.view.accessibility.AccessibilityEvent;
+import java.util.Collections;
import java.util.List;
/**
@@ -2397,6 +2398,53 @@
return false;
}
+ /**
+ * Sets a list of areas within this window's coordinate space where the system should not
+ * intercept touch or other pointing device gestures.
+ *
+ * <p>This method should be used by apps that make use of
+ * {@link #takeSurface(SurfaceHolder.Callback2)} and do not have a view hierarchy available.
+ * Apps that do have a view hierarchy should use
+ * {@link View#setSystemGestureExclusionRects(List)} instead. This method does not modify or
+ * replace the gesture exclusion rects populated by individual views in this window's view
+ * hierarchy using {@link View#setSystemGestureExclusionRects(List)}.</p>
+ *
+ * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
+ * input in order to function correctly in the presence of global system gestures that may
+ * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
+ * to provide system-level navigation functionality, a view such as a navigation drawer
+ * container can mark the left (or starting) edge of itself as requiring gesture capture
+ * priority using this API. The system may then choose to relax its own gesture recognition
+ * to allow the app to consume the user's gesture. It is not necessary for an app to register
+ * exclusion rects for broadly spanning regions such as the entirety of a
+ * <code>ScrollView</code> or for simple press and release click targets such as
+ * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
+ * a precision touch gesture in a small area in either the X or Y dimension, such as
+ * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
+ *
+ * <p>Do not modify the provided list after this method is called.</p>
+ *
+ * @param rects A list of precision gesture regions that this window needs to function correctly
+ */
+ @SuppressWarnings("unused")
+ public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ throw new UnsupportedOperationException("window does not support gesture exclusion rects");
+ }
+
+ /**
+ * Retrieve the list of areas within this window's coordinate space where the system should not
+ * intercept touch or other pointing device gestures. This is the list as set by
+ * {@link #setSystemGestureExclusionRects(List)} or an empty list if
+ * {@link #setSystemGestureExclusionRects(List)} has not been called. It does not include
+ * exclusion rects set by this window's view hierarchy.
+ *
+ * @return a list of system gesture exclusion rects specific to this window
+ */
+ @NonNull
+ public List<Rect> getSystemGestureExclusionRects() {
+ return Collections.emptyList();
+ }
+
/** @hide */
public void setTheme(int resId) {
}
diff --git a/core/java/android/view/autofill/AutofillManagerInternal.java b/core/java/android/view/autofill/AutofillManagerInternal.java
index 3de1a03..a07d46d 100644
--- a/core/java/android/view/autofill/AutofillManagerInternal.java
+++ b/core/java/android/view/autofill/AutofillManagerInternal.java
@@ -45,4 +45,12 @@
@Nullable
public abstract AutofillOptions getAutofillOptions(@NonNull String packageName,
long versionCode, @UserIdInt int userId);
+
+ /**
+ * Checks whether the given {@code uid} owns the
+ * {@link android.service.autofill.augmented.AugmentedAutofillService} implementation associated
+ * with the given {@code userId}.
+ */
+ public abstract boolean isAugmentedAutofillServiceForUser(@NonNull int callingUid,
+ @UserIdInt int userId);
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureCondition.java b/core/java/android/view/contentcapture/ContentCaptureCondition.java
index 6f9d4d3..54ebf55 100644
--- a/core/java/android/view/contentcapture/ContentCaptureCondition.java
+++ b/core/java/android/view/contentcapture/ContentCaptureCondition.java
@@ -35,7 +35,8 @@
public final class ContentCaptureCondition implements Parcelable {
/**
- * When set, package should use the {@link LocusId#getId()} as a regular expression.
+ * When set, package should use the {@link LocusId#getId()} as a regular expression (using the
+ * {@link java.util.regex.Pattern} format).
*/
public static final int FLAG_IS_REGEX = 0x2;
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 2539356..26454c0 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -191,8 +191,8 @@
*
* <p>If your view provides its own virtual hierarchy (for example, if it's a browser that draws
* the HTML using {@link Canvas} or native libraries in a different render process), then the view
- * is also responsible to notify the session when the virtual elements appear and disappear - see
- * {@link View#onProvideContentCaptureStructure(ViewStructure, int)} for more info.
+ * is also responsible to notify the session when the virtual elements appear and disappear -
+ * see {@link ContentCaptureSession#newViewStructure(View)} for more info.
*/
@SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
public final class ContentCaptureManager {
@@ -343,15 +343,6 @@
private MainContentCaptureSession mMainSession;
/** @hide */
- public interface ContentCaptureClient {
- /**
- * Gets the component name of the client.
- */
- @NonNull
- ComponentName contentCaptureClientGetComponentName();
- }
-
- /** @hide */
public ContentCaptureManager(@NonNull Context context,
@NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
@@ -578,16 +569,15 @@
}
/**
- * Called by the app to request the content capture service to remove user-data associated with
- * some context.
+ * Called by the app to remove content capture data associated with some context.
*
- * @param request object specifying what user data should be removed.
+ * @param request object specifying what data should be removed.
*/
- public void removeUserData(@NonNull UserDataRemovalRequest request) {
+ public void removeData(@NonNull DataRemovalRequest request) {
Preconditions.checkNotNull(request);
try {
- mService.removeUserData(request);
+ mService.removeData(request);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 7761038..17a1fb4 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -356,10 +356,6 @@
/**
* Notifies the Content Capture Service that a node has been added to the view structure.
*
- * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
- * automatically by the Android System for views that return {@code true} on
- * {@link View#onProvideContentCaptureStructure(ViewStructure, int)}.
- *
* @param node node that has been added.
*/
public final void notifyViewAppeared(@NonNull ViewStructure node) {
@@ -378,9 +374,6 @@
/**
* Notifies the Content Capture Service that a node has been removed from the view structure.
*
- * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
- * automatically by the Android System for standard views.
- *
* @param id id of the node that has been removed.
*/
public final void notifyViewDisappeared(@NonNull AutofillId id) {
@@ -441,7 +434,46 @@
/**
* Creates a {@link ViewStructure} for a "standard" view.
*
- * @hide
+ * <p>This method should be called after a visible view is laid out; the view then must populate
+ * the structure and pass it to {@link #notifyViewAppeared(ViewStructure)}.
+ *
+ * <b>Note: </b>views that manage a virtual structure under this view must populate just the
+ * node representing this view and return right away, then asynchronously report (not
+ * necessarily in the UI thread) when the children nodes appear, disappear or have their text
+ * changed by calling {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
+ * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
+ * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)} respectively.
+ * The structure for the a child must be created using
+ * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
+ * {@code autofillId} for a child can be obtained either through
+ * {@code childStructure.getAutofillId()} or
+ * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
+ *
+ * <p>When the virtual view hierarchy represents a web page, you should also:
+ *
+ * <ul>
+ * <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content capture
+ * events should be generate for that URL.
+ * <li>Create a new {@link ContentCaptureSession} child for every HTML element that renders a
+ * new URL (like an {@code IFRAME}) and use that session to notify events from that subtree.
+ * </ul>
+ *
+ * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
+ * <ul>
+ * <li>{@link ViewStructure#setChildCount(int)}
+ * <li>{@link ViewStructure#addChildCount(int)}
+ * <li>{@link ViewStructure#getChildCount()}
+ * <li>{@link ViewStructure#newChild(int)}
+ * <li>{@link ViewStructure#asyncNewChild(int)}
+ * <li>{@link ViewStructure#asyncCommit()}
+ * <li>{@link ViewStructure#setWebDomain(String)}
+ * <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
+ * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
+ * <li>{@link ViewStructure#setDataIsSensitive(boolean)}
+ * <li>{@link ViewStructure#setAlpha(float)}
+ * <li>{@link ViewStructure#setElevation(float)}
+ * <li>{@link ViewStructure#setTransformation(android.graphics.Matrix)}
+ * </ul>
*/
@NonNull
public final ViewStructure newViewStructure(@NonNull View view) {
diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.aidl b/core/java/android/view/contentcapture/DataRemovalRequest.aidl
similarity index 94%
rename from core/java/android/view/contentcapture/UserDataRemovalRequest.aidl
rename to core/java/android/view/contentcapture/DataRemovalRequest.aidl
index fbe47e0..c89d222 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.aidl
+++ b/core/java/android/view/contentcapture/DataRemovalRequest.aidl
@@ -16,4 +16,4 @@
package android.view.contentcapture;
-parcelable UserDataRemovalRequest;
+parcelable DataRemovalRequest;
diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.java b/core/java/android/view/contentcapture/DataRemovalRequest.java
similarity index 82%
rename from core/java/android/view/contentcapture/UserDataRemovalRequest.java
rename to core/java/android/view/contentcapture/DataRemovalRequest.java
index 3e1e4ab..3792846b 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.java
+++ b/core/java/android/view/contentcapture/DataRemovalRequest.java
@@ -31,14 +31,12 @@
import java.util.List;
/**
- * Class used by apps to request the Content Capture service to remove user-data associated with
- * some context.
+ * Class used by apps to remove content capture data associated with {@link LocusId LocusIds}.
*/
-public final class UserDataRemovalRequest implements Parcelable {
+public final class DataRemovalRequest implements Parcelable {
/**
- * When set, service should use the {@link LocusId#getId()} as prefix for the data to be
- * removed.
+ * When set, the {@link LocusId#getId()} is the prefix for the data to be removed.
*/
public static final int FLAG_IS_PREFIX = 0x1;
@@ -54,7 +52,7 @@
private final boolean mForEverything;
private ArrayList<LocusIdRequest> mLocusIdRequests;
- private UserDataRemovalRequest(@NonNull Builder builder) {
+ private DataRemovalRequest(@NonNull Builder builder) {
mPackageName = ActivityThread.currentActivityThread().getApplication().getPackageName();
mForEverything = builder.mForEverything;
if (builder.mLocusIds != null) {
@@ -67,7 +65,7 @@
}
}
- private UserDataRemovalRequest(@NonNull Parcel parcel) {
+ private DataRemovalRequest(@NonNull Parcel parcel) {
mPackageName = parcel.readString();
mForEverything = parcel.readBoolean();
if (!mForEverything) {
@@ -89,7 +87,7 @@
}
/**
- * Checks if app is requesting to remove all user data associated with its package.
+ * Checks if app is requesting to remove content capture data associated with its package.
*/
public boolean isForEverything() {
return mForEverything;
@@ -104,7 +102,7 @@
}
/**
- * Builder for {@link UserDataRemovalRequest} objects.
+ * Builder for {@link DataRemovalRequest} objects.
*/
public static final class Builder {
@@ -115,7 +113,7 @@
private boolean mDestroyed;
/**
- * Requests servive to remove all user data associated with the app's package.
+ * Requests to remove all content capture data associated with the app's package.
*
* @return this builder
*/
@@ -132,7 +130,7 @@
* Request service to remove data associated with a given {@link LocusId}.
*
* @param locusId the {@link LocusId} being requested to be removed.
- * @param flags either {@link UserDataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}
+ * @param flags either {@link DataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}
*
* @return this builder
*/
@@ -154,17 +152,17 @@
}
/**
- * Builds the {@link UserDataRemovalRequest}.
+ * Builds the {@link DataRemovalRequest}.
*/
@NonNull
- public UserDataRemovalRequest build() {
+ public DataRemovalRequest build() {
throwIfDestroyed();
Preconditions.checkState(mForEverything || mLocusIds != null,
"must call either #forEverything() or add one #addLocusId()");
mDestroyed = true;
- return new UserDataRemovalRequest(this);
+ return new DataRemovalRequest(this);
}
private void throwIfDestroyed() {
@@ -192,19 +190,19 @@
}
}
- public static final @android.annotation.NonNull Parcelable.Creator<UserDataRemovalRequest> CREATOR =
- new Parcelable.Creator<UserDataRemovalRequest>() {
+ public static final @android.annotation.NonNull Parcelable.Creator<DataRemovalRequest> CREATOR =
+ new Parcelable.Creator<DataRemovalRequest>() {
@Override
@NonNull
- public UserDataRemovalRequest createFromParcel(Parcel parcel) {
- return new UserDataRemovalRequest(parcel);
+ public DataRemovalRequest createFromParcel(Parcel parcel) {
+ return new DataRemovalRequest(parcel);
}
@Override
@NonNull
- public UserDataRemovalRequest[] newArray(int size) {
- return new UserDataRemovalRequest[size];
+ public DataRemovalRequest[] newArray(int size) {
+ return new DataRemovalRequest[size];
}
};
@@ -231,7 +229,7 @@
/**
* Gets the flags associates with request.
*
- * @return either {@link UserDataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}.
+ * @return either {@link DataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}.
*/
@NonNull
public @Flags int getFlags() {
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index 7335073..ced9417 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -19,7 +19,7 @@
import android.content.ComponentName;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureEvent;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
import android.os.IBinder;
import com.android.internal.os.IResultReceiver;
@@ -59,9 +59,9 @@
void getServiceComponentName(in IResultReceiver result);
/**
- * Requests the removal of user data for the calling user.
+ * Requests the removal of content capture data for the calling user.
*/
- void removeUserData(in UserDataRemovalRequest request);
+ void removeData(in DataRemovalRequest request);
/**
* Returns whether the content capture feature is enabled for the calling user.
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 5e00425..fd73856 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1951,6 +1951,23 @@
}
/**
+ * Unregister for IME state callbacks and applying visibility in
+ * {@link android.view.ImeInsetsSourceConsumer}.
+ * @hide
+ */
+ public void unregisterImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
+ if (imeInsetsConsumer == null) {
+ throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
+ }
+
+ synchronized (mH) {
+ if (mImeInsetsConsumer == imeInsetsConsumer) {
+ mImeInsetsConsumer = null;
+ }
+ }
+ }
+
+ /**
* Call showSoftInput with currently focused view.
* @return {@code true} if IME can be shown.
* @hide
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
index b408129..f2fa67d 100644
--- a/core/java/android/view/textclassifier/ConversationActions.java
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -316,16 +316,20 @@
private final List<String> mHints;
@Nullable
private String mCallingPackageName;
+ @NonNull
+ private Bundle mExtras;
private Request(
@NonNull List<Message> conversation,
@NonNull TextClassifier.EntityConfig typeConfig,
int maxSuggestions,
- @Nullable @Hint List<String> hints) {
+ @Nullable @Hint List<String> hints,
+ @NonNull Bundle extras) {
mConversation = Preconditions.checkNotNull(conversation);
mTypeConfig = Preconditions.checkNotNull(typeConfig);
mMaxSuggestions = maxSuggestions;
mHints = hints;
+ mExtras = extras;
}
private static Request readFromParcel(Parcel in) {
@@ -336,12 +340,13 @@
List<String> hints = new ArrayList<>();
in.readStringList(hints);
String callingPackageName = in.readString();
-
+ Bundle extras = in.readBundle();
Request request = new Request(
conversation,
typeConfig,
maxSuggestions,
- hints);
+ hints,
+ extras);
request.setCallingPackageName(callingPackageName);
return request;
}
@@ -353,6 +358,7 @@
parcel.writeInt(mMaxSuggestions);
parcel.writeStringList(mHints);
parcel.writeString(mCallingPackageName);
+ parcel.writeBundle(mExtras);
}
@Override
@@ -421,6 +427,16 @@
return mCallingPackageName;
}
+ /**
+ * Returns the extended data related to this request.
+ *
+ * <p><b>NOTE: </b>Do not modify this bundle.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
/** Builder object to construct the {@link Request} object. */
public static final class Builder {
@NonNull
@@ -431,6 +447,8 @@
@Nullable
@Hint
private List<String> mHints;
+ @Nullable
+ private Bundle mExtras;
/**
* Constructs a builder.
@@ -469,6 +487,13 @@
return this;
}
+ /** Sets a set of extended data to the request. */
+ @NonNull
+ public Builder setExtras(@Nullable Bundle bundle) {
+ mExtras = bundle;
+ return this;
+ }
+
/** Builds the {@link Request} object. */
@NonNull
public Request build() {
@@ -480,7 +505,8 @@
mMaxSuggestions,
mHints == null
? Collections.emptyList()
- : Collections.unmodifiableList(mHints));
+ : Collections.unmodifiableList(mHints),
+ mExtras == null ? Bundle.EMPTY : mExtras);
}
}
}
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
index 7b23674..11e0e2c 100644
--- a/core/java/android/view/textclassifier/ExtrasUtils.java
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -36,6 +36,7 @@
// TODO: Make this a TestApi for CTS testing.
public final class ExtrasUtils {
+ // Keys for response objects.
private static final String SERIALIZED_ENTITIES_DATA = "serialized-entities-data";
private static final String ENTITIES_EXTRAS = "entities-extras";
private static final String ACTION_INTENT = "action-intent";
@@ -48,6 +49,10 @@
private static final String TEXT_LANGUAGES = "text-languages";
private static final String ENTITIES = "entities";
+ // Keys for request objects.
+ private static final String IS_SERIALIZED_ENTITY_DATA_ENABLED =
+ "is-serialized-entity-data-enabled";
+
private ExtrasUtils() {}
/**
@@ -308,7 +313,23 @@
/**
* Returns a list of entities contained in the {@code extra}.
*/
+ @Nullable
public static List<Bundle> getEntities(Bundle container) {
return container.getParcelableArrayList(ENTITIES);
}
+
+ /**
+ * Whether the annotator should populate serialized entity data into the result object.
+ */
+ public static boolean isSerializedEntityDataEnabled(TextLinks.Request request) {
+ return request.getExtras().getBoolean(IS_SERIALIZED_ENTITY_DATA_ENABLED);
+ }
+
+ /**
+ * To indicate whether the annotator should populate serialized entity data in the result
+ * object.
+ */
+ public static void putIsSerializedEntityDataEnabled(Bundle bundle, boolean isEnabled) {
+ bundle.putBoolean(IS_SERIALIZED_ENTITY_DATA_ENABLED, isEnabled);
+ }
}
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index 236f89b..d3d61a7 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.icu.util.ULocale;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,54 +31,65 @@
import java.util.Arrays;
/**
- * A text classifier event.
+ * This class represents events that are sent by components to the {@link TextClassifier} to report
+ * something of note that relates to a feature powered by the TextClassifier. The TextClassifier may
+ * log these events or use them to improve future responses to queries.
+ * <p>
+ * Each categories of the events have their own subclass. Events of each types has an associated
+ * set of related properties. You can find the specification of them in the subclasses.
*/
-// TODO: Comprehensive javadoc.
-public final class TextClassifierEvent implements Parcelable {
+public abstract class TextClassifierEvent implements Parcelable {
- public static final @android.annotation.NonNull Creator<TextClassifierEvent> CREATOR = new Creator<TextClassifierEvent>() {
- @Override
- public TextClassifierEvent createFromParcel(Parcel in) {
- return readFromParcel(in);
- }
-
- @Override
- public TextClassifierEvent[] newArray(int size) {
- return new TextClassifierEvent[size];
- }
- };
+ private static final int PARCEL_TOKEN_TEXT_SELECTION_EVENT = 1;
+ private static final int PARCEL_TOKEN_TEXT_LINKIFY_EVENT = 2;
+ private static final int PARCEL_TOKEN_CONVERSATION_ACTION_EVENT = 3;
+ private static final int PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT = 4;
/** @hide **/
@Retention(RetentionPolicy.SOURCE)
- @IntDef({CATEGORY_UNDEFINED, CATEGORY_SELECTION, CATEGORY_LINKIFY,
+ @IntDef({CATEGORY_SELECTION, CATEGORY_LINKIFY,
CATEGORY_CONVERSATION_ACTIONS, CATEGORY_LANGUAGE_DETECTION})
public @interface Category {
// For custom event categories, use range 1000+.
}
- /** Undefined category */
- public static final int CATEGORY_UNDEFINED = 0;
- /** Smart selection */
+
+ /**
+ * Smart selection
+ *
+ * @see TextSelectionEvent
+ */
public static final int CATEGORY_SELECTION = 1;
- /** Linkify */
+ /**
+ * Linkify
+ *
+ * @see TextLinkifyEvent
+ */
public static final int CATEGORY_LINKIFY = 2;
- /** Conversation actions */
+ /**
+ * Conversation actions
+ *
+ * @see ConversationActionsEvent
+ */
public static final int CATEGORY_CONVERSATION_ACTIONS = 3;
- /** Language detection */
+ /**
+ * Language detection
+ *
+ * @see LanguageDetectionEvent
+ */
public static final int CATEGORY_LANGUAGE_DETECTION = 4;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({TYPE_UNDEFINED, TYPE_SELECTION_STARTED, TYPE_SELECTION_MODIFIED,
- TYPE_SMART_SELECTION_SINGLE, TYPE_SMART_SELECTION_MULTI, TYPE_AUTO_SELECTION,
- TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION,
- TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION,
- TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL,
- TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED})
+ @IntDef({TYPE_SELECTION_STARTED, TYPE_SELECTION_MODIFIED,
+ TYPE_SMART_SELECTION_SINGLE, TYPE_SMART_SELECTION_MULTI, TYPE_AUTO_SELECTION,
+ TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION,
+ TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION,
+ TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL,
+ TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED})
public @interface Type {
// For custom event types, use range 1,000,000+.
}
- /** User started a new selection. */
- public static final int TYPE_UNDEFINED = 0;
+
/** User started a new selection. */
public static final int TYPE_SELECTION_STARTED = 1;
/** User modified an existing selection. */
@@ -119,63 +131,49 @@
/** TextClassifier generated some actions */
public static final int TYPE_ACTIONS_GENERATED = 20;
- @Category private final int mEventCategory;
- @Type private final int mEventType;
- @Nullable private final String[] mEntityTypes;
- @Nullable private final TextClassificationContext mEventContext;
- @Nullable private final String mResultId;
+ @Category
+ private final int mEventCategory;
+ @Type
+ private final int mEventType;
+ @Nullable
+ private final String[] mEntityTypes;
+ @Nullable
+ private final TextClassificationContext mEventContext;
+ @Nullable
+ private final String mResultId;
private final int mEventIndex;
- private final long mEventTime;
+ private final float[] mScores;
+ @Nullable
+ private final String mModelName;
+ private final int[] mActionIndices;
private final Bundle mExtras;
- // Smart selection.
- private final int mRelativeWordStartIndex;
- private final int mRelativeWordEndIndex;
- private final int mRelativeSuggestedWordStartIndex;
- private final int mRelativeSuggestedWordEndIndex;
+ private TextClassifierEvent(Builder builder) {
+ mEventCategory = builder.mEventCategory;
+ mEventType = builder.mEventType;
+ mEntityTypes = builder.mEntityTypes;
+ mEventContext = builder.mEventContext;
+ mResultId = builder.mResultId;
+ mEventIndex = builder.mEventIndex;
+ mScores = builder.mScores;
+ mModelName = builder.mModelName;
+ mActionIndices = builder.mActionIndices;
+ mExtras = builder.mExtras == null ? Bundle.EMPTY : builder.mExtras;
+ }
- // Smart action.
- private final int[] mActionIndices;
-
- // Language detection.
- @Nullable private final String mLanguage;
- private final float mScore;
-
- @Nullable private final String mModelName;
-
- private TextClassifierEvent(
- int eventCategory,
- int eventType,
- String[] entityTypes,
- TextClassificationContext eventContext,
- String resultId,
- int eventIndex,
- long eventTime,
- Bundle extras,
- int relativeWordStartIndex,
- int relativeWordEndIndex,
- int relativeSuggestedWordStartIndex,
- int relativeSuggestedWordEndIndex,
- int[] actionIndex,
- String language,
- float score,
- String modelVersion) {
- mEventCategory = eventCategory;
- mEventType = eventType;
- mEntityTypes = entityTypes;
- mEventContext = eventContext;
- mResultId = resultId;
- mEventIndex = eventIndex;
- mEventTime = eventTime;
- mExtras = extras;
- mRelativeWordStartIndex = relativeWordStartIndex;
- mRelativeWordEndIndex = relativeWordEndIndex;
- mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
- mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
- mActionIndices = actionIndex;
- mLanguage = language;
- mScore = score;
- mModelName = modelVersion;
+ private TextClassifierEvent(Parcel in) {
+ mEventCategory = in.readInt();
+ mEventType = in.readInt();
+ mEntityTypes = in.readStringArray();
+ mEventContext = in.readParcelable(null);
+ mResultId = in.readString();
+ mEventIndex = in.readInt();
+ int scoresLength = in.readInt();
+ mScores = new float[scoresLength];
+ in.readFloatArray(mScores);
+ mModelName = in.readString();
+ mActionIndices = in.createIntArray();
+ mExtras = in.readBundle();
}
@Override
@@ -183,44 +181,62 @@
return 0;
}
+ @NonNull
+ public static final Creator<TextClassifierEvent> CREATOR = new Creator<TextClassifierEvent>() {
+ @Override
+ public TextClassifierEvent createFromParcel(Parcel in) {
+ int token = in.readInt();
+ if (token == PARCEL_TOKEN_TEXT_SELECTION_EVENT) {
+ return new TextSelectionEvent(in);
+ }
+ if (token == PARCEL_TOKEN_TEXT_LINKIFY_EVENT) {
+ return new TextLinkifyEvent(in);
+ }
+ if (token == PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT) {
+ return new LanguageDetectionEvent(in);
+ }
+ if (token == PARCEL_TOKEN_CONVERSATION_ACTION_EVENT) {
+ return new ConversationActionsEvent(in);
+ }
+ throw new IllegalStateException("Unexpected input event type token in parcel.");
+ }
+
+ @Override
+ public TextClassifierEvent[] newArray(int size) {
+ return new TextClassifierEvent[size];
+ }
+ };
+
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(getParcelToken());
dest.writeInt(mEventCategory);
dest.writeInt(mEventType);
dest.writeStringArray(mEntityTypes);
dest.writeParcelable(mEventContext, flags);
dest.writeString(mResultId);
dest.writeInt(mEventIndex);
- dest.writeLong(mEventTime);
- dest.writeBundle(mExtras);
- dest.writeInt(mRelativeWordStartIndex);
- dest.writeInt(mRelativeWordEndIndex);
- dest.writeInt(mRelativeSuggestedWordStartIndex);
- dest.writeInt(mRelativeSuggestedWordEndIndex);
- dest.writeIntArray(mActionIndices);
- dest.writeString(mLanguage);
- dest.writeFloat(mScore);
+ dest.writeInt(mScores.length);
+ dest.writeFloatArray(mScores);
dest.writeString(mModelName);
+ dest.writeIntArray(mActionIndices);
+ dest.writeBundle(mExtras);
}
- private static TextClassifierEvent readFromParcel(Parcel in) {
- return new TextClassifierEvent(
- /* eventCategory= */ in.readInt(),
- /* eventType= */ in.readInt(),
- /* entityTypes=*/ in.readStringArray(),
- /* eventContext= */ in.readParcelable(null),
- /* resultId= */ in.readString(),
- /* eventIndex= */ in.readInt(),
- /* eventTime= */ in.readLong(),
- /* extras= */ in.readBundle(),
- /* relativeWordStartIndex= */ in.readInt(),
- /* relativeWordEndIndex= */ in.readInt(),
- /* relativeSuggestedWordStartIndex= */ in.readInt(),
- /* relativeSuggestedWordEndIndex= */ in.readInt(),
- /* actionIndices= */ in.createIntArray(),
- /* language= */ in.readString(),
- /* score= */ in.readFloat(),
- /* modelVersion= */ in.readString());
+ private int getParcelToken() {
+ if (this instanceof TextSelectionEvent) {
+ return PARCEL_TOKEN_TEXT_SELECTION_EVENT;
+ }
+ if (this instanceof TextLinkifyEvent) {
+ return PARCEL_TOKEN_TEXT_LINKIFY_EVENT;
+ }
+ if (this instanceof LanguageDetectionEvent) {
+ return PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT;
+ }
+ if (this instanceof ConversationActionsEvent) {
+ return PARCEL_TOKEN_CONVERSATION_ACTION_EVENT;
+ }
+ throw new IllegalArgumentException("Unexpected type: " + this.getClass().getSimpleName());
}
/**
@@ -241,6 +257,8 @@
/**
* Returns an array of entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
+ *
+ * @see Builder#setEntityTypes(String...) for supported types.
*/
@NonNull
public String[] getEntityTypes() {
@@ -270,13 +288,33 @@
return mEventIndex;
}
- // TODO: Remove this API.
/**
- * Returns the time this event occurred. This is the number of milliseconds since
- * January 1, 1970, 00:00:00 GMT. 0 indicates not set.
+ * Returns the scores of the suggestions.
*/
- public long getEventTime() {
- return mEventTime;
+ @NonNull
+ public float[] getScores() {
+ return mScores;
+ }
+
+ /**
+ * Returns the model name.
+ */
+ @Nullable
+ public String getModelName() {
+ return mModelName;
+ }
+
+ /**
+ * Returns the indices of the actions relating to this event.
+ * Actions are usually returned by the text classifier in priority order with the most
+ * preferred action at index 0. This list gives an indication of the position of the actions
+ * that are being reported.
+ *
+ * @see Builder#setActionIndices(int...)
+ */
+ @NonNull
+ public int[] getActionIndices() {
+ return mActionIndices;
}
/**
@@ -289,151 +327,149 @@
return mExtras;
}
- /**
- * For smart selection. Returns the relative word index of the start of the selection.
- */
- public int getRelativeWordStartIndex() {
- return mRelativeWordStartIndex;
- }
-
- /**
- * For smart selection. Returns the relative word (exclusive) index of the end of the selection.
- */
- public int getRelativeWordEndIndex() {
- return mRelativeWordEndIndex;
- }
-
- /**
- * For smart selection. Returns the relative word index of the start of the smart selection.
- */
- public int getRelativeSuggestedWordStartIndex() {
- return mRelativeSuggestedWordStartIndex;
- }
-
- /**
- * For smart selection. Returns the relative word (exclusive) index of the end of the
- * smart selection.
- */
- public int getRelativeSuggestedWordEndIndex() {
- return mRelativeSuggestedWordEndIndex;
- }
-
- /**
- * Returns the indices of the actions relating to this event.
- * Actions are usually returned by the text classifier in priority order with the most
- * preferred action at index 0. This list gives an indication of the position of the actions
- * that are being reported.
- */
- @NonNull
- public int[] getActionIndices() {
- return mActionIndices;
- }
-
- /**
- * For language detection. Returns the language tag for the detected locale.
- * @see java.util.Locale#forLanguageTag(String).
- */
- @Nullable
- public String getLanguage() {
- return mLanguage;
- }
-
- /**
- * Returns the score of the suggestion.
- */
- public float getScore() {
- return mScore;
- }
-
- /**
- * Returns the model name.
- * @hide
- */
- @Nullable
- public String getModelName() {
- return mModelName;
+ @Override
+ public String toString() {
+ StringBuilder out = new StringBuilder(128);
+ out.append(this.getClass().getSimpleName());
+ out.append("{");
+ out.append("mEventCategory=").append(mEventCategory);
+ out.append(", mEventTypes=").append(Arrays.toString(mEntityTypes));
+ out.append(", mEventContext=").append(mEventContext);
+ out.append(", mResultId=").append(mResultId);
+ out.append(", mEventIndex=").append(mEventIndex);
+ out.append(", mExtras=").append(mExtras);
+ out.append(", mScores=").append(Arrays.toString(mScores));
+ out.append(", mModelName=").append(mModelName);
+ out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
+ out.append("}");
+ return out.toString();
}
/**
* Builder to build a text classifier event.
+ *
+ * @param <T> The subclass to be built.
*/
- public static final class Builder {
+ public abstract static class Builder<T extends Builder<T>> {
private final int mEventCategory;
private final int mEventType;
private String[] mEntityTypes = new String[0];
- @Nullable private TextClassificationContext mEventContext;
- @Nullable private String mResultId;
+ @Nullable
+ private TextClassificationContext mEventContext;
+ @Nullable
+ private String mResultId;
private int mEventIndex;
- private long mEventTime;
- @Nullable private Bundle mExtras;
- private int mRelativeWordStartIndex;
- private int mRelativeWordEndIndex;
- private int mRelativeSuggestedWordStartIndex;
- private int mRelativeSuggestedWordEndIndex;
- private int[] mActionIndices = new int[0];
- @Nullable private String mLanguage;
- private float mScore;
-
+ private float[] mScores = new float[0];
+ @Nullable
private String mModelName;
+ private int[] mActionIndices = new int[0];
+ @Nullable
+ private Bundle mExtras;
/**
* Creates a builder for building {@link TextClassifierEvent}s.
*
* @param eventCategory The event category. e.g. {@link #CATEGORY_SELECTION}
- * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED}
+ * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED}
*/
- public Builder(@Category int eventCategory, @Type int eventType) {
+ private Builder(@Category int eventCategory, @Type int eventType) {
mEventCategory = eventCategory;
mEventType = eventType;
}
/**
* Sets the entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
+ * <p>
+ * Supported types:
+ * <p>See {@link TextClassifier.EntityType}
+ * <p>See {@link ConversationAction.ActionType}
+ * <p>See {@link ULocale#toLanguageTag()}
*/
@NonNull
- public Builder setEntityTypes(@NonNull String... entityTypes) {
+ public T setEntityTypes(@NonNull String... entityTypes) {
+ Preconditions.checkNotNull(entityTypes);
mEntityTypes = new String[entityTypes.length];
System.arraycopy(entityTypes, 0, mEntityTypes, 0, entityTypes.length);
- return this;
+ return self();
}
/**
* Sets the event context.
*/
@NonNull
- public Builder setEventContext(@Nullable TextClassificationContext eventContext) {
+ public T setEventContext(@Nullable TextClassificationContext eventContext) {
mEventContext = eventContext;
- return this;
+ return self();
}
/**
* Sets the id of the text classifier result related to this event.
*/
@NonNull
- public Builder setResultId(@Nullable String resultId) {
+ public T setResultId(@Nullable String resultId) {
mResultId = resultId;
- return this;
+ return self();
}
/**
- * Sets the index of this events in the series of events it belongs to.
+ * Sets the index of this event in the series of events it belongs to.
*/
@NonNull
- public Builder setEventIndex(int eventIndex) {
+ public T setEventIndex(int eventIndex) {
mEventIndex = eventIndex;
- return this;
+ return self();
}
- // TODO: Remove this API.
/**
- * Sets the time this event occurred. This is the number of milliseconds since
- * January 1, 1970, 00:00:00 GMT. 0 indicates not set.
+ * Sets the scores of the suggestions.
*/
@NonNull
- public Builder setEventTime(long eventTime) {
- mEventTime = eventTime;
- return this;
+ public T setScores(@NonNull float... scores) {
+ Preconditions.checkNotNull(scores);
+ mScores = new float[scores.length];
+ System.arraycopy(scores, 0, mScores, 0, scores.length);
+ return self();
+ }
+
+ /**
+ * Sets the model name string.
+ */
+ @NonNull
+ public T setModelName(@Nullable String modelVersion) {
+ mModelName = modelVersion;
+ return self();
+ }
+
+ /**
+ * Sets the indices of the actions involved in this event. Actions are usually returned by
+ * the text classifier in priority order with the most preferred action at index 0.
+ * These indices give an indication of the position of the actions that are being reported.
+ * <p>
+ * E.g.
+ * <pre>
+ * // 3 smart actions are shown at index 0, 1, 2 respectively in response to a link click.
+ * new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_ACTIONS_SHOWN)
+ * .setEventIndex(0, 1, 2)
+ * ...
+ * .build();
+ *
+ * ...
+ *
+ * // Smart action at index 1 is activated.
+ * new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_SMART_ACTION)
+ * .setEventIndex(1)
+ * ...
+ * .build();
+ * </pre>
+ *
+ * @see TextClassification#getActions()
+ */
+ @NonNull
+ public T setActionIndices(@NonNull int... actionIndices) {
+ mActionIndices = new int[actionIndices.length];
+ System.arraycopy(actionIndices, 0, mActionIndices, 0, actionIndices.length);
+ return self();
}
/**
@@ -445,136 +481,545 @@
* objects in this bundle.
*/
@NonNull
- public Builder setExtras(@NonNull Bundle extras) {
+ public T setExtras(@NonNull Bundle extras) {
mExtras = Preconditions.checkNotNull(extras);
- return this;
+ return self();
}
- /**
- * For smart selection. Sets the relative word index of the start of the selection.
- */
- @NonNull
- public Builder setRelativeWordStartIndex(int relativeWordStartIndex) {
- mRelativeWordStartIndex = relativeWordStartIndex;
- return this;
- }
-
- /**
- * For smart selection. Sets the relative word (exclusive) index of the end of the
- * selection.
- */
- @NonNull
- public Builder setRelativeWordEndIndex(int relativeWordEndIndex) {
- mRelativeWordEndIndex = relativeWordEndIndex;
- return this;
- }
-
- /**
- * For smart selection. Sets the relative word index of the start of the smart selection.
- */
- @NonNull
- public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) {
- mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
- return this;
- }
-
- /**
- * For smart selection. Sets the relative word (exclusive) index of the end of the
- * smart selection.
- */
- @NonNull
- public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) {
- mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
- return this;
- }
-
- /**
- * Sets the indices of the actions involved in this event. Actions are usually returned by
- * the text classifier in priority order with the most preferred action at index 0.
- * This index gives an indication of the position of the action that is being reported.
- */
- @NonNull
- public Builder setActionIndices(@NonNull int... actionIndices) {
- mActionIndices = new int[actionIndices.length];
- System.arraycopy(actionIndices, 0, mActionIndices, 0, actionIndices.length);
- return this;
- }
-
- /**
- * For language detection. Sets the language tag for the detected locale.
- * @see java.util.Locale#forLanguageTag(String).
- */
- @NonNull
- public Builder setLanguage(@Nullable String language) {
- mLanguage = language;
- return this;
- }
-
- /**
- * Sets the score of the suggestion.
- */
- @NonNull
- public Builder setScore(float score) {
- mScore = score;
- return this;
- }
-
- /**
- * Sets the model name string.
- * @hide
- */
- public Builder setModelName(@Nullable String modelVersion) {
- mModelName = modelVersion;
- return this;
- }
-
- /**
- * Builds and returns a text classifier event.
- */
- @NonNull
- public TextClassifierEvent build() {
- mExtras = mExtras == null ? Bundle.EMPTY : mExtras;
- return new TextClassifierEvent(
- mEventCategory,
- mEventType,
- mEntityTypes,
- mEventContext,
- mResultId,
- mEventIndex,
- mEventTime,
- mExtras,
- mRelativeWordStartIndex,
- mRelativeWordEndIndex,
- mRelativeSuggestedWordStartIndex,
- mRelativeSuggestedWordEndIndex,
- mActionIndices,
- mLanguage,
- mScore,
- mModelName);
- }
- // TODO: Add build(boolean validate).
+ abstract T self();
}
- @Override
- public String toString() {
- StringBuilder out = new StringBuilder(128);
- out.append("TextClassifierEvent{");
- out.append("mEventCategory=").append(mEventCategory);
- out.append(", mEventTypes=").append(Arrays.toString(mEntityTypes));
- out.append(", mEventContext=").append(mEventContext);
- out.append(", mResultId=").append(mResultId);
- out.append(", mEventIndex=").append(mEventIndex);
- out.append(", mEventTime=").append(mEventTime);
- out.append(", mExtras=").append(mExtras);
- out.append(", mRelativeWordStartIndex=").append(mRelativeWordStartIndex);
- out.append(", mRelativeWordEndIndex=").append(mRelativeWordEndIndex);
- out.append(", mRelativeSuggestedWordStartIndex=").append(mRelativeSuggestedWordStartIndex);
- out.append(", mRelativeSuggestedWordEndIndex=").append(mRelativeSuggestedWordEndIndex);
- out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
- out.append(", mLanguage=").append(mLanguage);
- out.append(", mScore=").append(mScore);
- out.append(", mModelName=").append(mModelName);
- out.append("}");
- return out.toString();
+ /**
+ * This class represents events that are related to the smart text selection feature.
+ * <p>
+ * <pre>
+ * // User started a selection. e.g. "York" in text "New York City, NY".
+ * new TextSelectionEvent.Builder(TYPE_SELECTION_STARTED)
+ * .setEventContext(classificationContext)
+ * .setEventIndex(0)
+ * .build();
+ *
+ * // System smart-selects a recognized entity. e.g. "New York City".
+ * new TextSelectionEvent.Builder(TYPE_SMART_SELECTION_MULTI)
+ * .setEventContext(classificationContext)
+ * .setResultId(textSelection.getId())
+ * .setRelativeWordStartIndex(-1) // Goes back one word to "New" from "York".
+ * .setRelativeWordEndIndex(2) // Goes forward 2 words from "York" to start of ",".
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(1)
+ * .build();
+ *
+ * // User resets the selection to the original selection. i.e. "York".
+ * new TextSelectionEvent.Builder(TYPE_SELECTION_RESET)
+ * .setEventContext(classificationContext)
+ * .setResultId(textSelection.getId())
+ * .setRelativeSuggestedWordStartIndex(-1) // Repeated from above.
+ * .setRelativeSuggestedWordEndIndex(2) // Repeated from above.
+ * .setRelativeWordStartIndex(0) // Original selection is always at (0, 1].
+ * .setRelativeWordEndIndex(1)
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(2)
+ * .build();
+ *
+ * // User modified the selection. e.g. "New".
+ * new TextSelectionEvent.Builder(TYPE_SELECTION_MODIFIED)
+ * .setEventContext(classificationContext)
+ * .setResultId(textSelection.getId())
+ * .setRelativeSuggestedWordStartIndex(-1) // Repeated from above.
+ * .setRelativeSuggestedWordEndIndex(2) // Repeated from above.
+ * .setRelativeWordStartIndex(-1) // Goes backward one word from "York" to
+ * "New".
+ * .setRelativeWordEndIndex(0) // Goes backward one word to exclude "York".
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(3)
+ * .build();
+ *
+ * // Smart (contextual) actions (at indices, 0, 1, 2) presented to the user.
+ * // e.g. "Map", "Ride share", "Explore".
+ * new TextSelectionEvent.Builder(TYPE_ACTIONS_SHOWN)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setActionIndices(0, 1, 2)
+ * .setEventIndex(4)
+ * .build();
+ *
+ * // User chooses the "Copy" action.
+ * new TextSelectionEvent.Builder(TYPE_COPY_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(5)
+ * .build();
+ *
+ * // User chooses smart action at index 1. i.e. "Ride share".
+ * new TextSelectionEvent.Builder(TYPE_SMART_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setActionIndices(1)
+ * .setEventIndex(5)
+ * .build();
+ *
+ * // Selection dismissed.
+ * new TextSelectionEvent.Builder(TYPE_SELECTION_DESTROYED)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(6)
+ * .build();
+ * </pre>
+ * <p>
+ */
+ public static final class TextSelectionEvent extends TextClassifierEvent implements Parcelable {
+
+ @NonNull
+ public static final Creator<TextSelectionEvent> CREATOR =
+ new Creator<TextSelectionEvent>() {
+ @Override
+ public TextSelectionEvent createFromParcel(Parcel in) {
+ in.readInt(); // skip token, we already know this is a TextSelectionEvent
+ return new TextSelectionEvent(in);
+ }
+
+ @Override
+ public TextSelectionEvent[] newArray(int size) {
+ return new TextSelectionEvent[size];
+ }
+ };
+
+ final int mRelativeWordStartIndex;
+ final int mRelativeWordEndIndex;
+ final int mRelativeSuggestedWordStartIndex;
+ final int mRelativeSuggestedWordEndIndex;
+
+ private TextSelectionEvent(TextSelectionEvent.Builder builder) {
+ super(builder);
+ mRelativeWordStartIndex = builder.mRelativeWordStartIndex;
+ mRelativeWordEndIndex = builder.mRelativeWordEndIndex;
+ mRelativeSuggestedWordStartIndex = builder.mRelativeSuggestedWordStartIndex;
+ mRelativeSuggestedWordEndIndex = builder.mRelativeSuggestedWordEndIndex;
+ }
+
+ private TextSelectionEvent(Parcel in) {
+ super(in);
+ mRelativeWordStartIndex = in.readInt();
+ mRelativeWordEndIndex = in.readInt();
+ mRelativeSuggestedWordStartIndex = in.readInt();
+ mRelativeSuggestedWordEndIndex = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mRelativeWordStartIndex);
+ dest.writeInt(mRelativeWordEndIndex);
+ dest.writeInt(mRelativeSuggestedWordStartIndex);
+ dest.writeInt(mRelativeSuggestedWordEndIndex);
+ }
+
+ /**
+ * Returns the relative word index of the start of the selection.
+ */
+ public int getRelativeWordStartIndex() {
+ return mRelativeWordStartIndex;
+ }
+
+ /**
+ * Returns the relative word (exclusive) index of the end of the selection.
+ */
+ public int getRelativeWordEndIndex() {
+ return mRelativeWordEndIndex;
+ }
+
+ /**
+ * Returns the relative word index of the start of the smart selection.
+ */
+ public int getRelativeSuggestedWordStartIndex() {
+ return mRelativeSuggestedWordStartIndex;
+ }
+
+ /**
+ * Returns the relative word (exclusive) index of the end of the
+ * smart selection.
+ */
+ public int getRelativeSuggestedWordEndIndex() {
+ return mRelativeSuggestedWordEndIndex;
+ }
+
+ /**
+ * Builder class for {@link TextSelectionEvent}.
+ */
+ public static final class Builder extends
+ TextClassifierEvent.Builder<TextSelectionEvent.Builder> {
+ int mRelativeWordStartIndex;
+ int mRelativeWordEndIndex;
+ int mRelativeSuggestedWordStartIndex;
+ int mRelativeSuggestedWordEndIndex;
+
+ /**
+ * Creates a builder for building {@link TextSelectionEvent}s.
+ *
+ * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED}
+ */
+ public Builder(@Type int eventType) {
+ super(CATEGORY_SELECTION, eventType);
+ }
+
+ /**
+ * Sets the relative word index of the start of the selection.
+ */
+ @NonNull
+ public Builder setRelativeWordStartIndex(int relativeWordStartIndex) {
+ mRelativeWordStartIndex = relativeWordStartIndex;
+ return this;
+ }
+
+ /**
+ * Sets the relative word (exclusive) index of the end of the
+ * selection.
+ */
+ @NonNull
+ public Builder setRelativeWordEndIndex(int relativeWordEndIndex) {
+ mRelativeWordEndIndex = relativeWordEndIndex;
+ return this;
+ }
+
+ /**
+ * Sets the relative word index of the start of the smart
+ * selection.
+ */
+ @NonNull
+ public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) {
+ mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
+ return this;
+ }
+
+ /**
+ * Sets the relative word (exclusive) index of the end of the
+ * smart selection.
+ */
+ @NonNull
+ public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) {
+ mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
+ return this;
+ }
+
+ @Override
+ TextSelectionEvent.Builder self() {
+ return this;
+ }
+
+ /**
+ * Builds and returns a {@link TextSelectionEvent}.
+ */
+ @NonNull
+ public TextSelectionEvent build() {
+ return new TextSelectionEvent(this);
+ }
+ }
+ }
+
+ /**
+ * This class represents events that are related to the smart linkify feature.
+ * <p>
+ * <pre>
+ * // User clicked on a link.
+ * new TextLinkifyEvent.Builder(TYPE_LINK_CLICKED)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(0)
+ * .build();
+ *
+ * // Smart (contextual) actions presented to the user in response to a link click.
+ * new TextLinkifyEvent.Builder(TYPE_ACTIONS_SHOWN)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setActionIndices(range(textClassification.getActions().size()))
+ * .setEventIndex(1)
+ * .build();
+ *
+ * // User chooses smart action at index 0.
+ * new TextLinkifyEvent.Builder(TYPE_SMART_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setActionIndices(0)
+ * .setEventIndex(2)
+ * .build();
+ * </pre>
+ */
+ public static final class TextLinkifyEvent extends TextClassifierEvent implements Parcelable {
+
+ @NonNull
+ public static final Creator<TextLinkifyEvent> CREATOR =
+ new Creator<TextLinkifyEvent>() {
+ @Override
+ public TextLinkifyEvent createFromParcel(Parcel in) {
+ in.readInt(); // skip token, we already know this is a TextLinkifyEvent
+ return new TextLinkifyEvent(in);
+ }
+
+ @Override
+ public TextLinkifyEvent[] newArray(int size) {
+ return new TextLinkifyEvent[size];
+ }
+ };
+
+ private TextLinkifyEvent(Parcel in) {
+ super(in);
+ }
+
+ private TextLinkifyEvent(TextLinkifyEvent.Builder builder) {
+ super(builder);
+ }
+
+ /**
+ * Builder class for {@link TextLinkifyEvent}.
+ */
+ public static final class Builder
+ extends TextClassifierEvent.Builder<TextLinkifyEvent.Builder> {
+ /**
+ * Creates a builder for building {@link TextLinkifyEvent}s.
+ *
+ * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+ */
+ public Builder(@Type int eventType) {
+ super(TextClassifierEvent.CATEGORY_LINKIFY, eventType);
+ }
+
+ @Override
+ Builder self() {
+ return this;
+ }
+
+ /**
+ * Builds and returns a {@link TextLinkifyEvent}.
+ */
+ @NonNull
+ public TextLinkifyEvent build() {
+ return new TextLinkifyEvent(this);
+ }
+ }
+ }
+
+ /**
+ * This class represents events that are related to the language detection feature.
+ * <p>
+ * <pre>
+ * // Translate action shown for foreign text.
+ * new LanguageDetectionEvent.Builder(TYPE_ACTIONS_SHOWN)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(language)
+ * .setScore(score)
+ * .setActionIndices(textClassification.getActions().indexOf(translateAction))
+ * .setEventIndex(0)
+ * .build();
+ *
+ * // Translate action selected.
+ * new LanguageDetectionEvent.Builder(TYPE_SMART_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(language)
+ * .setScore(score)
+ * .setActionIndices(textClassification.getActions().indexOf(translateAction))
+ * .setEventIndex(1)
+ * .build();
+ */
+ public static final class LanguageDetectionEvent extends TextClassifierEvent
+ implements Parcelable {
+
+ @NonNull
+ public static final Creator<LanguageDetectionEvent> CREATOR =
+ new Creator<LanguageDetectionEvent>() {
+ @Override
+ public LanguageDetectionEvent createFromParcel(Parcel in) {
+ // skip token, we already know this is a LanguageDetectionEvent.
+ in.readInt();
+ return new LanguageDetectionEvent(in);
+ }
+
+ @Override
+ public LanguageDetectionEvent[] newArray(int size) {
+ return new LanguageDetectionEvent[size];
+ }
+ };
+
+ @Nullable
+ private final ULocale mLocale;
+
+ private LanguageDetectionEvent(Parcel in) {
+ super(in);
+ final String languageTag = in.readString();
+ mLocale = languageTag == null ? null : ULocale.forLanguageTag(languageTag);
+ }
+
+ private LanguageDetectionEvent(LanguageDetectionEvent.Builder builder) {
+ super(builder);
+ mLocale = builder.mLocale;
+ }
+
+ /**
+ * Returns the detected locale.
+ */
+ @Nullable
+ public ULocale getLocale() {
+ return mLocale;
+ }
+
+ /**
+ * Builder class for {@link LanguageDetectionEvent}.
+ */
+ public static final class Builder
+ extends TextClassifierEvent.Builder<LanguageDetectionEvent.Builder> {
+ @Nullable
+ private ULocale mLocale;
+
+ /**
+ * Creates a builder for building {@link TextSelectionEvent}s.
+ *
+ * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+ */
+ public Builder(@Type int eventType) {
+ super(TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType);
+ }
+
+ /**
+ * Sets the detected locale.
+ */
+ @NonNull
+ public Builder setLocale(@Nullable ULocale locale) {
+ mLocale = locale;
+ return this;
+ }
+
+ @Override
+ Builder self() {
+ return this;
+ }
+
+ /**
+ * Builds and returns a {@link LanguageDetectionEvent}.
+ */
+ @NonNull
+ public LanguageDetectionEvent build() {
+ return new LanguageDetectionEvent(this);
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(mLocale == null ? null : mLocale.toLanguageTag());
+ }
+ }
+
+ /**
+ * This class represents events that are related to the conversation actions feature.
+ * <p>
+ * <pre>
+ * // Conversation (contextual) actions/replies generated.
+ * new ConversationActionsEvent.Builder(TYPE_ACTIONS_GENERATED)
+ * .setEventContext(classificationContext)
+ * .setResultId(conversationActions.getId())
+ * .setEntityTypes(getTypes(conversationActions))
+ * .setActionIndices(range(conversationActions.getActions().size()))
+ * .setEventIndex(0)
+ * .build();
+ *
+ * // Conversation actions/replies presented to user.
+ * new ConversationActionsEvent.Builder(TYPE_ACTIONS_SHOWN)
+ * .setEventContext(classificationContext)
+ * .setResultId(conversationActions.getId())
+ * .setEntityTypes(getTypes(conversationActions))
+ * .setActionIndices(range(conversationActions.getActions().size()))
+ * .setEventIndex(1)
+ * .build();
+ *
+ * // User clicked the "Reply" button to compose their custom reply.
+ * new ConversationActionsEvent.Builder(TYPE_MANUAL_REPLY)
+ * .setEventContext(classificationContext)
+ * .setResultId(conversationActions.getId())
+ * .setEventIndex(2)
+ * .build();
+ *
+ * // User selected a smart (contextual) action/reply.
+ * new ConversationActionsEvent.Builder(TYPE_SMART_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(conversationActions.getId())
+ * .setEntityTypes(conversationActions.get(1).getType())
+ * .setScore(conversationAction.get(1).getConfidenceScore())
+ * .setActionIndices(1)
+ * .setEventIndex(2)
+ * .build();
+ * </pre>
+ */
+ public static final class ConversationActionsEvent extends TextClassifierEvent
+ implements Parcelable {
+
+ @NonNull
+ public static final Creator<ConversationActionsEvent> CREATOR =
+ new Creator<ConversationActionsEvent>() {
+ @Override
+ public ConversationActionsEvent createFromParcel(Parcel in) {
+ // skip token, we already know this is a ConversationActionsEvent.
+ in.readInt();
+ return new ConversationActionsEvent(in);
+ }
+
+ @Override
+ public ConversationActionsEvent[] newArray(int size) {
+ return new ConversationActionsEvent[size];
+ }
+ };
+
+ private ConversationActionsEvent(Parcel in) {
+ super(in);
+ }
+
+ private ConversationActionsEvent(ConversationActionsEvent.Builder builder) {
+ super(builder);
+ }
+
+ /**
+ * Builder class for {@link ConversationActionsEvent}.
+ */
+ public static final class Builder
+ extends TextClassifierEvent.Builder<ConversationActionsEvent.Builder> {
+ /**
+ * Creates a builder for building {@link TextSelectionEvent}s.
+ *
+ * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+ */
+ public Builder(@Type int eventType) {
+ super(TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType);
+ }
+
+ @Override
+ Builder self() {
+ return this;
+ }
+
+ /**
+ * Builds and returns a {@link ConversationActionsEvent}.
+ */
+ @NonNull
+ public ConversationActionsEvent build() {
+ return new ConversationActionsEvent(this);
+ }
+ }
}
}
diff --git a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
index 6a12250..3e088b8 100644
--- a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
+++ b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
@@ -65,9 +65,10 @@
final LogMaker log = new LogMaker(category)
.setSubtype(getLogType(event))
.addTaggedData(FIELD_TEXT_CLASSIFIER_SESSION_ID, event.getResultId())
- .addTaggedData(FIELD_TEXTCLASSIFIER_MODEL, getModelName(event))
- .addTaggedData(FIELD_TEXT_CLASSIFIER_SCORE, event.getScore());
-
+ .addTaggedData(FIELD_TEXTCLASSIFIER_MODEL, getModelName(event));
+ if (event.getScores().length >= 1) {
+ log.addTaggedData(FIELD_TEXT_CLASSIFIER_SCORE, event.getScores()[0]);
+ }
String[] entityTypes = event.getEntityTypes();
// The old logger does not support a field of list type, and thus workaround by store them
// in three separate fields. This is not an issue with the new logger.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 323bf59..3297523 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -307,6 +307,8 @@
final String detectLanguageTags = detectLanguageTagsFromText(request.getText());
final AnnotatorModel annotatorImpl =
getAnnotatorImpl(request.getDefaultLocales());
+ final boolean isSerializedEntityDataEnabled =
+ ExtrasUtils.isSerializedEntityDataEnabled(request);
final AnnotatorModel.AnnotatedSpan[] annotations =
annotatorImpl.annotate(
textString,
@@ -314,7 +316,10 @@
refTime.toInstant().toEpochMilli(),
refTime.getZone().getId(),
localesString,
- detectLanguageTags));
+ detectLanguageTags,
+ entitiesToIdentify,
+ AnnotatorModel.AnnotationUsecase.SMART.getValue(),
+ isSerializedEntityDataEnabled));
for (AnnotatorModel.AnnotatedSpan span : annotations) {
final AnnotatorModel.ClassificationResult[] results =
span.getClassification();
@@ -326,7 +331,11 @@
for (int i = 0; i < results.length; i++) {
entityScores.put(results[i].getCollection(), results[i].getScore());
}
- builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores);
+ Bundle extras = new Bundle();
+ if (isSerializedEntityDataEnabled) {
+ ExtrasUtils.putEntities(extras, results);
+ }
+ builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores, extras);
}
final TextLinks links = builder.build();
final long endTimeMs = System.currentTimeMillis();
@@ -451,10 +460,6 @@
Collection<String> expectedTypes = resolveActionTypesFromRequest(request);
List<ConversationAction> conversationActions = new ArrayList<>();
for (ActionsSuggestionsModel.ActionSuggestion nativeSuggestion : nativeSuggestions) {
- if (request.getMaxSuggestions() >= 0
- && conversationActions.size() == request.getMaxSuggestions()) {
- break;
- }
String actionType = nativeSuggestion.getActionType();
if (!expectedTypes.contains(actionType)) {
continue;
@@ -484,6 +489,10 @@
}
conversationActions =
ActionsSuggestionsHelper.removeActionsWithDuplicates(conversationActions);
+ if (request.getMaxSuggestions() >= 0
+ && conversationActions.size() > request.getMaxSuggestions()) {
+ conversationActions = conversationActions.subList(0, request.getMaxSuggestions());
+ }
String resultId = ActionsSuggestionsHelper.createResultId(
mContext,
request.getConversation(),
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 26dba45..137b67c 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -413,9 +413,6 @@
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
- if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
- setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
- }
if (context == null) {
throw new IllegalArgumentException("Invalid context argument");
@@ -2799,11 +2796,6 @@
}
@Override
- public void onProvideContentCaptureStructure(ViewStructure structure, int flags) {
- mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags);
- }
-
- @Override
public void autofill(SparseArray<AutofillValue>values) {
mProvider.getViewDelegate().autofill(values);
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index c55f7d6..c3bb9a0 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1318,8 +1318,7 @@
@ViewStructureType int viewFor, int flags) {
super.onProvideStructure(structure, viewFor, flags);
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
final Adapter adapter = getAdapter();
if (adapter == null) return;
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 564cfdd..51ca805 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -933,12 +933,11 @@
final String language = ExtrasUtils.getEntityType(foreignLanguageExtra);
final float score = ExtrasUtils.getScore(foreignLanguageExtra);
final String model = ExtrasUtils.getModelName(foreignLanguageExtra);
- return new TextClassifierEvent.Builder(
- TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType)
+ return new TextClassifierEvent.LanguageDetectionEvent.Builder(eventType)
.setEventContext(classificationContext)
.setResultId(classification.getId())
.setEntityTypes(language)
- .setScore(score)
+ .setScores(score)
.setActionIndices(classification.getActions().indexOf(translateAction))
.setModelName(model)
.build();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a961783..618b05f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -161,8 +161,6 @@
import android.view.animation.AnimationUtils;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
-import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureSession;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -978,9 +976,6 @@
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
- if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
- setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
- }
setTextInternal("");
@@ -10520,8 +10515,7 @@
}
/**
- * Notify managers (such as {@link AutofillManager} and {@link ContentCaptureManager}) that are
- * interested on text changes.
+ * Notify managers (such as {@link AutofillManager}) that are interested in text changes.
*/
private void notifyListeningManagersAfterTextChanged() {
@@ -10537,22 +10531,6 @@
afm.notifyValueChanged(TextView.this);
}
}
-
- // TODO(b/121045053): should use a flag / boolean to keep status of SHOWN / HIDDEN instead
- // of using isLaidout(), so it's not called in cases where it's laid out but a
- // notifyAppeared was not sent.
-
- // ContentCapture
- if (isLaidOut() && isImportantForContentCapture() && isTextEditable()) {
- final ContentCaptureManager cm = mContext.getSystemService(ContentCaptureManager.class);
- if (cm != null && cm.isContentCaptureEnabled()) {
- final ContentCaptureSession session = getContentCaptureSession();
- if (session != null) {
- // TODO(b/111276913): pass flags when edited by user / add CTS test
- session.notifyViewTextChanged(getAutofillId(), getText());
- }
- }
- }
}
private boolean isAutofillable() {
@@ -11386,8 +11364,7 @@
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
}
@@ -11403,12 +11380,8 @@
}
}
- if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
if (mLayout == null) {
- if (viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
- Log.w(LOG_TAG, "onProvideContentCaptureStructure(): calling assumeLayout()");
- }
assumeLayout();
}
Layout layout = mLayout;
@@ -11496,8 +11469,7 @@
}
}
- if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
// Extract style information that applies to the TextView as a whole.
int style = 0;
int typefaceStyle = getTypefaceStyle();
@@ -11525,8 +11497,7 @@
structure.setTextStyle(getTextSize(), getCurrentTextColor(),
AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
}
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setMinTextEms(getMinEms());
structure.setMaxTextEms(getMaxEms());
int maxLength = -1;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index b8ac6dc..54338bf 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -84,6 +84,7 @@
import android.service.chooser.ChooserTargetService;
import android.service.chooser.IChooserTargetResult;
import android.service.chooser.IChooserTargetService;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.HashedStringCache;
@@ -1349,13 +1350,13 @@
appPredictor.notifyAppTargetEvent(
new AppTargetEvent.Builder(
// TODO(b/124404997) Send full shortcut info, not just Id with AppTargetId.
- new AppTarget.Builder(new AppTargetId(shortcutId))
- .setTarget(componentName.getPackageName(), getUser())
+ new AppTarget.Builder(new AppTargetId(shortcutId),
+ componentName.getPackageName(), getUser())
.setClassName(componentName.getClassName())
.build(),
- AppTargetEvent.ACTION_LAUNCH
- ).setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
- .build());
+ AppTargetEvent.ACTION_LAUNCH)
+ .setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
+ .build());
}
@Nullable
@@ -1546,6 +1547,29 @@
float getModifiedScore();
ChooserTarget getChooserTarget();
+
+ /**
+ * Do not label as 'equals', since this doesn't quite work
+ * as intended with java 8.
+ */
+ default boolean isSimilar(ChooserTargetInfo other) {
+ if (other == null) return false;
+
+ ChooserTarget ct1 = getChooserTarget();
+ ChooserTarget ct2 = other.getChooserTarget();
+
+ // If either is null, there is not enough info to make an informed decision
+ // about equality, so just exit
+ if (ct1 == null || ct2 == null) return false;
+
+ if (ct1.getComponentName().equals(ct2.getComponentName())
+ && TextUtils.equals(getDisplayLabel(), other.getDisplayLabel())
+ && TextUtils.equals(getExtendedInfo(), other.getExtendedInfo())) {
+ return true;
+ }
+
+ return false;
+ }
}
/**
@@ -1624,6 +1648,7 @@
private final DisplayResolveInfo mSourceInfo;
private final ResolveInfo mBackupResolveInfo;
private final ChooserTarget mChooserTarget;
+ private final String mDisplayLabel;
private Drawable mBadgeIcon = null;
private CharSequence mBadgeContentDescription;
private Drawable mDisplayIcon;
@@ -1661,6 +1686,8 @@
mFillInIntent = null;
mFillInFlags = 0;
+
+ mDisplayLabel = sanitizeDisplayLabel(chooserTarget.getTitle());
}
private SelectableTargetInfo(SelectableTargetInfo other, Intent fillInIntent, int flags) {
@@ -1673,6 +1700,14 @@
mFillInIntent = fillInIntent;
mFillInFlags = flags;
mModifiedScore = other.mModifiedScore;
+
+ mDisplayLabel = sanitizeDisplayLabel(mChooserTarget.getTitle());
+ }
+
+ private String sanitizeDisplayLabel(CharSequence label) {
+ SpannableStringBuilder sb = new SpannableStringBuilder(label);
+ sb.clearSpans();
+ return sb.toString();
}
public boolean isSuspended() {
@@ -1811,7 +1846,7 @@
@Override
public CharSequence getDisplayLabel() {
- return mChooserTarget.getTitle();
+ return mDisplayLabel;
}
@Override
@@ -2229,8 +2264,6 @@
final float baseScore = getBaseScore(origTarget, isShortcutResult);
Collections.sort(targets, mBaseTargetComparator);
-
-
float lastScore = 0;
boolean shouldNotify = false;
for (int i = 0, N = Math.min(targets.size(), MAX_TARGETS_PER_SERVICE); i < N; i++) {
@@ -2305,8 +2338,15 @@
return false;
}
- final float newScore = chooserTargetInfo.getModifiedScore();
+ // Check for duplicates and abort if found
+ for (ChooserTargetInfo otherTargetInfo : mServiceTargets) {
+ if (chooserTargetInfo.isSimilar(otherTargetInfo)) {
+ return false;
+ }
+ }
+
int currentSize = mServiceTargets.size();
+ final float newScore = chooserTargetInfo.getModifiedScore();
for (int i = 0; i < Math.min(currentSize, MAX_SERVICE_TARGETS); i++) {
final ChooserTargetInfo serviceTarget = mServiceTargets.get(i);
if (serviceTarget == null) {
@@ -2393,15 +2433,11 @@
* @return true if the view width has changed
*/
public boolean calculateChooserTargetWidth(int width) {
- int targetMinWidth = getResources().getDimensionPixelSize(
- R.dimen.chooser_target_width);
-
if (width == 0) {
return false;
}
- int targetWidth = width / getMaxTargetsPerRow();
- int newWidth = Math.max(targetWidth, targetMinWidth);
+ int newWidth = width / getMaxTargetsPerRow();
if (newWidth != mChooserTargetWidth) {
mChooserTargetWidth = newWidth;
return true;
@@ -2622,12 +2658,24 @@
}
}
+ /**
+ * Need to merge CALLER + ranked STANDARD into a single row. All other types
+ * are placed into their own row as determined by their target type, and dividers
+ * are added in the list to separate each type.
+ */
+ int getRowType(int rowPosition) {
+ int positionType = mChooserListAdapter.getPositionTargetType(rowPosition);
+ if (positionType == ChooserListAdapter.TARGET_CALLER) {
+ return ChooserListAdapter.TARGET_STANDARD;
+ }
+
+ return positionType;
+ }
+
void bindViewHolder(int rowPosition, RowViewHolder holder) {
final int start = getFirstRowPosition(rowPosition);
- final int startType = mChooserListAdapter.getPositionTargetType(start);
-
- final int lastStartType = mChooserListAdapter.getPositionTargetType(
- getFirstRowPosition(rowPosition - 1));
+ final int startType = getRowType(start);
+ final int lastStartType = getRowType(getFirstRowPosition(rowPosition - 1));
final ViewGroup row = holder.getViewGroup();
@@ -2639,7 +2687,7 @@
int columnCount = holder.getColumnCount();
int end = start + columnCount - 1;
- while (mChooserListAdapter.getPositionTargetType(end) != startType && end >= start) {
+ while (getRowType(end) != startType && end >= start) {
end--;
}
@@ -2691,14 +2739,15 @@
return row * getMaxTargetsPerRow();
}
- final int callerCount = mChooserListAdapter.getCallerTargetCount();
- final int callerRows = (int) Math.ceil((float) callerCount / getMaxTargetsPerRow());
- if (row < callerRows + serviceRows) {
+ final int callerAndRankedCount = mChooserListAdapter.getCallerTargetCount()
+ + mChooserListAdapter.getRankedTargetCount();
+ final int callerAndRankedRows = getCallerAndRankedTargetRowCount();
+ if (row < callerAndRankedRows + serviceRows) {
return serviceCount + (row - serviceRows) * getMaxTargetsPerRow();
}
- return callerCount + serviceCount
- + (row - callerRows - serviceRows) * getMaxTargetsPerRow();
+ return callerAndRankedCount + serviceCount
+ + (row - callerAndRankedRows - serviceRows) * getMaxTargetsPerRow();
}
public void handleScroll(View v, int y, int oldy) {
diff --git a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
index 69d9ccc..b5f2147 100644
--- a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
@@ -31,4 +31,5 @@
in IMultiClientInputMethodSession multiClientSession, in InputChannel writeChannel);
void reportImeWindowTarget(int clientId, int targetWindowHandle, in IBinder imeWindowToken);
boolean isUidAllowedOnDisplay(int displayId, int uid);
+ void setActive(int clientId, boolean active);
}
diff --git a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
index 9220117..1cf6887 100644
--- a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
@@ -212,4 +212,21 @@
}
}
+ /**
+ * Calls {@link IMultiClientInputMethodPrivilegedOperations#setActive(int, boolean)}.
+ * @param clientId client ID to be set active/inactive
+ * @param active {@code true} set set active.
+ */
+ @AnyThread
+ public void setActive(int clientId, boolean active) {
+ final IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+ if (ops == null) {
+ return;
+ }
+ try {
+ ops.setActive(clientId, active);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index fd75f4f..21f8d87 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -45,6 +45,7 @@
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Color;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaController;
@@ -115,6 +116,7 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.List;
/**
* Android-specific Window.
@@ -3926,4 +3928,15 @@
public WindowInsetsController getInsetsController() {
return mDecor.getWindowInsetsController();
}
+
+ @Override
+ public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ getViewRootImpl().setRootSystemGestureExclusionRects(rects);
+ }
+
+ @Override
+ @NonNull
+ public List<Rect> getSystemGestureExclusionRects() {
+ return getViewRootImpl().getRootSystemGestureExclusionRects();
+ }
}
diff --git a/core/java/com/android/internal/util/TrafficStatsConstants.java b/core/java/com/android/internal/util/TrafficStatsConstants.java
new file mode 100644
index 0000000..2806ae2
--- /dev/null
+++ b/core/java/com/android/internal/util/TrafficStatsConstants.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+/**
+ * Constants for traffic stats.
+ * @hide
+ */
+public class TrafficStatsConstants {
+ // These tags are used by the network stack to do traffic for its own purposes. Traffic
+ // tagged with these will be counted toward the network stack and must stay inside the
+ // range defined by
+ // {@link android.net.TrafficStats#TAG_NETWORK_STACK_RANGE_START} and
+ // {@link android.net.TrafficStats#TAG_NETWORK_STACK_RANGE_END}.
+ public static final int TAG_SYSTEM_DHCP = 0xFFFFFE01;
+ public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFE02;
+ public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFE03;
+
+ public static final int TAG_SYSTEM_NTP = 0xFFFFFF41;
+ public static final int TAG_SYSTEM_GPS = 0xFFFFFF44;
+ public static final int TAG_SYSTEM_PAC = 0xFFFFFF45;
+
+ // These tags are used by the network stack to do traffic on behalf of apps. Traffic
+ // tagged with these will be counted toward the app on behalf of which the network
+ // stack is doing this traffic. These values must stay inside the range defined by
+ // {@link android.net.TrafficStats#TAG_NETWORK_STACK_IMPERSONATION_RANGE_START} and
+ // {@link android.net.TrafficStats#TAG_NETWORK_STACK_IMPERSONATION_RANGE_END}.
+ public static final int TAG_SYSTEM_PROBE = 0xFFFFFF81;
+}
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp
index 19a1c72..1e6d49e 100644
--- a/core/jni/android_nio_utils.cpp
+++ b/core/jni/android_nio_utils.cpp
@@ -18,42 +18,29 @@
#include "core_jni_helpers.h"
-void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) {
- assert(array);
+namespace android {
- jint position;
- jint limit;
- jint elementSizeShift;
- jlong pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
+AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit)
+ : fEnv(env), fCommit(commit) {
+ jlong pointer = jniGetNioBufferPointer(fEnv, nioBuffer);
if (pointer != 0L) {
- pointer += position << elementSizeShift;
- return reinterpret_cast<void*>(pointer);
- }
-
- jint offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
- *array = jniGetNioBufferBaseArray(_env, buffer);
- void * data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
- return reinterpret_cast<void*>(reinterpret_cast<char*>(data) + offset);
-}
-
-
-void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data,
- jboolean commit) {
- _env->ReleasePrimitiveArrayCritical(array, data,
- commit ? 0 : JNI_ABORT);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer,
- jboolean commit) {
- fEnv = env;
- fCommit = commit;
- fPointer = android::nio_getPointer(env, nioBuffer, &fArray);
-}
-
-android::AutoBufferPointer::~AutoBufferPointer() {
- if (NULL != fArray) {
- android::nio_releasePointer(fEnv, fArray, fPointer, fCommit);
+ // Buffer is backed by a direct buffer.
+ fArray = nullptr;
+ fElements = nullptr;
+ fPointer = reinterpret_cast<void*>(pointer);
+ } else {
+ // Buffer is backed by a managed array.
+ jint byteOffset = jniGetNioBufferBaseArrayOffset(fEnv, nioBuffer);
+ fArray = jniGetNioBufferBaseArray(fEnv, nioBuffer);
+ fElements = fEnv->GetPrimitiveArrayCritical(fArray, /* isCopy= */ nullptr);
+ fPointer = reinterpret_cast<void*>(reinterpret_cast<char*>(fElements) + byteOffset);
}
}
+
+AutoBufferPointer::~AutoBufferPointer() {
+ if (nullptr != fArray) {
+ fEnv->ReleasePrimitiveArrayCritical(fArray, fElements, fCommit ? 0 : JNI_ABORT);
+ }
+}
+
+} // namespace android
diff --git a/core/jni/android_nio_utils.h b/core/jni/android_nio_utils.h
index c634cb91..aa75dd0 100644
--- a/core/jni/android_nio_utils.h
+++ b/core/jni/android_nio_utils.h
@@ -20,52 +20,60 @@
#include <android_runtime/AndroidRuntime.h>
namespace android {
-
-/**
- * Given an nio.Buffer, return a pointer to it, beginning at its current
- * position. The returned pointer is only valid for the current JNI stack-frame.
- * For performance, it does not create any global references, so the getPointer
- * (and releasePointer if array is returned non-null) must be done in the
- * same JNI stack-frame.
- *
- * @param env The current JNI env
- * @param buffer The nio.Buffer object
- * @param array REQUIRED. Output. If on return it is set to non-null, then
- * nio_releasePointer must be called with the array
- * and the returned pointer when the caller is through with it.
- * If on return it is set to null, do not call
- * nio_releasePointer.
- * @return The pointer to the memory in the buffer object
- */
-void* nio_getPointer(JNIEnv *env, jobject buffer, jarray *array);
/**
- * Call this if android_nio_getPointer returned non-null in its array parameter.
- * Pass that array and the returned pointer when you are done accessing the
- * pointer. If called (i.e. array is non-null), it must be called in the same
- * JNI stack-frame as getPointer
+ * Class providing scoped access to the memory backing a java.nio.Buffer instance.
*
- * @param env The current JNI env
- * @param buffer The array returned from android_nio_getPointer (!= null)
- * @param pointer The pointer returned by android_nio_getPointer
- * @param commit JNI_FALSE if the pointer was just read, and JNI_TRUE if
- * the pointer was written to.
+ * Instances of this class should only be allocated on the stack as heap allocation is not
+ * supported.
+ *
+ * Instances of this class do not create any global references for performance reasons.
*/
-void nio_releasePointer(JNIEnv *env, jarray array, void *pointer,
- jboolean commit);
-
-class AutoBufferPointer {
+class AutoBufferPointer final {
public:
+ /** Constructor for an AutoBufferPointer instance.
+ *
+ * @param env The current JNI env
+ * @param nioBuffer Instance of a java.nio.Buffer whose memory will be accessed.
+ * @param commit JNI_TRUE if the underlying memory will be updated and should be
+ * copied back to the managed heap. JNI_FALSE if the data will
+ * not be modified or the modifications may be discarded.
+ *
+ * The commit parameter is only applicable if the buffer is backed by a managed heap
+ * array and the runtime had to provide a copy of the data rather than the original data.
+ */
AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit);
+
+ /** Destructor for an AutoBufferPointer instance.
+ *
+ * Releases critical managed heap array pointer if acquired.
+ */
~AutoBufferPointer();
+ /**
+ * Returns a pointer to the current position of the buffer provided to the constructor. This
+ * pointer is only valid whilst the AutoBufferPointer instance remains in scope.
+ */
void* pointer() const { return fPointer; }
private:
- JNIEnv* fEnv;
- void* fPointer;
- jarray fArray;
- jboolean fCommit;
+ JNIEnv* const fEnv;
+ void* fPointer; // Pointer to current buffer position when constructed.
+ void* fElements; // Pointer to array element 0 (null if buffer is direct, may be
+ // within fArray or point to a copy of the array).
+ jarray fArray; // Pointer to array on managed heap.
+ const jboolean fCommit; // Flag to commit data to source (when fElements is a copy of fArray).
+
+ // Unsupported constructors and operators.
+ AutoBufferPointer() = delete;
+ AutoBufferPointer(AutoBufferPointer&) = delete;
+ AutoBufferPointer& operator=(AutoBufferPointer&) = delete;
+ static void* operator new(std::size_t);
+ static void* operator new[](std::size_t);
+ static void* operator new(std::size_t, void*);
+ static void* operator new[](std::size_t, void*);
+ static void operator delete(void*, std::size_t);
+ static void operator delete[](void*, std::size_t);
};
} /* namespace android */
diff --git a/core/proto/android/os/enums.proto b/core/proto/android/os/enums.proto
index c357065..566861b 100644
--- a/core/proto/android/os/enums.proto
+++ b/core/proto/android/os/enums.proto
@@ -78,6 +78,41 @@
TEMPERATURE_TYPE_NPU = 9;
}
+// Device throttling severity
+// These constants are defined in hardware/interfaces/thermal/2.0/types.hal.
+// Any change to the types in the thermal hal should be made here as well.
+enum ThrottlingSeverityEnum {
+ // Not under throttling.
+ NONE = 0;
+ // Light throttling where UX is not impacted.
+ LIGHT = 1;
+ // Moderate throttling where UX is not largely impacted.
+ MODERATE = 2;
+ // Severe throttling where UX is largely impacted.
+ // Similar to 1.0 throttlingThreshold.
+ SEVERE = 3;
+ // Platform has done everything to reduce power.
+ CRITICAL = 4;
+ // Key components in platform are shutting down due to thermal condition.
+ // Device functionalities will be limited.
+ EMERGENCY = 5;
+ // Need shutdown immediately.
+ SHUTDOWN = 6;
+};
+
+// Device cooling device types.
+// These constants are defined in hardware/interfaces/thermal/2.0/types.hal.
+// Any change to the types in the thermal hal should be made here as well.
+enum CoolingTypeEnum {
+ FAN = 0;
+ BATTERY = 1;
+ CPU = 2;
+ GPU = 3;
+ MODEM = 4;
+ NPU = 5;
+ COMPONENT = 6;
+};
+
// Wakelock types, primarily used by android/os/PowerManager.java.
enum WakeLockLevelEnum {
// NOTE: Wake lock levels were previously defined as a bit field, except
diff --git a/core/res/res/anim/activity_close_enter.xml b/core/res/res/anim/activity_close_enter.xml
index 371bcfe..9fa7c54 100644
--- a/core/res/res/anim/activity_close_enter.xml
+++ b/core/res/res/anim/activity_close_enter.xml
@@ -19,15 +19,16 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
- <translate
- android:fromYDelta="-2%"
- android:toYDelta="0"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:duration="425"/>
- <alpha
- android:fromAlpha="0.9"
- android:toAlpha="1.0"
- android:interpolator="@interpolator/activity_close_dim"
- android:startOffset="0"
- android:duration="425"/>
+ <scale
+ android:fromXScale="1.1"
+ android:toXScale="1"
+ android:fromYScale="1.1"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:duration="400"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml
index d87f100..1599ae8 100644
--- a/core/res/res/anim/activity_close_exit.xml
+++ b/core/res/res/anim/activity_close_exit.xml
@@ -20,25 +20,25 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="top">
- <translate
- android:fromYDelta="0"
- android:toYDelta="4.1%"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:duration="425"/>
- <cliprect
- android:fromLeft="0%"
- android:fromTop="0%"
- android:fromRight="100%"
- android:fromBottom="100%"
- android:toLeft="0%"
- android:toTop="95.9%"
- android:toRight="100%"
- android:toBottom="100%"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
- android:duration="425"/>
<alpha
- android:fromAlpha="1.0"
- android:toAlpha="1.0"
- android:interpolator="@interpolator/fast_out_linear_in"
- android:duration="425"/>
+ android:fromAlpha="1"
+ android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="33"
+ android:duration="50"/>
+ <scale
+ android:fromXScale="1"
+ android:toXScale="0.9"
+ android:fromYScale="1"
+ android:toYScale="0.9"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:duration="400"/>
</set>
diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml
index cb03070..38d3e8ed 100644
--- a/core/res/res/anim/activity_open_enter.xml
+++ b/core/res/res/anim/activity_open_enter.xml
@@ -18,20 +18,25 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
- <translate
- android:fromYDelta="4.1%"
- android:toYDelta="0"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:duration="425"/>
- <cliprect
- android:fromLeft="0%"
- android:fromTop="95.9%"
- android:fromRight="100%"
- android:fromBottom="100%"
- android:toLeft="0%"
- android:toTop="0%"
- android:toRight="100%"
- android:toBottom="100%"
+ <alpha
+ android:fromAlpha="0"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="50"
+ android:duration="50"/>
+ <scale
+ android:fromXScale="0.85"
+ android:toXScale="1"
+ android:fromYScale="0.85"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
android:interpolator="@interpolator/fast_out_extra_slow_in"
- android:duration="425"/>
+ android:duration="400"/>
</set>
diff --git a/core/res/res/anim/activity_open_exit.xml b/core/res/res/anim/activity_open_exit.xml
index d52b150..3865d21 100644
--- a/core/res/res/anim/activity_open_exit.xml
+++ b/core/res/res/anim/activity_open_exit.xml
@@ -18,14 +18,28 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
- <translate
- android:fromYDelta="0"
- android:toYDelta="-2%"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:duration="425"/>
+
+ <!-- Fade out, over a black surface, which simulates a black scrim -->
<alpha
- android:fromAlpha="1.0"
- android:toAlpha="0.9"
+ android:fromAlpha="1"
+ android:toAlpha="0.4"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
android:interpolator="@interpolator/linear"
- android:duration="117"/>
+ android:startOffset="83"
+ android:duration="167"/>
+
+ <scale
+ android:fromXScale="1"
+ android:toXScale="1.05"
+ android:fromYScale="1"
+ android:toYScale="1.05"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:duration="400"/>
</set>
\ No newline at end of file
diff --git a/core/res/res/drawable/chooser_row_layer_list.xml b/core/res/res/drawable/chooser_row_layer_list.xml
index 0fb26e1..0800815 100644
--- a/core/res/res/drawable/chooser_row_layer_list.xml
+++ b/core/res/res/drawable/chooser_row_layer_list.xml
@@ -17,7 +17,7 @@
*/
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:bottom="-2dp" android:left="-2dp" android:right="-2dp">
+ <item android:bottom="-5dp" android:left="-5dp" android:right="-5dp">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="@color/chooser_row_divider"/>
</shape>
diff --git a/core/res/res/layout/chooser_grid_preview_text.xml b/core/res/res/layout/chooser_grid_preview_text.xml
index 3c9ffdb..f3ca0af 100644
--- a/core/res/res/layout/chooser_grid_preview_text.xml
+++ b/core/res/res/layout/chooser_grid_preview_text.xml
@@ -24,9 +24,9 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="@dimen/chooser_view_spacing"
- android:background="?attr/colorBackgroundFloating">
+ android:background="?android:attr/colorBackgroundFloating">
- <LinearLayout
+ <RelativeLayout
android:layout_width="@dimen/chooser_preview_width"
android:layout_height="wrap_content"
android:layout_gravity="center"
@@ -35,28 +35,51 @@
android:paddingRight="@dimen/chooser_edge_margin_normal"
android:layout_marginBottom="@dimen/chooser_view_spacing"
android:id="@+id/content_preview_text_layout">
+
<TextView
android:id="@+id/content_preview_text"
- android:layout_width="0dp"
- android:layout_weight="1"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
+ android:layout_alignParentStart="true"
+ android:layout_toStartOf="@id/copy_button"
+ android:layout_centerVertical="true"
android:ellipsize="end"
- android:gravity="start|top"
- android:paddingRight="@dimen/chooser_view_spacing"
+ android:textColor="?android:attr/textColorPrimary"
android:maxLines="2"/>
- <ImageButton
+
+ <LinearLayout
android:id="@+id/copy_button"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:padding="12dp"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_alignParentEnd="true"
+ android:layout_marginStart="@dimen/chooser_view_spacing"
android:gravity="center"
- android:layout_gravity="center_vertical"
- android:src="@drawable/ic_content_copy_gm2"
+ android:minWidth="48dp"
+ android:minHeight="48dp"
android:clickable="true"
- android:contentDescription="@string/copy"
- android:background="?attr/selectableItemBackgroundBorderless"/>
- </LinearLayout>
+ android:background="?android:attr/selectableItemBackgroundBorderless">
+
+ <ImageView
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:gravity="top|center_horizontal"
+ android:src="@drawable/ic_content_copy_gm2" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:gravity="center_horizontal"
+ android:text="@string/copy"
+ android:textColor="?android:textColorSecondary"
+ android:textSize="12sp"
+ android:maxWidth="72dp"
+ android:maxLines="2"
+ android:ellipsize="end" />
+ </LinearLayout>
+ </RelativeLayout>
<!-- Required sub-layout so we can get the nice rounded corners-->
<!-- around this section -->
@@ -89,7 +112,8 @@
android:layout_gravity="center_vertical"
android:ellipsize="end"
android:maxLines="2"
- android:textSize="20sp"/>
+ android:textSize="20sp"
+ android:textColor="?android:attr/textColorPrimary"/>
</LinearLayout>
</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ed8f2c1..ab9a298 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2485,24 +2485,7 @@
<flag name="noExcludeDescendants" value="0x8" />
</attr>
- <!-- Hints the Android System whether the view node associated with this View should be
- use for content capture purposes. -->
- <attr name="importantForContentCapture">
- <!-- Let the Android System use its heuristics to determine if the view is important for content capture. -->
- <flag name="auto" value="0" />
- <!-- Hint the Android System that this view is important for content capture,
- and its children (if any) will be traversed.. -->
- <flag name="yes" value="0x1" />
- <!-- Hint the Android System that this view is *not* important for content capture,
- but its children (if any) will be traversed.. -->
- <flag name="no" value="0x2" />
- <!-- Hint the Android System that this view is important for content capture,
- but its children (if any) will not be traversed. -->
- <flag name="yesExcludeDescendants" value="0x4" />
- <!-- Hint the Android System that this view is *not* important for content capture,
- and its children (if any) will not be traversed. -->
- <flag name="noExcludeDescendants" value="0x8" />
- </attr>
+ <attr name="__removed6" />
<!-- Boolean that controls whether a view can take focus while in touch mode.
If this is true for a view, that view can gain focus when clicked on, and can keep
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5268189..4d6fda9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3483,6 +3483,12 @@
<item>com.android.messaging</item>
</string-array>
+ <!-- An array of packages that can make sound on the ringer stream in priority-only DND
+ mode -->
+ <string-array translatable="false" name="config_priorityOnlyDndExemptPackages">
+ <item>com.android.dialer</item>
+ </string-array>
+
<!-- An array of packages which can listen for notifications on low ram devices. -->
<string-array translatable="false" name="config_allowedManagedServicesOnLowRamDevices" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9a8c754..b7d61c8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2922,7 +2922,7 @@
<public name="settingsSliceUri" />
<public name="shell" />
<public name="interactiveUiTimeout" />
- <public name="importantForContentCapture" />
+ <public name="__removed6" />
<public name="supportsMultipleDisplays" />
<public name="useAppZygote" />
<public name="__removed1" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 94b5da6b..924b036 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3188,6 +3188,7 @@
<java-symbol type="array" name="config_convert_to_emergency_number_map" />
<java-symbol type="array" name="config_nonBlockableNotificationPackages" />
+ <java-symbol type="array" name="config_priorityOnlyDndExemptPackages" />
<java-symbol type="array" name="config_allowedManagedServicesOnLowRamDevices" />
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 9cb3489..711eaa7 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -38,6 +38,7 @@
import android.os.IBinder;
import android.util.MergedConfiguration;
import android.view.Display;
+import android.view.View;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -153,6 +154,34 @@
}
@Test
+ public void testHandleActivity_assetsChanged() {
+ final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+
+ final IBinder[] token = new IBinder[1];
+ final View[] decorView = new View[1];
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ token[0] = activity.getActivityToken();
+ decorView[0] = activity.getWindow().getDecorView();
+
+ // Relaunches all activities
+ activityThread.handleApplicationInfoChanged(activity.getApplicationInfo());
+ });
+
+ final View[] newDecorView = new View[1];
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ final Activity newActivity = activityThread.getActivity(token[0]);
+ newDecorView[0] = activity.getWindow().getDecorView();
+ });
+
+ assertEquals("Window must be preserved", decorView[0], newDecorView[0]);
+ }
+
+ @Test
public void testHandleActivityConfigurationChanged_DropStaleConfigurations() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
diff --git a/core/tests/coretests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java
index d2a1dd9..2280cf1 100644
--- a/core/tests/coretests/src/android/graphics/BitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapTest.java
@@ -22,6 +22,10 @@
import junit.framework.TestCase;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
public class BitmapTest extends TestCase {
@SmallTest
@@ -262,4 +266,231 @@
assertFalse(hardwareBitmap.isMutable());
assertEquals(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), hardwareBitmap.getColorSpace());
}
+
+ @SmallTest
+ public void testCopyWithDirectByteBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to direct buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final byte padValue = 0x5a;
+ final int bytesPerElement = 1;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ ByteBuffer directBuffer = ByteBuffer.allocateDirect(bufferSize);
+
+ // Write padding
+ directBuffer.put(0, padValue);
+ directBuffer.put(directBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ directBuffer.position(pad);
+ bm1.copyPixelsToBuffer(directBuffer);
+ assertEquals(directBuffer.position(),
+ pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(directBuffer.get(0), padValue);
+ assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+ // Create bitmap from direct buffer and check match.
+ directBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(directBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithDirectShortBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final short padValue = 0x55aa;
+ final int bytesPerElement = 2;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ ShortBuffer directBuffer =
+ ByteBuffer.allocateDirect(bufferSize * bytesPerElement).asShortBuffer();
+
+ // Write padding
+ directBuffer.put(0, padValue);
+ directBuffer.put(directBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ directBuffer.position(pad);
+ bm1.copyPixelsToBuffer(directBuffer);
+ assertEquals(directBuffer.position(),
+ pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(directBuffer.get(0), padValue);
+ assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ directBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(directBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithDirectIntBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final int padValue = 0x55aa5a5a;
+ final int bytesPerElement = 4;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ IntBuffer directBuffer =
+ ByteBuffer.allocateDirect(bufferSize * bytesPerElement).asIntBuffer();
+
+ // Write padding
+ directBuffer.put(0, padValue);
+ directBuffer.put(directBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ directBuffer.position(pad);
+ bm1.copyPixelsToBuffer(directBuffer);
+ assertEquals(directBuffer.position(),
+ pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(directBuffer.get(0), padValue);
+ assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ directBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(directBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithHeapByteBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final byte padValue = 0x5a;
+ final int bytesPerElement = 1;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ ByteBuffer heapBuffer = ByteBuffer.allocate(bufferSize);
+
+ // Write padding
+ heapBuffer.put(0, padValue);
+ heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ heapBuffer.position(pad);
+ bm1.copyPixelsToBuffer(heapBuffer);
+ assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(heapBuffer.get(0), padValue);
+ assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ heapBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(heapBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithHeapShortBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final short padValue = 0x55aa;
+ final int bytesPerElement = 2;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ ShortBuffer heapBuffer = ShortBuffer.allocate(bufferSize);
+
+ // Write padding
+ heapBuffer.put(0, padValue);
+ heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ heapBuffer.position(pad);
+ bm1.copyPixelsToBuffer(heapBuffer);
+ assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(heapBuffer.get(0), padValue);
+ assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ heapBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(heapBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithHeapIntBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final int padValue = 0x55aa5a5a;
+ final int bytesPerElement = 4;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ IntBuffer heapBuffer = IntBuffer.allocate(bufferSize);
+
+ // Write padding
+ heapBuffer.put(0, padValue);
+ heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ heapBuffer.position(pad);
+ bm1.copyPixelsToBuffer(heapBuffer);
+ assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(heapBuffer.get(0), padValue);
+ assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ heapBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(heapBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index fafd833..0e94abc0 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -709,7 +709,9 @@
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS,
Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS,
- Settings.Secure.BIOMETRIC_DEBUG_ENABLED);
+ Settings.Secure.BIOMETRIC_DEBUG_ENABLED,
+ Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+ Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index ebbbdec..bdd3038 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -39,11 +39,13 @@
import android.util.SparseArray;
import android.view.SurfaceControl.Transaction;
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import android.view.test.InsetsModeSession;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -62,7 +64,6 @@
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsAnimationControlImplTest {
@@ -72,15 +73,25 @@
private SurfaceControl mTopLeash;
private SurfaceControl mNavLeash;
private InsetsState mInsetsState;
+ private static InsetsModeSession sInsetsModeSession;
@Mock Transaction mMockTransaction;
@Mock InsetsController mMockController;
@Mock WindowInsetsAnimationControlListener mMockListener;
@Mock SyncRtSurfaceTransactionApplier mMockTransactionApplier;
+ @BeforeClass
+ public static void setupOnce() {
+ sInsetsModeSession = new InsetsModeSession(NEW_INSETS_MODE_FULL);
+ }
+
+ @AfterClass
+ public static void tearDownOnce() throws Exception {
+ sInsetsModeSession.close();
+ }
+
@Before
public void setup() {
- ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL;
MockitoAnnotations.initMocks(this);
mTopLeash = new SurfaceControl.Builder(mSession)
.setName("testSurface")
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 4d8d3f6..1e55828 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -43,7 +43,6 @@
import android.widget.TextView;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -63,7 +62,6 @@
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsControllerTest {
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index a32fa77..971e143 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -34,7 +34,6 @@
import android.widget.TextView;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -53,7 +52,6 @@
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsSourceConsumerTest {
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index b55a9c6..533a58e 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -24,7 +24,6 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -41,7 +40,6 @@
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsSourceTest {
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 8e167da..a73269a 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -40,7 +40,6 @@
import android.view.WindowInsets.Type;
import android.view.test.InsetsModeSession;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
@@ -56,7 +55,6 @@
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsStateTest {
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
index cd885e0..7c255c9 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
@@ -47,6 +47,6 @@
@Test
public void testRemoveUserData_invalid() {
- assertThrows(NullPointerException.class, () -> mManager.removeUserData(null));
+ assertThrows(NullPointerException.class, () -> mManager.removeData(null));
}
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index 433991e..aeb8949 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -362,6 +362,38 @@
}
@Test
+ public void testGenerateLinks_entityData() {
+ if (isTextClassifierDisabled()) return;
+ String text = "The number is +12122537077.";
+ Bundle extras = new Bundle();
+ ExtrasUtils.putIsSerializedEntityDataEnabled(extras, true);
+ TextLinks.Request request = new TextLinks.Request.Builder(text).setExtras(extras).build();
+
+ TextLinks textLinks = mClassifier.generateLinks(request);
+
+ Truth.assertThat(textLinks.getLinks()).hasSize(1);
+ TextLinks.TextLink textLink = textLinks.getLinks().iterator().next();
+ List<Bundle> entities = ExtrasUtils.getEntities(textLink.getExtras());
+ Truth.assertThat(entities).hasSize(1);
+ Bundle entity = entities.get(0);
+ Truth.assertThat(ExtrasUtils.getEntityType(entity)).isEqualTo(TextClassifier.TYPE_PHONE);
+ }
+
+ @Test
+ public void testGenerateLinks_entityData_disabled() {
+ if (isTextClassifierDisabled()) return;
+ String text = "The number is +12122537077.";
+ TextLinks.Request request = new TextLinks.Request.Builder(text).build();
+
+ TextLinks textLinks = mClassifier.generateLinks(request);
+
+ Truth.assertThat(textLinks.getLinks()).hasSize(1);
+ TextLinks.TextLink textLink = textLinks.getLinks().iterator().next();
+ List<Bundle> entities = ExtrasUtils.getEntities(textLink.getExtras());
+ Truth.assertThat(entities).isNull();
+ }
+
+ @Test
public void testDetectLanguage() {
if (isTextClassifierDisabled()) return;
String text = "This is English text";
@@ -380,7 +412,7 @@
}
@Test
- public void testSuggestConversationActions_textReplyOnly_maxThree() {
+ public void testSuggestConversationActions_textReplyOnly_maxOne() {
if (isTextClassifierDisabled()) return;
ConversationActions.Message message =
new ConversationActions.Message.Builder(
@@ -399,12 +431,11 @@
.build();
ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
- assertTrue(conversationActions.getConversationActions().size() > 0);
- for (ConversationAction conversationAction :
- conversationActions.getConversationActions()) {
- assertThat(conversationAction,
- isConversationAction(ConversationAction.TYPE_TEXT_REPLY));
- }
+ Truth.assertThat(conversationActions.getConversationActions()).hasSize(1);
+ ConversationAction conversationAction = conversationActions.getConversationActions().get(0);
+ Truth.assertThat(conversationAction.getType()).isEqualTo(
+ ConversationAction.TYPE_TEXT_REPLY);
+ Truth.assertThat(conversationAction.getTextReply()).isNotNull();
}
@Test
@@ -493,6 +524,24 @@
ExtrasUtils.getSerializedEntityData(conversationAction.getExtras())).isNotEmpty();
}
+ @Test
+ public void testSuggetsConversationActions_deduplicate() {
+ if (isTextClassifierDisabled()) return;
+ ConversationActions.Message message =
+ new ConversationActions.Message.Builder(
+ ConversationActions.Message.PERSON_USER_OTHERS)
+ .setText("a@android.com b@android.com")
+ .build();
+ ConversationActions.Request request =
+ new ConversationActions.Request.Builder(Collections.singletonList(message))
+ .setMaxSuggestions(3)
+ .build();
+
+ ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
+
+ Truth.assertThat(conversationActions.getConversationActions()).isEmpty();
+ }
+
private boolean isTextClassifierDisabled() {
return mClassifier == null || mClassifier == TextClassifier.NO_OP;
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
index 1980a60..2c540e5 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
@@ -49,8 +49,6 @@
public class TextClassifierEventTronLoggerTest {
private static final String WIDGET_TYPE = "notification";
private static final String PACKAGE_NAME = "pkg";
- private static final long EVENT_TIME = System.currentTimeMillis();
-
@Mock
private MetricsLogger mMetricsLogger;
@@ -68,13 +66,11 @@
TextClassificationContext textClassificationContext =
new TextClassificationContext.Builder(PACKAGE_NAME, WIDGET_TYPE)
.build();
- TextClassifierEvent textClassifierEvent =
- new TextClassifierEvent.Builder(
- TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS,
+ TextClassifierEvent.ConversationActionsEvent textClassifierEvent =
+ new TextClassifierEvent.ConversationActionsEvent.Builder(
TextClassifierEvent.TYPE_SMART_ACTION)
.setEntityTypes(ConversationAction.TYPE_CALL_PHONE)
- .setScore(0.5f)
- .setEventTime(EVENT_TIME)
+ .setScores(0.5f)
.setEventContext(textClassificationContext)
.build();
@@ -83,10 +79,8 @@
ArgumentCaptor<LogMaker> captor = ArgumentCaptor.forClass(LogMaker.class);
Mockito.verify(mMetricsLogger).write(captor.capture());
LogMaker logMaker = captor.getValue();
- assertThat(logMaker.getCategory()).isEqualTo(
- CONVERSATION_ACTIONS);
- assertThat(logMaker.getSubtype()).isEqualTo(
- ACTION_TEXT_SELECTION_SMART_SHARE);
+ assertThat(logMaker.getCategory()).isEqualTo(CONVERSATION_ACTIONS);
+ assertThat(logMaker.getSubtype()).isEqualTo(ACTION_TEXT_SELECTION_SMART_SHARE);
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_FIRST_ENTITY_TYPE))
.isEqualTo(ConversationAction.TYPE_CALL_PHONE);
assertThat((float) logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_SCORE))
@@ -101,9 +95,8 @@
@Test
public void testWriteEvent_unsupportedCategory() {
- TextClassifierEvent textClassifierEvent =
- new TextClassifierEvent.Builder(
- TextClassifierEvent.CATEGORY_SELECTION,
+ TextClassifierEvent.TextSelectionEvent textClassifierEvent =
+ new TextClassifierEvent.TextSelectionEvent.Builder(
TextClassifierEvent.TYPE_SMART_ACTION)
.build();
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
new file mode 100644
index 0000000..ae3ff86
--- /dev/null
+++ b/core/tests/mockingcoretests/Android.bp
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "FrameworksMockingCoreTests",
+
+ srcs: [
+ "src/**/*.java",
+ ],
+
+ static_libs: [
+ "frameworks-base-testutils",
+ "services.core",
+ "androidx.test.runner",
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "mockito-target-extended-minus-junit4",
+ "platform-test-annotations",
+ "truth-prebuilt",
+ "testables",
+ "ub-uiautomator",
+ ],
+
+ libs: [
+ "android.test.base",
+ "android.test.mock",
+ "android.test.runner",
+ ],
+
+ // These are not normally accessible from apps so they must be explicitly included.
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
+
+ platform_apis: true,
+ test_suites: ["device-tests"],
+
+ certificate: "platform",
+}
diff --git a/core/tests/mockingcoretests/AndroidManifest.xml b/core/tests/mockingcoretests/AndroidManifest.xml
new file mode 100644
index 0000000..b9ee085
--- /dev/null
+++ b/core/tests/mockingcoretests/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ android:installLocation="internalOnly"
+ package="com.android.frameworks.mockingcoretests"
+ android:sharedUserId="com.android.uid.test">
+
+ <application android:supportsRtl="true" android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+
+ <activity android:name="android.app.activity.ActivityThreadClientTest$TestActivity"
+ android:exported="true">
+ </activity>
+
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.mockingcoretests"
+ android:label="Frameworks Mocking Core Tests" />
+</manifest>
diff --git a/core/tests/mockingcoretests/AndroidTest.xml b/core/tests/mockingcoretests/AndroidTest.xml
new file mode 100644
index 0000000..47aa410
--- /dev/null
+++ b/core/tests/mockingcoretests/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<configuration description="Runs Frameworks Mocking Core Tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="FrameworksMockingCoreTests.apk" />
+ </target_preparer>
+ <option name="test-tag" value="FrameworksMockingCoreTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.frameworks.mockingcoretests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/core/tests/mockingcoretests/README b/core/tests/mockingcoretests/README
new file mode 100644
index 0000000..c0f65c2
--- /dev/null
+++ b/core/tests/mockingcoretests/README
@@ -0,0 +1,33 @@
+* Copyright (C) 2019 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+
+
+INTRODUCTION
+
+The Android platform core tests that require additional mocking capabilities and use Extended
+Mockito, such as the ability to stub static methods. ExtendedMockito is not fully compatible with
+regular Mockito library, so tests that use it have to be verified and adapted. For that reason a
+separate module is used instead of adding to FrameworksCoreTests.
+
+For more information about ExtendedMockito see documentation of
+com.android.dx.mockito.inline.extended.ExtendedMockito class.
+
+See ../coretests/README for more information on FrameworksCoreTests.
+
+
+INSTRUCTIONS
+
+To build, install and run:
+
+ atest FrameworksMockingCoreTests
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
new file mode 100644
index 0000000..86d55ea
--- /dev/null
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.activity;
+
+import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
+import android.app.ActivityThread.ActivityClientRecord;
+import android.app.IActivityTaskManager;
+import android.app.servertransaction.PendingTransactionActions;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.view.WindowManagerGlobal;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+/**
+ * Test for verifying {@link android.app.ActivityThread} class.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksMockingCoreTests:android.app.activity.ActivityThreadClientTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class ActivityThreadClientTest {
+
+ @Test
+ @UiThreadTest
+ public void testWindowVisibilityChange_OnCreate() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ clientSession.launchActivity(r);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, true);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, false);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testWindowVisibilityChange_OnCreate_Finished() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ Activity activity = clientSession.launchActivity(r);
+ activity.finish();
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, true);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, false);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testWindowVisibilityChange_OnStart() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ clientSession.launchActivity(r);
+ clientSession.startActivity(r);
+ assertEquals(ON_START, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, false);
+ assertEquals(ON_STOP, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, true);
+ assertEquals(ON_START, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testWindowVisibilityChange_OnStart_Finished() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ Activity activity = clientSession.launchActivity(r);
+ clientSession.startActivity(r);
+ activity.finish();
+ assertEquals(ON_START, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, false);
+ assertEquals(ON_STOP, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, true);
+ assertEquals(ON_START, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testWindowVisibilityChange_OnResume() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ clientSession.launchActivity(r);
+ clientSession.startActivity(r);
+ clientSession.resumeActivity(r);
+ assertEquals(ON_RESUME, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, false);
+ assertEquals(ON_STOP, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, true);
+ assertEquals(ON_START, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testWindowVisibilityChange_OnPause() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ clientSession.launchActivity(r);
+ clientSession.startActivity(r);
+ clientSession.resumeActivity(r);
+ clientSession.pauseActivity(r);
+ assertEquals(ON_PAUSE, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, false);
+ assertEquals(ON_STOP, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, true);
+ assertEquals(ON_START, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testWindowVisibilityChange_OnStop() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ clientSession.launchActivity(r);
+ clientSession.startActivity(r);
+ clientSession.resumeActivity(r);
+ clientSession.pauseActivity(r);
+ clientSession.stopActivity(r);
+ assertEquals(ON_STOP, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, true);
+ assertEquals(ON_START, r.getLifecycleState());
+
+ clientSession.changeVisibility(r, false);
+ assertEquals(ON_STOP, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLifecycleAfterFinished_OnCreate() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ Activity activity = clientSession.launchActivity(r);
+ activity.finish();
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.startActivity(r);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.resumeActivity(r);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.pauseActivity(r);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.stopActivity(r);
+ assertEquals(ON_CREATE, r.getLifecycleState());
+
+ clientSession.destroyActivity(r);
+ assertEquals(ON_DESTROY, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLifecycleAfterFinished_OnStart() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ Activity activity = clientSession.launchActivity(r);
+ clientSession.startActivity(r);
+ activity.finish();
+ assertEquals(ON_START, r.getLifecycleState());
+
+ clientSession.resumeActivity(r);
+ assertEquals(ON_START, r.getLifecycleState());
+
+ clientSession.pauseActivity(r);
+ assertEquals(ON_START, r.getLifecycleState());
+
+ clientSession.stopActivity(r);
+ assertEquals(ON_STOP, r.getLifecycleState());
+
+ clientSession.destroyActivity(r);
+ assertEquals(ON_DESTROY, r.getLifecycleState());
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLifecycleAfterFinished_OnResume() throws Exception {
+ try (ClientMockSession clientSession = new ClientMockSession()) {
+ ActivityClientRecord r = clientSession.stubActivityRecord();
+
+ Activity activity = clientSession.launchActivity(r);
+ clientSession.startActivity(r);
+ clientSession.resumeActivity(r);
+ activity.finish();
+ assertEquals(ON_RESUME, r.getLifecycleState());
+
+ clientSession.pauseActivity(r);
+ assertEquals(ON_PAUSE, r.getLifecycleState());
+
+ clientSession.stopActivity(r);
+ assertEquals(ON_STOP, r.getLifecycleState());
+
+ clientSession.destroyActivity(r);
+ assertEquals(ON_DESTROY, r.getLifecycleState());
+ }
+ }
+
+ private class ClientMockSession implements AutoCloseable {
+ private MockitoSession mMockSession;
+ private ActivityThread mThread;
+
+ private ClientMockSession() throws RemoteException {
+ mThread = ActivityThread.currentActivityThread();
+ mMockSession = mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .spyStatic(ActivityTaskManager.class)
+ .spyStatic(WindowManagerGlobal.class)
+ .startMocking();
+ doReturn(Mockito.mock(WindowManagerGlobal.class))
+ .when(WindowManagerGlobal::getInstance);
+ IActivityTaskManager mockAtm = Mockito.mock(IActivityTaskManager.class);
+ doReturn(mockAtm).when(ActivityTaskManager::getService);
+ when(mockAtm.finishActivity(any(), anyInt(), any(), anyInt())).thenReturn(true);
+ }
+
+ private Activity launchActivity(ActivityClientRecord r) {
+ return mThread.handleLaunchActivity(r, null /* pendingActions */,
+ null /* customIntent */);
+ }
+
+ private void startActivity(ActivityClientRecord r) {
+ mThread.handleStartActivity(r, null /* pendingActions */);
+ }
+
+ private void resumeActivity(ActivityClientRecord r) {
+ mThread.handleResumeActivity(r.token, true /* finalStateRequest */,
+ true /* isForward */, "test");
+ }
+
+ private void pauseActivity(ActivityClientRecord r) {
+ mThread.handlePauseActivity(r.token, false /* finished */,
+ false /* userLeaving */, 0 /* configChanges */, null /* pendingActions */,
+ "test");
+ }
+
+ private void stopActivity(ActivityClientRecord r) {
+ mThread.handleStopActivity(r.token, false /* show */, 0 /* configChanges */,
+ new PendingTransactionActions(), false /* finalStateRequest */, "test");
+ }
+
+ private void destroyActivity(ActivityClientRecord r) {
+ mThread.handleDestroyActivity(r.token, true /* finishing */, 0 /* configChanges */,
+ false /* getNonConfigInstance */, "test");
+ }
+
+ private void changeVisibility(ActivityClientRecord r, boolean show) {
+ mThread.handleWindowVisibility(r.token, show);
+ }
+
+ private ActivityClientRecord stubActivityRecord() {
+ ComponentName component = new ComponentName(
+ InstrumentationRegistry.getInstrumentation().getContext(), TestActivity.class);
+ ActivityInfo info = new ActivityInfo();
+ info.packageName = component.getPackageName();
+ info.name = component.getClassName();
+ info.exported = true;
+ info.applicationInfo = new ApplicationInfo();
+ info.applicationInfo.packageName = info.packageName;
+ info.applicationInfo.uid = UserHandle.myUserId();
+
+ return new ActivityClientRecord(new Binder(), Intent.makeMainActivity(component),
+ 0 /* ident */, info, new Configuration(),
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null /* referrer */,
+ null /* voiceInteractor */, null /* state */, null /* persistentState */,
+ null /* pendingResults */, null /* pendingNewIntents */, true /* isForward */,
+ null /* profilerInfo */, mThread /* client */);
+ }
+
+ @Override
+ public void close() {
+ mMockSession.finishMocking();
+ }
+ }
+
+ // Test activity
+ public static class TestActivity extends Activity {
+ }
+}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 11e4cb8..2ad2e76 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3510,6 +3510,7 @@
ResStringPool keyStrings;
size_t typeIdOffset;
+ bool definesOverlayable = false;
};
// A group of objects describing a particular resource package.
@@ -6861,6 +6862,10 @@
ALOGW("Found multiple library tables, ignoring...");
}
} else {
+ if (ctype == RES_TABLE_OVERLAYABLE_TYPE) {
+ package->definesOverlayable = true;
+ }
+
status_t err = validate_chunk(chunk, sizeof(ResChunk_header),
endPos, "ResTable_package:unknown");
if (err != NO_ERROR) {
@@ -7138,6 +7143,11 @@
return UNKNOWN_ERROR;
}
+ // Idmap is not aware of overlayable, exit since policy checks can't be done
+ if (targetResTable.mPackageGroups[0]->packages[0]->definesOverlayable) {
+ return UNKNOWN_ERROR;
+ }
+
const ResTable_package* targetPackageStruct =
targetResTable.mPackageGroups[0]->packages[0]->package;
const size_t tmpNameSize = arraysize(targetPackageStruct->name);
diff --git a/libs/hwui/TreeInfo.cpp b/libs/hwui/TreeInfo.cpp
index cdad20e..dc53dd6 100644
--- a/libs/hwui/TreeInfo.cpp
+++ b/libs/hwui/TreeInfo.cpp
@@ -25,6 +25,7 @@
, prepareTextures(mode == MODE_FULL)
, canvasContext(canvasContext)
, damageGenerationId(canvasContext.getFrameNumber())
- , disableForceDark(canvasContext.useForceDark() ? 0 : 1) {}
+ , disableForceDark(canvasContext.useForceDark() ? 0 : 1)
+ , screenSize(canvasContext.getNextFrameSize()) {}
} // namespace android::uirenderer
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 04eabac..7e8d12f 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -20,6 +20,7 @@
#include "utils/Macros.h"
#include <utils/Timers.h>
+#include "SkSize.h"
#include <string>
@@ -96,6 +97,8 @@
int disableForceDark;
+ const SkISize screenSize;
+
struct Out {
bool hasFunctors = false;
// This is only updated if evaluateAnimations is true
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index da905cf..5418b33 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -547,6 +547,11 @@
}
void Tree::draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& inPaint) {
+ if (canvas->quickReject(bounds)) {
+ // The RenderNode is on screen, but the AVD is not.
+ return;
+ }
+
// Update the paint for any animatable properties
SkPaint paint = inPaint;
paint.setAlpha(mProperties.getRootAlpha() * 255);
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 29d5ef2..41bcfc2 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -22,6 +22,7 @@
#include "renderthread/CanvasContext.h"
#include <SkImagePriv.h>
+#include <SkPathOps.h>
namespace android {
namespace uirenderer {
@@ -35,7 +36,7 @@
animatedImage->syncProperties();
}
for (auto& vectorDrawable : mVectorDrawables) {
- vectorDrawable->syncProperties();
+ vectorDrawable.first->syncProperties();
}
}
@@ -51,6 +52,29 @@
}
}
+static bool intersects(const SkISize screenSize, const Matrix4& mat, const SkRect& bounds) {
+ Vector3 points[] = { Vector3 {bounds.fLeft, bounds.fTop, 0},
+ Vector3 {bounds.fRight, bounds.fTop, 0},
+ Vector3 {bounds.fRight, bounds.fBottom, 0},
+ Vector3 {bounds.fLeft, bounds.fBottom, 0}};
+ float minX, minY, maxX, maxY;
+ bool first = true;
+ for (auto& point : points) {
+ mat.mapPoint3d(point);
+ if (first) {
+ minX = maxX = point.x;
+ minY = maxY = point.y;
+ first = false;
+ } else {
+ minX = std::min(minX, point.x);
+ minY = std::min(minY, point.y);
+ maxX = std::max(maxX, point.x);
+ maxY = std::max(maxY, point.y);
+ }
+ }
+ return SkRect::Make(screenSize).intersects(SkRect::MakeLTRB(minX, minY, maxX, maxY));
+}
+
bool SkiaDisplayList::prepareListAndChildren(
TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
@@ -107,15 +131,23 @@
}
}
- for (auto& vectorDrawable : mVectorDrawables) {
+ for (auto& vectorDrawablePair : mVectorDrawables) {
// If any vector drawable in the display list needs update, damage the node.
+ auto& vectorDrawable = vectorDrawablePair.first;
if (vectorDrawable->isDirty()) {
- isDirty = true;
- static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
- ->getVectorDrawables()
- ->push_back(vectorDrawable);
+ Matrix4 totalMatrix;
+ info.damageAccumulator->computeCurrentTransform(&totalMatrix);
+ Matrix4 canvasMatrix(vectorDrawablePair.second);
+ totalMatrix.multiply(canvasMatrix);
+ const SkRect& bounds = vectorDrawable->properties().getBounds();
+ if (intersects(info.screenSize, totalMatrix, bounds)) {
+ isDirty = true;
+ static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
+ ->getVectorDrawables()
+ ->push_back(vectorDrawable);
+ vectorDrawable->setPropertyChangeWillBeConsumed(true);
+ }
}
- vectorDrawable->setPropertyChangeWillBeConsumed(true);
}
return isDirty;
}
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 3219ad1..b791037 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -22,6 +22,7 @@
#include "TreeInfo.h"
#include "hwui/AnimatedImageDrawable.h"
#include "utils/LinearAllocator.h"
+#include "utils/Pair.h"
#include <deque>
@@ -41,12 +42,6 @@
namespace skiapipeline {
-/**
- * This class is intended to be self contained, but still subclasses from
- * DisplayList to make it easier to support switching between the two at
- * runtime. The downside of this inheritance is that we pay for the overhead
- * of the parent class construction/destruction without any real benefit.
- */
class SkiaDisplayList {
public:
size_t getUsedSize() { return allocator.usedSize() + mDisplayList.usedSize(); }
@@ -156,7 +151,17 @@
std::deque<RenderNodeDrawable> mChildNodes;
std::deque<FunctorDrawable*> mChildFunctors;
std::vector<SkImage*> mMutableImages;
- std::vector<VectorDrawableRoot*> mVectorDrawables;
+private:
+ std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
+public:
+ void appendVD(VectorDrawableRoot* r) {
+ appendVD(r, SkMatrix::I());
+ }
+
+ void appendVD(VectorDrawableRoot* r, const SkMatrix& mat) {
+ mVectorDrawables.push_back(Pair<VectorDrawableRoot*, SkMatrix>(r, mat));
+ }
+
std::vector<AnimatedImageDrawable*> mAnimatedImages;
DisplayListData mDisplayList;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 5a47a29..0a28949 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -152,7 +152,9 @@
void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
mRecorder.drawVectorDrawable(tree);
- mDisplayList->mVectorDrawables.push_back(tree);
+ SkMatrix mat;
+ this->getMatrix(&mat);
+ mDisplayList->appendVD(tree, mat);
}
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 1b3bd30..2957b14 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -41,6 +41,7 @@
#include <sys/stat.h>
#include <algorithm>
+#include <cstdint>
#include <cstdlib>
#include <functional>
@@ -510,6 +511,17 @@
prepareAndDraw(nullptr);
}
+SkISize CanvasContext::getNextFrameSize() const {
+ ReliableSurface* surface = mNativeSurface.get();
+ if (surface) {
+ SkISize size;
+ surface->query(NATIVE_WINDOW_WIDTH, &size.fWidth);
+ surface->query(NATIVE_WINDOW_HEIGHT, &size.fHeight);
+ return size;
+ }
+ return {INT32_MAX, INT32_MAX};
+}
+
void CanvasContext::prepareAndDraw(RenderNode* node) {
ATRACE_CALL();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0bd080d..912b125 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -32,6 +32,7 @@
#include <EGL/egl.h>
#include <SkBitmap.h>
#include <SkRect.h>
+#include <SkSize.h>
#include <cutils/compiler.h>
#include <gui/Surface.h>
#include <utils/Functor.h>
@@ -112,7 +113,7 @@
void setSurface(sp<Surface>&& surface);
bool pauseSurface();
void setStopped(bool stopped);
- bool hasSurface() { return mNativeSurface.get(); }
+ bool hasSurface() const { return mNativeSurface.get(); }
void allocateBuffers();
void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
@@ -205,6 +206,8 @@
// Must be called before setSurface
void setRenderAheadDepth(uint32_t renderAhead);
+ SkISize getNextFrameSize() const;
+
private:
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 1b4cf7e..6fb164a 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -23,6 +23,7 @@
#include "pipeline/skia/GLFunctorDrawable.h"
#include "pipeline/skia/SkiaDisplayList.h"
#include "renderthread/CanvasContext.h"
+#include "tests/common/TestContext.h"
#include "tests/common/TestUtils.h"
using namespace android;
@@ -50,13 +51,13 @@
GLFunctorDrawable functorDrawable(nullptr, nullptr, &dummyCanvas);
skiaDL->mChildFunctors.push_back(&functorDrawable);
skiaDL->mMutableImages.push_back(nullptr);
- skiaDL->mVectorDrawables.push_back(nullptr);
+ skiaDL->appendVD(nullptr);
skiaDL->mProjectionReceiver = &drawable;
ASSERT_FALSE(skiaDL->mChildNodes.empty());
ASSERT_FALSE(skiaDL->mChildFunctors.empty());
ASSERT_FALSE(skiaDL->mMutableImages.empty());
- ASSERT_FALSE(skiaDL->mVectorDrawables.empty());
+ ASSERT_TRUE(skiaDL->hasVectorDrawables());
ASSERT_FALSE(skiaDL->isEmpty());
ASSERT_TRUE(skiaDL->mProjectionReceiver);
@@ -65,7 +66,7 @@
ASSERT_TRUE(skiaDL->mChildNodes.empty());
ASSERT_TRUE(skiaDL->mChildFunctors.empty());
ASSERT_TRUE(skiaDL->mMutableImages.empty());
- ASSERT_TRUE(skiaDL->mVectorDrawables.empty());
+ ASSERT_FALSE(skiaDL->hasVectorDrawables());
ASSERT_TRUE(skiaDL->isEmpty());
ASSERT_FALSE(skiaDL->mProjectionReceiver);
}
@@ -110,7 +111,7 @@
SkRect bounds = SkRect::MakeWH(200, 200);
VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
vectorDrawable.mutateStagingProperties()->setBounds(bounds);
- skiaDL.mVectorDrawables.push_back(&vectorDrawable);
+ skiaDL.appendVD(&vectorDrawable);
// ensure that the functor and vectorDrawable are properly synced
TestUtils::runOnRenderThread([&](auto&) {
@@ -149,9 +150,14 @@
SkiaDisplayList skiaDL;
+ // The VectorDrawableRoot needs to have bounds on screen (and therefore not
+ // empty) in order to have PropertyChangeWillBeConsumed set.
+ const auto bounds = SkRect::MakeIWH(100, 100);
+
// prepare with a clean VD
VectorDrawableRoot cleanVD(new VectorDrawable::Group());
- skiaDL.mVectorDrawables.push_back(&cleanVD);
+ cleanVD.mutateProperties()->setBounds(bounds);
+ skiaDL.appendVD(&cleanVD);
cleanVD.getBitmapUpdateIfDirty(); // this clears the dirty bit
ASSERT_FALSE(cleanVD.isDirty());
@@ -159,11 +165,12 @@
TestUtils::MockTreeObserver observer;
ASSERT_FALSE(skiaDL.prepareListAndChildren(observer, info, false,
[](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
- ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
+ ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
// prepare again this time adding a dirty VD
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
- skiaDL.mVectorDrawables.push_back(&dirtyVD);
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ skiaDL.appendVD(&dirtyVD);
ASSERT_TRUE(dirtyVD.isDirty());
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
@@ -191,6 +198,169 @@
canvasContext->destroy();
}
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren_vdOffscreen) {
+ auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
+ ContextFactory contextFactory;
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+
+ // Set up a Surface so that we can position the VectorDrawable offscreen.
+ test::TestContext testContext;
+ testContext.setRenderOffscreen(true);
+ auto surface = testContext.surface();
+ int width, height;
+ surface->query(NATIVE_WINDOW_WIDTH, &width);
+ surface->query(NATIVE_WINDOW_HEIGHT, &height);
+ canvasContext->setSurface(std::move(surface));
+
+ TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
+ DamageAccumulator damageAccumulator;
+ info.damageAccumulator = &damageAccumulator;
+
+ // The VectorDrawableRoot needs to have bounds on screen (and therefore not
+ // empty) in order to have PropertyChangeWillBeConsumed set.
+ const auto bounds = SkRect::MakeIWH(100, 100);
+
+ for (const SkRect b : {bounds.makeOffset(width, 0),
+ bounds.makeOffset(0, height),
+ bounds.makeOffset(-bounds.width(), 0),
+ bounds.makeOffset(0, -bounds.height())}) {
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(b);
+ skiaDL.appendVD(&dirtyVD);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_FALSE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+ }
+
+ // The DamageAccumulator's transform can also result in the
+ // VectorDrawableRoot being offscreen.
+ for (const SkISize translate : { SkISize{width, 0},
+ SkISize{0, height},
+ SkISize{-width, 0},
+ SkISize{0, -height}}) {
+ Matrix4 mat4;
+ mat4.translate(translate.fWidth, translate.fHeight);
+ damageAccumulator.pushTransform(&mat4);
+
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ skiaDL.appendVD(&dirtyVD);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_FALSE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+ damageAccumulator.popTransform();
+ }
+
+ // Another way to be offscreen: a matrix from the draw call.
+ for (const SkMatrix translate : { SkMatrix::MakeTrans(width, 0),
+ SkMatrix::MakeTrans(0, height),
+ SkMatrix::MakeTrans(-width, 0),
+ SkMatrix::MakeTrans(0, -height)}) {
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ skiaDL.appendVD(&dirtyVD, translate);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_FALSE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+ }
+
+ // Verify that the matrices are combined in the right order.
+ {
+ // Rotate and then translate, so the VD is offscreen.
+ Matrix4 mat4;
+ mat4.loadRotate(180);
+ damageAccumulator.pushTransform(&mat4);
+
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ SkMatrix translate = SkMatrix::MakeTrans(50, 50);
+ skiaDL.appendVD(&dirtyVD, translate);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_FALSE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+ damageAccumulator.popTransform();
+ }
+ {
+ // Switch the order of rotate and translate, so it is on screen.
+ Matrix4 mat4;
+ mat4.translate(50, 50);
+ damageAccumulator.pushTransform(&mat4);
+
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ SkMatrix rotate;
+ rotate.setRotate(180);
+ skiaDL.appendVD(&dirtyVD, rotate);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_TRUE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+ damageAccumulator.popTransform();
+ }
+ {
+ // An AVD that is larger than the screen.
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(SkRect::MakeLTRB(-1, -1, width + 1, height + 1));
+ skiaDL.appendVD(&dirtyVD);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_TRUE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+ }
+ {
+ // An AVD whose bounds are not a rectangle after applying a matrix.
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ SkMatrix mat;
+ mat.setRotate(45, 50, 50);
+ skiaDL.appendVD(&dirtyVD, mat);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_TRUE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+ }
+}
+
TEST(SkiaDisplayList, updateChildren) {
SkiaDisplayList skiaDL;
diff --git a/media/Android.bp b/media/Android.bp
index 8746046..70dacb2 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -20,10 +20,6 @@
],
},
- static_libs: [
- "mediaplayer2-protos",
- ],
-
permitted_packages: [
"android.media",
],
@@ -43,7 +39,6 @@
name: "updatable-media-srcs",
srcs: [
":mediasession2-srcs",
- ":mediaplayer2-srcs",
],
}
@@ -51,7 +46,6 @@
name: "updatable-media-srcs-without-aidls",
srcs : [
":mediasession2-srcs-without-aidls",
- ":mediaplayer2-srcs",
],
}
@@ -64,7 +58,6 @@
"apex/java/android/media/IMediaSession2Service.aidl",
"apex/java/android/media/MediaConstants.java",
"apex/java/android/media/MediaController2.java",
- "apex/java/android/media/MediaItem2.java",
"apex/java/android/media/MediaSession2.java",
"apex/java/android/media/MediaSession2Service.java",
"apex/java/android/media/Session2Command.java",
@@ -110,8 +103,7 @@
"--hide MissingPermission --hide BroadcastBehavior " +
"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
- "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi " +
- " --show-annotation android.annotation.TestApi "
+ "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi "
droidstubs {
name: "updatable-media-stubs",
diff --git a/media/apex/java/android/media/BufferingParams.java b/media/apex/java/android/media/BufferingParams.java
index 83594d4..943f142 100644
--- a/media/apex/java/android/media/BufferingParams.java
+++ b/media/apex/java/android/media/BufferingParams.java
@@ -17,7 +17,6 @@
package android.media;
import android.annotation.IntDef;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -64,7 +63,6 @@
* <p>Users should use {@link Builder} to change {@link BufferingParams}.
* @hide
*/
-@TestApi
public final class BufferingParams implements Parcelable {
private static final int BUFFERING_NO_MARK = -1;
diff --git a/media/apex/java/android/media/MediaItem2.java b/media/apex/java/android/media/MediaItem2.java
deleted file mode 100644
index ff0d43e..0000000
--- a/media/apex/java/android/media/MediaItem2.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import static android.media.MediaMetadata.METADATA_KEY_MEDIA_ID;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * A class with information on a single media item with the metadata information.
- * <p>
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a>
- * for consistent behavior across all devices.
- * <p>
- */
-public final class MediaItem2 implements Parcelable {
- private static final String TAG = "MediaItem2";
-
- // intentionally less than long.MAX_VALUE.
- // Declare this first to avoid 'illegal forward reference'.
- static final long LONG_MAX = 0x7ffffffffffffffL;
-
- /**
- * Used when a position is unknown.
- *
- * @see #getEndPosition()
- */
- public static final long POSITION_UNKNOWN = LONG_MAX;
-
- public static final @android.annotation.NonNull Parcelable.Creator<MediaItem2> CREATOR =
- new Parcelable.Creator<MediaItem2>() {
- @Override
- public MediaItem2 createFromParcel(Parcel in) {
- return new MediaItem2(in);
- }
-
- @Override
- public MediaItem2[] newArray(int size) {
- return new MediaItem2[size];
- }
- };
-
- private static final long UNKNOWN_TIME = -1;
-
- private final long mStartPositionMs;
- private final long mEndPositionMs;
-
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private MediaMetadata mMetadata;
- @GuardedBy("mLock")
- private final List<Pair<OnMetadataChangedListener, Executor>> mListeners = new ArrayList<>();
-
- /**
- * Used by {@link MediaItem2.Builder}.
- */
- // Note: Needs to be protected when we want to allow 3rd party player to define customized
- // MediaItem2.
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaItem2(Builder builder) {
- this(builder.mMetadata, builder.mStartPositionMs, builder.mEndPositionMs);
- }
-
- /**
- * Used by Parcelable.Creator.
- */
- // Note: Needs to be protected when we want to allow 3rd party player to define customized
- // MediaItem2.
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaItem2(Parcel in) {
- this(in.readParcelable(MediaItem2.class.getClassLoader()), in.readLong(), in.readLong());
- }
-
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaItem2(MediaItem2 item) {
- this(item.mMetadata, item.mStartPositionMs, item.mEndPositionMs);
- }
-
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaItem2(@Nullable MediaMetadata metadata, long startPositionMs, long endPositionMs) {
- if (startPositionMs > endPositionMs) {
- throw new IllegalArgumentException("Illegal start/end position: "
- + startPositionMs + " : " + endPositionMs);
- }
- if (metadata != null && metadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
- long durationMs = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
- if (durationMs != UNKNOWN_TIME && endPositionMs != POSITION_UNKNOWN
- && endPositionMs > durationMs) {
- throw new IllegalArgumentException("endPositionMs shouldn't be greater than"
- + " duration in the metdata, endPositionMs=" + endPositionMs
- + ", durationMs=" + durationMs);
- }
- }
- mMetadata = metadata;
- mStartPositionMs = startPositionMs;
- mEndPositionMs = endPositionMs;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder(getClass().getSimpleName());
- synchronized (mLock) {
- sb.append("{mMetadata=").append(mMetadata);
- sb.append(", mStartPositionMs=").append(mStartPositionMs);
- sb.append(", mEndPositionMs=").append(mEndPositionMs);
- sb.append('}');
- }
- return sb.toString();
- }
-
- /**
- * Sets metadata. If the metadata is not {@code null}, its id should be matched with this
- * instance's media id.
- *
- * @param metadata metadata to update
- * @see MediaMetadata#METADATA_KEY_MEDIA_ID
- */
- public void setMetadata(@Nullable MediaMetadata metadata) {
- List<Pair<OnMetadataChangedListener, Executor>> listeners = new ArrayList<>();
- synchronized (mLock) {
- if (mMetadata != null && metadata != null
- && !TextUtils.equals(getMediaId(), metadata.getString(METADATA_KEY_MEDIA_ID))) {
- Log.d(TAG, "MediaItem2's media ID shouldn't be changed");
- return;
- }
- mMetadata = metadata;
- listeners.addAll(mListeners);
- }
-
- for (Pair<OnMetadataChangedListener, Executor> pair : listeners) {
- final OnMetadataChangedListener listener = pair.first;
- pair.second.execute(new Runnable() {
- @Override
- public void run() {
- listener.onMetadataChanged(MediaItem2.this);
- }
- });
- }
- }
-
- /**
- * Gets the metadata of the media.
- *
- * @return metadata from the session
- */
- public @Nullable MediaMetadata getMetadata() {
- synchronized (mLock) {
- return mMetadata;
- }
- }
-
- /**
- * Return the position in milliseconds at which the playback will start.
- * @return the position in milliseconds at which the playback will start
- */
- public long getStartPosition() {
- return mStartPositionMs;
- }
-
- /**
- * Return the position in milliseconds at which the playback will end.
- * {@link #POSITION_UNKNOWN} means ending at the end of source content.
- * @return the position in milliseconds at which the playback will end
- */
- public long getEndPosition() {
- return mEndPositionMs;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mMetadata, 0);
- dest.writeLong(mStartPositionMs);
- dest.writeLong(mEndPositionMs);
- }
-
- /**
- * Gets the media id for this item. If it's not {@code null}, it's a persistent unique key
- * for the underlying media content.
- *
- * @return media Id from the session
- */
- @Nullable String getMediaId() {
- synchronized (mLock) {
- return mMetadata != null
- ? mMetadata.getString(METADATA_KEY_MEDIA_ID) : null;
- }
- }
-
- void addOnMetadataChangedListener(Executor executor, OnMetadataChangedListener listener) {
- synchronized (mLock) {
- for (Pair<OnMetadataChangedListener, Executor> pair : mListeners) {
- if (pair.first == listener) {
- return;
- }
- }
- mListeners.add(new Pair<>(listener, executor));
- }
- }
-
- void removeOnMetadataChangedListener(OnMetadataChangedListener listener) {
- synchronized (mLock) {
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- if (mListeners.get(i).first == listener) {
- mListeners.remove(i);
- return;
- }
- }
- }
- }
-
- /**
- * Builder for {@link MediaItem2}.
- */
- public static final class Builder {
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaMetadata mMetadata;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- long mStartPositionMs = 0;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- long mEndPositionMs = POSITION_UNKNOWN;
-
- /**
- * Set the metadata of this instance. {@code null} for unset.
- *
- * @param metadata metadata
- * @return this instance for chaining
- */
- public @NonNull Builder setMetadata(@Nullable MediaMetadata metadata) {
- mMetadata = metadata;
- return this;
- }
-
- /**
- * Sets the start position in milliseconds at which the playback will start.
- * Any negative number is treated as 0.
- *
- * @param position the start position in milliseconds at which the playback will start
- * @return the same Builder instance.
- */
- public @NonNull Builder setStartPosition(long position) {
- if (position < 0) {
- position = 0;
- }
- mStartPositionMs = position;
- return this;
- }
-
- /**
- * Sets the end position in milliseconds at which the playback will end.
- * Any negative number is treated as maximum length of the media item.
- *
- * @param position the end position in milliseconds at which the playback will end
- * @return the same Builder instance.
- */
- public @NonNull Builder setEndPosition(long position) {
- if (position < 0) {
- position = POSITION_UNKNOWN;
- }
- mEndPositionMs = position;
- return this;
- }
-
- /**
- * Build {@link MediaItem2}.
- *
- * @return a new {@link MediaItem2}.
- */
- public @NonNull MediaItem2 build() {
- return new MediaItem2(this);
- }
- }
-
- interface OnMetadataChangedListener {
- void onMetadataChanged(MediaItem2 item);
- }
-}
diff --git a/media/apex/java/android/media/Session2Command.java b/media/apex/java/android/media/Session2Command.java
index 7f73dc1..7c752e1 100644
--- a/media/apex/java/android/media/Session2Command.java
+++ b/media/apex/java/android/media/Session2Command.java
@@ -30,7 +30,7 @@
* <p>
* If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
* If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
- * {@link #getCustomCommand()} shouldn't be {@code null}.
+ * {@link #getCustomAction()} shouldn't be {@code null}.
* <p>
* Refer to the
* <a href="{@docRoot}reference/androidx/media2/SessionCommand2.html">AndroidX SessionCommand</a>
@@ -63,8 +63,8 @@
private final int mCommandCode;
// Nonnull if it's custom command
- private final String mCustomCommand;
- private final Bundle mExtras;
+ private final String mCustomAction;
+ private final Bundle mCustomExtras;
/**
* Constructor for creating a command predefined in AndroidX media2.
@@ -76,8 +76,8 @@
throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM");
}
mCommandCode = commandCode;
- mCustomCommand = null;
- mExtras = null;
+ mCustomAction = null;
+ mCustomExtras = null;
}
/**
@@ -91,8 +91,8 @@
throw new IllegalArgumentException("action shouldn't be null");
}
mCommandCode = COMMAND_CODE_CUSTOM;
- mCustomCommand = action;
- mExtras = extras;
+ mCustomAction = action;
+ mCustomExtras = extras;
}
/**
@@ -101,8 +101,8 @@
@SuppressWarnings("WeakerAccess") /* synthetic access */
Session2Command(Parcel in) {
mCommandCode = in.readInt();
- mCustomCommand = in.readString();
- mExtras = in.readBundle();
+ mCustomAction = in.readString();
+ mCustomExtras = in.readBundle();
}
/**
@@ -118,8 +118,8 @@
* This will return {@code null} for a predefined command.
*/
@Nullable
- public String getCustomCommand() {
- return mCustomCommand;
+ public String getCustomAction() {
+ return mCustomAction;
}
/**
@@ -127,8 +127,8 @@
* This will return {@code null} for a predefined command.
*/
@Nullable
- public Bundle getExtras() {
- return mExtras;
+ public Bundle getCustomExtras() {
+ return mCustomExtras;
}
@Override
@@ -142,8 +142,8 @@
throw new IllegalArgumentException("parcel shouldn't be null");
}
dest.writeInt(mCommandCode);
- dest.writeString(mCustomCommand);
- dest.writeBundle(mExtras);
+ dest.writeString(mCustomAction);
+ dest.writeBundle(mCustomExtras);
}
@Override
@@ -153,12 +153,12 @@
}
Session2Command other = (Session2Command) obj;
return mCommandCode == other.mCommandCode
- && TextUtils.equals(mCustomCommand, other.mCustomCommand);
+ && TextUtils.equals(mCustomAction, other.mCustomAction);
}
@Override
public int hashCode() {
- return Objects.hash(mCustomCommand, mCommandCode);
+ return Objects.hash(mCustomAction, mCommandCode);
}
/**
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d347137..f8e43437 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4523,6 +4523,7 @@
*/
/** @hide */
+ @TestApi
@SystemApi
public static final int SUCCESS = AudioSystem.SUCCESS;
/**
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
deleted file mode 100644
index f704acd..0000000
--- a/media/java/android/media/MiniThumbFile.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.UnsupportedAppUsage;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
-import android.util.Log;
-
-import dalvik.system.VMRuntime;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.util.Hashtable;
-
-/**
- * This class handles the mini-thumb file. A mini-thumb file consists
- * of blocks, indexed by id. Each block has BYTES_PER_MINTHUMB bytes in the
- * following format:
- *
- * 1 byte status (0 = empty, 1 = mini-thumb available)
- * 8 bytes magic (a magic number to match what's in the database)
- * 4 bytes data length (LEN)
- * LEN bytes jpeg data
- * (the remaining bytes are unused)
- *
- * @hide This file is shared between MediaStore and MediaProvider and should remained internal use
- * only.
- * @deprecated thumbnails are now maintained in separate files, and this file
- * format is no longer used.
- */
-@Deprecated
-public class MiniThumbFile {
- private static final String TAG = "MiniThumbFile";
- private static final int MINI_THUMB_DATA_FILE_VERSION = 4;
- public static final int BYTES_PER_MINTHUMB = 10000;
- private static final int HEADER_SIZE = 1 + 8 + 4;
- private Uri mUri;
- private RandomAccessFile mMiniThumbFile;
- private FileChannel mChannel;
- private ByteBuffer mBuffer;
- private ByteBuffer mEmptyBuffer;
- private static final Hashtable<String, MiniThumbFile> sThumbFiles =
- new Hashtable<String, MiniThumbFile>();
-
- /**
- * We store different types of thumbnails in different files. To remain backward compatibility,
- * we should hashcode of content://media/external/images/media remains the same.
- */
- @UnsupportedAppUsage
- public static synchronized void reset() {
- for (MiniThumbFile file : sThumbFiles.values()) {
- file.deactivate();
- }
- sThumbFiles.clear();
- }
-
- public static synchronized MiniThumbFile instance(Uri uri) {
- if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q) {
- throw new UnsupportedOperationException();
- }
- String type = uri.getPathSegments().get(1);
- MiniThumbFile file = sThumbFiles.get(type);
- // Log.v(TAG, "get minithumbfile for type: "+type);
- if (file == null) {
- file = new MiniThumbFile(
- Uri.parse("content://media/external/" + type + "/media"));
- sThumbFiles.put(type, file);
- }
-
- return file;
- }
-
- private String randomAccessFilePath(int version) {
- String directoryName =
- Environment.getExternalStorageDirectory().toString()
- + "/DCIM/.thumbnails";
- return directoryName + "/.thumbdata" + version + "-" + mUri.hashCode();
- }
-
- private void removeOldFile() {
- String oldPath = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION - 1);
- File oldFile = new File(oldPath);
- if (oldFile.exists()) {
- try {
- oldFile.delete();
- } catch (SecurityException ex) {
- // ignore
- }
- }
- }
-
- private RandomAccessFile miniThumbDataFile() {
- if (mMiniThumbFile == null) {
- removeOldFile();
- String path = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION);
- File directory = new File(path).getParentFile();
- if (!directory.isDirectory()) {
- if (!directory.mkdirs()) {
- Log.e(TAG, "Unable to create .thumbnails directory "
- + directory.toString());
- }
- }
- File f = new File(path);
- try {
- mMiniThumbFile = new RandomAccessFile(f, "rw");
- } catch (IOException ex) {
- // Open as read-only so we can at least read the existing
- // thumbnails.
- try {
- mMiniThumbFile = new RandomAccessFile(f, "r");
- } catch (IOException ex2) {
- // ignore exception
- }
- }
- if (mMiniThumbFile != null) {
- mChannel = mMiniThumbFile.getChannel();
- }
- }
- return mMiniThumbFile;
- }
-
- private MiniThumbFile(Uri uri) {
- mUri = uri;
- mBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
- mEmptyBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
- }
-
- public synchronized void deactivate() {
- if (mMiniThumbFile != null) {
- try {
- mMiniThumbFile.close();
- mMiniThumbFile = null;
- } catch (IOException ex) {
- // ignore exception
- }
- }
- }
-
- // Get the magic number for the specified id in the mini-thumb file.
- // Returns 0 if the magic is not available.
- public synchronized long getMagic(long id) {
- // check the mini thumb file for the right data. Right is
- // defined as having the right magic number at the offset
- // reserved for this "id".
- RandomAccessFile r = miniThumbDataFile();
- if (r != null) {
- long pos = id * BYTES_PER_MINTHUMB;
- FileLock lock = null;
- try {
- mBuffer.clear();
- mBuffer.limit(1 + 8);
-
- lock = mChannel.lock(pos, 1 + 8, true);
- // check that we can read the following 9 bytes
- // (1 for the "status" and 8 for the long)
- if (mChannel.read(mBuffer, pos) == 9) {
- mBuffer.position(0);
- if (mBuffer.get() == 1) {
- return mBuffer.getLong();
- }
- }
- } catch (IOException ex) {
- Log.v(TAG, "Got exception checking file magic: ", ex);
- } catch (RuntimeException ex) {
- // Other NIO related exception like disk full, read only channel..etc
- Log.e(TAG, "Got exception when reading magic, id = " + id +
- ", disk full or mount read-only? " + ex.getClass());
- } finally {
- try {
- if (lock != null) lock.release();
- }
- catch (IOException ex) {
- // ignore it.
- }
- }
- }
- return 0;
- }
-
- public synchronized void eraseMiniThumb(long id) {
- RandomAccessFile r = miniThumbDataFile();
- if (r != null) {
- long pos = id * BYTES_PER_MINTHUMB;
- FileLock lock = null;
- try {
- mBuffer.clear();
- mBuffer.limit(1 + 8);
-
- lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, false);
- // check that we can read the following 9 bytes
- // (1 for the "status" and 8 for the long)
- if (mChannel.read(mBuffer, pos) == 9) {
- mBuffer.position(0);
- if (mBuffer.get() == 1) {
- long currentMagic = mBuffer.getLong();
- if (currentMagic == 0) {
- // there is no thumbnail stored here
- Log.i(TAG, "no thumbnail for id " + id);
- return;
- }
- // zero out the thumbnail slot
- // Log.v(TAG, "clearing slot " + id + ", magic " + currentMagic
- // + " at offset " + pos);
- mChannel.write(mEmptyBuffer, pos);
- }
- } else {
- // Log.v(TAG, "No slot");
- }
- } catch (IOException ex) {
- Log.v(TAG, "Got exception checking file magic: ", ex);
- } catch (RuntimeException ex) {
- // Other NIO related exception like disk full, read only channel..etc
- Log.e(TAG, "Got exception when reading magic, id = " + id +
- ", disk full or mount read-only? " + ex.getClass());
- } finally {
- try {
- if (lock != null) lock.release();
- }
- catch (IOException ex) {
- // ignore it.
- }
- }
- } else {
- // Log.v(TAG, "No data file");
- }
- }
-
- public synchronized void saveMiniThumbToFile(byte[] data, long id, long magic)
- throws IOException {
- RandomAccessFile r = miniThumbDataFile();
- if (r == null) return;
-
- long pos = id * BYTES_PER_MINTHUMB;
- FileLock lock = null;
- try {
- if (data != null) {
- if (data.length > BYTES_PER_MINTHUMB - HEADER_SIZE) {
- // not enough space to store it.
- return;
- }
- mBuffer.clear();
- mBuffer.put((byte) 1);
- mBuffer.putLong(magic);
- mBuffer.putInt(data.length);
- mBuffer.put(data);
- mBuffer.flip();
-
- lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, false);
- mChannel.write(mBuffer, pos);
- }
- } catch (IOException ex) {
- Log.e(TAG, "couldn't save mini thumbnail data for "
- + id + "; ", ex);
- throw ex;
- } catch (RuntimeException ex) {
- // Other NIO related exception like disk full, read only channel..etc
- Log.e(TAG, "couldn't save mini thumbnail data for "
- + id + "; disk full or mount read-only? " + ex.getClass());
- } finally {
- try {
- if (lock != null) lock.release();
- }
- catch (IOException ex) {
- // ignore it.
- }
- }
- }
-
- /**
- * Gallery app can use this method to retrieve mini-thumbnail. Full size
- * images share the same IDs with their corresponding thumbnails.
- *
- * @param id the ID of the image (same of full size image).
- * @param data the buffer to store mini-thumbnail.
- */
- public synchronized byte [] getMiniThumbFromFile(long id, byte [] data) {
- RandomAccessFile r = miniThumbDataFile();
- if (r == null) return null;
-
- long pos = id * BYTES_PER_MINTHUMB;
- FileLock lock = null;
- try {
- mBuffer.clear();
- lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, true);
- int size = mChannel.read(mBuffer, pos);
- if (size > 1 + 8 + 4) { // flag, magic, length
- mBuffer.position(0);
- byte flag = mBuffer.get();
- long magic = mBuffer.getLong();
- int length = mBuffer.getInt();
-
- if (size >= 1 + 8 + 4 + length && length != 0 && magic != 0 && flag == 1 &&
- data.length >= length) {
- mBuffer.get(data, 0, length);
- return data;
- }
- }
- } catch (IOException ex) {
- Log.w(TAG, "got exception when reading thumbnail id=" + id + ", exception: " + ex);
- } catch (RuntimeException ex) {
- // Other NIO related exception like disk full, read only channel..etc
- Log.e(TAG, "Got exception when reading thumbnail, id = " + id +
- ", disk full or mount read-only? " + ex.getClass());
- } finally {
- try {
- if (lock != null) lock.release();
- }
- catch (IOException ex) {
- // ignore it.
- }
- }
- return null;
- }
-}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index fefb0d7..e207721 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -495,15 +495,17 @@
if (mCursor == null || !mCursor.moveToPosition(position)) {
return null;
}
-
- return getUriFromCursor(mCursor);
+
+ return getUriFromCursor(mContext, mCursor);
}
- private static Uri getUriFromCursor(Cursor cursor) {
- return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor
- .getLong(ID_COLUMN_INDEX));
+ private static Uri getUriFromCursor(Context context, Cursor cursor) {
+ final Uri uri = ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)),
+ cursor.getLong(ID_COLUMN_INDEX));
+ final Uri canonicalized = context.getContentResolver().canonicalize(uri);
+ return (canonicalized != null) ? canonicalized : uri;
}
-
+
/**
* Gets the position of a {@link Uri} within this {@link RingtoneManager}.
*
@@ -569,7 +571,7 @@
Uri uri = null;
if (cursor.moveToFirst()) {
- uri = getUriFromCursor(cursor);
+ uri = getUriFromCursor(context, cursor);
}
cursor.close();
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 1cd60f7..39474e1 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -416,6 +416,7 @@
* @param devices list of devices to which the audio stream of the application may be routed.
* @return true if the change was successful, false otherwise.
*/
+ @TestApi
@SystemApi
public boolean setUidDeviceAffinity(int uid, @NonNull List<AudioDeviceInfo> devices) {
if (devices == null) {
@@ -457,6 +458,7 @@
* @param uid UID of the application affected.
* @return true if the change was successful, false otherwise.
*/
+ @TestApi
@SystemApi
public boolean removeUidDeviceAffinity(int uid) {
synchronized (mLock) {
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index 55c9361..81c5bcd 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -52,6 +52,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.TrafficStatsConstants;
import java.io.IOException;
import java.lang.reflect.Field;
@@ -238,7 +239,8 @@
if (isFinishing() || isDestroyed()) return;
HttpURLConnection urlConnection = null;
int httpResponseCode = 500;
- int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+ int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_PROBE);
try {
urlConnection = (HttpURLConnection) mNetwork.openConnection(
new URL(mCm.getCaptivePortalServerUrl()));
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 1544adb..7860f36 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -238,7 +238,7 @@
}
mSingleThreadExecutor.submit(() -> {
NotificationEntry entry =
- new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+ new NotificationEntry(mPackageManager, sbn.cloneLight(), channel, mSmsHelper);
SmartActionsHelper.SmartSuggestions suggestions = mSmartActionsHelper.suggest(entry);
if (DEBUG) {
Log.d(TAG, String.format(
@@ -272,6 +272,9 @@
final int importance = entry.getImportance() < IMPORTANCE_LOW
? entry.getImportance() : IMPORTANCE_LOW;
signals.putInt(KEY_IMPORTANCE, importance);
+ } else {
+ // Even if no change is made, send an identity adjustment for metric logging.
+ signals.putInt(KEY_IMPORTANCE, entry.getImportance());
}
}
@@ -293,7 +296,7 @@
Ranking ranking = getRanking(sbn.getKey(), rankingMap);
if (ranking != null && ranking.getChannel() != null) {
NotificationEntry entry = new NotificationEntry(mPackageManager,
- sbn, ranking.getChannel(), mSmsHelper);
+ sbn.cloneLight(), ranking.getChannel(), mSmsHelper);
String key = getKey(
sbn.getPackageName(), sbn.getUserId(), ranking.getChannel().getId());
ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 0d687d4..10360a3 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -338,7 +338,7 @@
createTextClassifierEventBuilder(
TextClassifierEvent.TYPE_SMART_ACTION, session.resultId)
.setEntityTypes(ConversationAction.TYPE_TEXT_REPLY)
- .setScore(session.repliesScores.getOrDefault(reply, 0f))
+ .setScores(session.repliesScores.getOrDefault(reply, 0f))
.build();
mTextClassifier.onTextClassifierEvent(textClassifierEvent);
}
@@ -381,11 +381,9 @@
.build();
}
- private TextClassifierEvent.Builder createTextClassifierEventBuilder(
+ private TextClassifierEvent.ConversationActionsEvent.Builder createTextClassifierEventBuilder(
int eventType, String resultId) {
- return new TextClassifierEvent.Builder(
- TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType)
- .setEventTime(System.currentTimeMillis())
+ return new TextClassifierEvent.ConversationActionsEvent.Builder(eventType)
.setEventContext(
new TextClassificationContext.Builder(
mContext.getPackageName(), TextClassifier.WIDGET_TYPE_NOTIFICATION)
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
index ebcaee8..dfa1ea0 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
@@ -330,7 +330,9 @@
List<TextClassifierEvent> events = argumentCaptor.getAllValues();
assertTextClassifierEvent(events.get(0), TextClassifierEvent.TYPE_ACTIONS_GENERATED);
assertTextClassifierEvent(events.get(1), TextClassifierEvent.TYPE_SMART_ACTION);
- assertThat(events.get(1).getScore()).isEqualTo(SCORE);
+ float[] scores = events.get(1).getScores();
+ assertThat(scores).hasLength(1);
+ assertThat(scores[0]).isEqualTo(SCORE);
}
@Test
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
index 64adc0d..af0e3bb 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
@@ -65,6 +65,7 @@
import com.android.internal.util.MessageUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.internal.util.TrafficStatsConstants;
import com.android.internal.util.WakeupMessage;
import java.io.FileDescriptor;
@@ -329,7 +330,8 @@
}
private boolean initUdpSocket() {
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_DHCP);
+ final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_DHCP);
try {
mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
SocketUtils.bindSocketToInterface(mUdpSock, mIfaceName);
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
index 8832eaa..d21b5f7 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
@@ -16,7 +16,6 @@
package android.net.dhcp;
-import static android.net.TrafficStats.TAG_SYSTEM_DHCP_SERVER;
import static android.net.dhcp.DhcpPacket.DHCP_CLIENT;
import static android.net.dhcp.DhcpPacket.DHCP_HOST_NAME;
import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
@@ -33,6 +32,7 @@
import static android.system.OsConstants.SO_BROADCAST;
import static android.system.OsConstants.SO_REUSEADDR;
+import static com.android.internal.util.TrafficStatsConstants.TAG_SYSTEM_DHCP_SERVER;
import static com.android.server.util.NetworkStackConstants.INFINITE_LEASE;
import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ALL;
import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ANY;
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 2a61250..27d4203 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -98,6 +98,7 @@
import com.android.internal.util.RingBufferIndices;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.internal.util.TrafficStatsConstants;
import com.android.networkstack.R;
import com.android.networkstack.metrics.DataStallDetectionStats;
import com.android.networkstack.metrics.DataStallStatsUtils;
@@ -1478,7 +1479,8 @@
int httpResponseCode = CaptivePortalProbeResult.FAILED_CODE;
String redirectUrl = null;
final Stopwatch probeTimer = new Stopwatch().start();
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+ final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_PROBE);
try {
urlConnection = (HttpURLConnection) mNetwork.openConnection(url);
urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
diff --git a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
index 87b5b57..4f4aef0 100644
--- a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
@@ -76,11 +76,13 @@
public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
final Intent intent = getShowAdminSupportDetailsIntent(context, admin);
int targetUserId = UserHandle.myUserId();
- if (admin != null && admin.user != null
- && isCurrentUserOrProfile(context, admin.user.getIdentifier())) {
- targetUserId = admin.user.getIdentifier();
+ if (admin != null) {
+ if (admin.user != null
+ && isCurrentUserOrProfile(context, admin.user.getIdentifier())) {
+ targetUserId = admin.user.getIdentifier();
+ }
+ intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
}
- intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
context.startActivityAsUser(intent, UserHandle.of(targetUserId));
}
diff --git a/packages/SettingsLib/res/layout/settings_dialog_title.xml b/packages/SettingsLib/res/layout/settings_dialog_title.xml
new file mode 100644
index 0000000..1e065e0
--- /dev/null
+++ b/packages/SettingsLib/res/layout/settings_dialog_title.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/settings_title_panel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/settings_title_template"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingStart="?android:attr/dialogPreferredPadding"
+ android:paddingEnd="?android:attr/dialogPreferredPadding"
+ android:paddingTop="@*android:dimen/dialog_padding_top_material">
+
+ <ImageView
+ android:id="@+id/settings_icon"
+ android:layout_width="24dip"
+ android:layout_height="24dip"
+ android:layout_marginBottom="12dip" />
+
+ <TextView
+ android:id="@+id/settings_title"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="center"
+ style="?android:attr/windowTitleStyle" />
+ </LinearLayout>
+
+ <Space
+ android:id="@+id/settings_title_divider"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="@*android:dimen/dialog_title_divider_material" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
index eff02d2..257943e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -83,6 +83,8 @@
// Dual tone implies that battery level is a clipped overlay over top of the whole shape
private var dualTone = false
+ private var batteryLevel = 0
+
private val invalidateRunnable: () -> Unit = {
invalidateSelf()
}
@@ -177,9 +179,9 @@
unifiedPath.reset()
levelPath.reset()
levelRect.set(fillRect)
- val fillFraction = level / 100f
+ val fillFraction = batteryLevel / 100f
val fillTop =
- if (level >= 95)
+ if (batteryLevel >= 95)
fillRect.top
else
fillRect.top + (fillRect.height() * (1 - fillFraction))
@@ -223,7 +225,7 @@
fillPaint.color = levelColor
// Show colorError below this level
- if (level <= Companion.CRITICAL_LEVEL && !charging) {
+ if (batteryLevel <= Companion.CRITICAL_LEVEL && !charging) {
c.save()
c.clipPath(scaledFill)
c.drawPath(levelPath, fillPaint)
@@ -310,13 +312,13 @@
*/
public open fun setBatteryLevel(l: Int) {
invertFillIcon = if (l >= 67) true else if (l <= 33) false else invertFillIcon
- level = l
- levelColor = batteryColorForLevel(level)
+ batteryLevel = l
+ levelColor = batteryColorForLevel(batteryLevel)
invalidateSelf()
}
public fun getBatteryLevel(): Int {
- return level
+ return batteryLevel
}
override fun onBoundsChange(bounds: Rect?) {
@@ -343,7 +345,7 @@
dualToneBackgroundFill.color = bgColor
// Also update the level color, since fillColor may have changed
- levelColor = batteryColorForLevel(level)
+ levelColor = batteryColorForLevel(batteryLevel)
invalidateSelf()
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 2b5a4e0..11c799e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -16,6 +16,7 @@
package com.android.settingslib;
+import static android.app.admin.DevicePolicyManager.EXTRA_RESTRICTION;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
@@ -28,11 +29,13 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.UserHandle;
@@ -42,6 +45,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -283,6 +287,26 @@
assertThat(profile).isNull();
}
+ @Test
+ public void sendShowAdminSupportDetailsIntent_extraRestrictionProvided() {
+ EnforcedAdmin enforcedAdmin = new EnforcedAdmin();
+ enforcedAdmin.enforcedRestriction = "Dummy";
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, enforcedAdmin);
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).startActivityAsUser(intentCaptor.capture(), any());
+ assertThat(intentCaptor.getValue().getExtra(EXTRA_RESTRICTION)).isEqualTo("Dummy");
+ }
+
+ @Test
+ public void sendShowAdminSupportDetailsIntent_noExtraRestriction() {
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, null);
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).startActivityAsUser(intentCaptor.capture(), any());
+ assertThat(intentCaptor.getValue().getExtra(EXTRA_RESTRICTION)).isNull();
+ }
+
private UserInfo setUpUser(int userId, ComponentName[] admins) {
UserInfo userInfo = new UserInfo(userId, "primary", 0);
when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/analog_thumbnail.png
similarity index 100%
rename from packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_thumbnail.png
rename to packages/SystemUI/res-keyguard/drawable-xxxhdpi/analog_thumbnail.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png
deleted file mode 100644
index 2bfd655..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_frame.xml b/packages/SystemUI/res-keyguard/drawable/analog_frame.xml
new file mode 100644
index 0000000..a663ac8
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/analog_frame.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="250dp"
+ android:width="250dp"
+ android:viewportHeight="380"
+ android:viewportWidth="380">
+ <path android:fillColor="#000000" android:pathData="M190,190m0,2a2,2 0,1 1,0 -4a2,2 0,1 1,0 4"/>
+</vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml b/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml
new file mode 100644
index 0000000..c7b6d60
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="250dp"
+ android:width="250dp"
+ android:viewportHeight="380"
+ android:viewportWidth="380">
+ <path android:fillColor="#777777" android:fillType="evenOdd" android:pathData="M203,190C203,185.398 200.608,181.354 197,179.044L197,58C197,54.134 193.866,51 190,51C186.134,51 183,54.134 183,58L183,179.043C179.392,181.354 177,185.397 177,190C177,197.18 182.82,203 190,203C197.18,203 203,197.18 203,190Z"/>
+</vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml b/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml
new file mode 100644
index 0000000..458275b
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="250dp"
+ android:width="250dp"
+ android:viewportHeight="380"
+ android:viewportWidth="380">
+ <path android:fillColor="#FFFFFF" android:pathData="M192,182.252C195.45,183.14 198,186.272 198,190C198,194.418 194.418,198 190,198C185.582,198 182,194.418 182,190C182,186.272 184.55,183.14 188,182.252L188,10C188,8.895 188.895,8 190,8C191.105,8 192,8.895 192,10L192,182.252Z"/>
+</vector>
diff --git a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml b/packages/SystemUI/res-keyguard/layout/analog_clock.xml
similarity index 67%
rename from packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
rename to packages/SystemUI/res-keyguard/layout/analog_clock.xml
index dd25df8..cf6d35ee2 100644
--- a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/analog_clock.xml
@@ -35,9 +35,27 @@
android:format24Hour="@string/keyguard_widget_24_hours_format"
android:elegantTextHeight="false"
/>
- <com.android.keyguard.clock.StretchAnalogClock
+ <com.android.keyguard.clock.ImageClock
android:id="@+id/analog_clock"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ >
+ <ImageView
+ android:id="@+id/hour_hand"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/analog_hour_hand"
+ />
+ <ImageView
+ android:id="@+id/minute_hand"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/analog_minute_hand"
+ />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/analog_frame"
+ />
+ </com.android.keyguard.clock.ImageClock>
</com.android.keyguard.clock.ClockLayout>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 4738887..1e98189 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -413,9 +413,6 @@
<string name="clock_title_bubble" translatable="false">Bubble</string>
<!-- Title for Stretch clock face that will appear in the picker app next to a preview image of
the clock face. [CHAR LIMIT=8] -->
- <string name="clock_title_stretch" translatable="false">Stretch</string>
- <!-- Title for Typographic clock face that will appear in the picker app next to a preview image of
- the clock face. [CHAR LIMIT=8] -->
- <string name="clock_title_type" translatable="false">Type</string>
+ <string name="clock_title_analog" translatable="false">Analog</string>
</resources>
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index f34161e..81d44cf 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -44,8 +44,7 @@
android:padding="0dp"
android:gravity="center"
android:ellipsize="marquee"
- android:textAppearance="@style/TextAppearance.QS.TileLabel"
- android:textColor="?android:attr/textColorPrimary"/>
+ android:textAppearance="@style/TextAppearance.QS.TileLabel"/>
<ImageView android:id="@+id/restricted_padlock"
android:layout_width="@dimen/qs_tile_text_size"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 444cabfc..f121c8e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1331,6 +1331,14 @@
<!-- Content description for accessibility: Clear the odi caption tool tip. [CHAR LIMIT=NONE] -->
<string name="accessibility_volume_close_odi_captions_tip">Close captions tip</string>
+ <!-- Content description for accessibility: Captions button. [CHAR LIMIT=NONE] -->
+ <string name="volume_odi_captions_content_description">Captions overlay</string>
+
+ <!-- Content description for accessibility: Hint if click will enable. [CHAR LIMIT=NONE] -->
+ <string name="volume_odi_captions_hint_enable">enable</string>
+ <!-- Content description for accessibility: Hint if click will disable. [CHAR LIMIT=NONE] -->
+ <string name="volume_odi_captions_hint_disable">disable</string>
+
<!-- content description for audio output chooser [CHAR LIMIT=NONE]-->
<string name="accessibility_output_chooser">Switch output device</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 64517ba..eca3926 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -16,14 +16,22 @@
package com.android.keyguard;
+import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
+import static android.telephony.PhoneStateListener.LISTEN_NONE;
+
+import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
+
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -36,6 +44,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -113,6 +122,17 @@
}
};
+ private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ mActiveMobileDataSubscription = subId;
+ if (mKeyguardUpdateMonitor != null) {
+ updateCarrierText();
+ }
+ }
+ };
+
/**
* The status of this lock screen. Primarily used for widgets on LockScreen.
*/
@@ -200,6 +220,8 @@
* @param callback Callback to provide text updates
*/
public void setListening(CarrierTextCallback callback) {
+ TelephonyManager telephonyManager = ((TelephonyManager) mContext
+ .getSystemService(Context.TELEPHONY_SERVICE));
if (callback != null) {
mCarrierTextCallback = callback;
if (ConnectivityManager.from(mContext).isNetworkSupported(
@@ -207,6 +229,8 @@
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
mKeyguardUpdateMonitor.registerCallback(mCallback);
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
+ telephonyManager.listen(mPhoneStateListener,
+ LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
} else {
// Don't listen and clear out the text when the device isn't a phone.
mKeyguardUpdateMonitor = null;
@@ -218,6 +242,35 @@
mKeyguardUpdateMonitor.removeCallback(mCallback);
mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
}
+ telephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
+ }
+ }
+
+ /**
+ * STOPSHIP(b/130246708) remove when no longer needed for testing purpose.
+ * @param subscriptions
+ */
+ private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) {
+ if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) {
+ SubscriptionInfo info1 = subscriptions.get(0);
+ SubscriptionInfo info2 = subscriptions.get(1);
+ if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) {
+ // If both subscriptions are primary, show both.
+ if (!info1.isOpportunistic() && !info2.isOpportunistic()) return;
+
+ // If carrier required, always show signal bar of primary subscription.
+ // Otherwise, show whichever subscription is currently active for Internet.
+ boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig()
+ .getBoolean(CarrierConfigManager
+ .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN);
+ if (alwaysShowPrimary) {
+ subscriptions.remove(info1.isOpportunistic() ? info1 : info2);
+ } else {
+ subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription
+ ? info2 : info1);
+ }
+
+ }
}
}
@@ -226,7 +279,17 @@
boolean anySimReadyAndInService = false;
CharSequence displayText = null;
- List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
+ // STOPSHIP(b/130246708) revert to mKeyguardUpdateMonitor.getSubscriptionInfo(false).
+ SubscriptionManager subscriptionManager = ((SubscriptionManager) mContext.getSystemService(
+ Context.TELEPHONY_SUBSCRIPTION_SERVICE));
+ List<SubscriptionInfo> subs = subscriptionManager.getActiveSubscriptionInfoList(false);
+
+ if (subs == null) {
+ subs = new ArrayList<>();
+ } else {
+ filterMobileSubscriptionInSameGroup(subs);
+ }
+
final int numSubs = subs.size();
final int[] subsIds = new int[numSubs];
// This array will contain in position i, the index of subscription in slot ID i.
@@ -311,20 +374,23 @@
displayText = updateCarrierTextWithSimIoError(displayText, carrierNames, subOrderBySlot,
allSimsMissing);
+ boolean airplaneMode = false;
// APM (airplane mode) != no carrier state. There are carrier services
// (e.g. WFC = Wi-Fi calling) which may operate in APM.
if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
displayText = getAirplaneModeMessage();
+ airplaneMode = true;
}
- if (TextUtils.isEmpty(displayText)) {
+ if (TextUtils.isEmpty(displayText) && !airplaneMode) {
displayText = TextUtils.join(mSeparator, carrierNames);
}
final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
displayText,
carrierNames,
!allSimsMissing,
- subsIds);
+ subsIds,
+ airplaneMode);
postToCallback(info);
}
@@ -525,14 +591,22 @@
public final CharSequence[] listOfCarriers;
public final boolean anySimReady;
public final int[] subscriptionIds;
+ public boolean airplaneMode;
@VisibleForTesting
public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
boolean anySimReady, int[] subscriptionIds) {
+ this(carrierText, listOfCarriers, anySimReady, subscriptionIds, false);
+ }
+
+ @VisibleForTesting
+ public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
+ boolean anySimReady, int[] subscriptionIds, boolean airplaneMode) {
this.carrierText = carrierText;
this.listOfCarriers = listOfCarriers;
this.anySimReady = anySimReady;
this.subscriptionIds = subscriptionIds;
+ this.airplaneMode = airplaneMode;
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fd55708..1d19fec 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -665,9 +665,9 @@
boolean wasRunning = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING;
boolean isRunning = fingerprintRunningState == BIOMETRIC_STATE_RUNNING;
mFingerprintRunningState = fingerprintRunningState;
- if (DEBUG) Log.v(TAG, "Fingerprint State: " + mFingerprintRunningState);
+ Log.d(TAG, "fingerprintRunningState: " + mFingerprintRunningState);
// Clients of KeyguardUpdateMonitor don't care about the internal state about the
- // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+ // asynchronousness of the cancel cycle. So only notify them if the actually running state
// has changed.
if (wasRunning != isRunning) {
notifyFingerprintRunningStateChanged();
@@ -818,9 +818,9 @@
boolean wasRunning = mFaceRunningState == BIOMETRIC_STATE_RUNNING;
boolean isRunning = faceRunningState == BIOMETRIC_STATE_RUNNING;
mFaceRunningState = faceRunningState;
- if (DEBUG) Log.v(TAG, "Face State: " + mFaceRunningState);
+ Log.d(TAG, "faceRunningState: " + mFaceRunningState);
// Clients of KeyguardUpdateMonitor don't care about the internal state or about the
- // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+ // asynchronousness of the cancel cycle. So only notify them if the actually running state
// has changed.
if (wasRunning != isRunning) {
notifyFaceRunningStateChanged();
@@ -2045,7 +2045,7 @@
*/
public void onKeyguardVisibilityChanged(boolean showing) {
checkIsHandlerThread();
- if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
+ Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
mKeyguardIsVisible = showing;
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
similarity index 90%
rename from packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
rename to packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
index 81b6a60..1652121 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
@@ -35,7 +35,7 @@
/**
* Controller for Stretch clock that can appear on lock screen and AOD.
*/
-public class StretchAnalogClockController implements ClockPlugin {
+public class AnalogClockController implements ClockPlugin {
/**
* Resources used to get title and thumbnail.
@@ -60,9 +60,9 @@
/**
* Custom clock shown on AOD screen and behind stack scroller on lock.
*/
- private View mBigClockView;
+ private ClockLayout mBigClockView;
private TextClock mDigitalClock;
- private StretchAnalogClock mAnalogClock;
+ private ImageClock mAnalogClock;
/**
* Small clock shown on lock screen above stack scroller.
@@ -82,7 +82,7 @@
* @param inflater Inflater used to inflate custom clock views.
* @param colorExtractor Extracts accent color from wallpaper.
*/
- public StretchAnalogClockController(Resources res, LayoutInflater inflater,
+ public AnalogClockController(Resources res, LayoutInflater inflater,
SysuiColorExtractor colorExtractor) {
mResources = res;
mLayoutInflater = inflater;
@@ -90,7 +90,7 @@
}
private void createViews() {
- mBigClockView = mLayoutInflater.inflate(R.layout.stretchanalog_clock, null);
+ mBigClockView = (ClockLayout) mLayoutInflater.inflate(R.layout.analog_clock, null);
mAnalogClock = mBigClockView.findViewById(R.id.analog_clock);
mDigitalClock = mBigClockView.findViewById(R.id.digital_clock);
@@ -114,17 +114,17 @@
@Override
public String getName() {
- return "stretch";
+ return "analog";
}
@Override
public String getTitle() {
- return mResources.getString(R.string.clock_title_stretch);
+ return mResources.getString(R.string.clock_title_analog);
}
@Override
public Bitmap getThumbnail() {
- return BitmapFactory.decodeResource(mResources, R.drawable.stretch_thumbnail);
+ return BitmapFactory.decodeResource(mResources, R.drawable.analog_thumbnail);
}
@Override
@@ -175,13 +175,14 @@
}
final int length = colorPalette.length;
mDigitalClock.setTextColor(colorPalette[Math.max(0, length - 5)]);
- mAnalogClock.setClockColor(colorPalette[Math.max(0, length - 5)],
+ mAnalogClock.setClockColors(colorPalette[Math.max(0, length - 5)],
colorPalette[Math.max(0, length - 2)]);
}
@Override
public void onTimeTick() {
mAnalogClock.onTimeChanged();
+ mBigClockView.onTimeChanged();
mDigitalClock.refresh();
mLockClock.refresh();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index d30f45f..6069a5e 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -60,7 +60,7 @@
/**
* Custom clock shown on AOD screen and behind stack scroller on lock.
*/
- private View mView;
+ private ClockLayout mView;
private TextClock mDigitalClock;
private ImageClock mAnalogClock;
@@ -90,7 +90,7 @@
}
private void createViews() {
- mView = mLayoutInflater.inflate(R.layout.bubble_clock, null);
+ mView = (ClockLayout) mLayoutInflater.inflate(R.layout.bubble_clock, null);
mDigitalClock = (TextClock) mView.findViewById(R.id.digital_clock);
mAnalogClock = (ImageClock) mView.findViewById(R.id.analog_clock);
@@ -186,6 +186,7 @@
@Override
public void onTimeTick() {
mAnalogClock.onTimeChanged();
+ mView.onTimeChanged();
mDigitalClock.refresh();
mLockClock.refresh();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
index 7ffee5d..55088a8 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
@@ -32,6 +32,7 @@
*/
public class ClockLayout extends FrameLayout {
+ private static final int ANALOG_CLOCK_SHIFT_FACTOR = 3;
/**
* Clock face views.
*/
@@ -73,7 +74,14 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
+ positionChildren();
+ }
+ void onTimeChanged() {
+ positionChildren();
+ }
+
+ private void positionChildren() {
final float offsetX = getBurnInOffset(mBurnInPreventionOffsetX * 2, true)
- mBurnInPreventionOffsetX;
final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY * 2, false)
@@ -89,9 +97,9 @@
// Put the analog clock in the middle of the screen.
if (mAnalogClock != null) {
mAnalogClock.setX(Math.max(0f, 0.5f * (getWidth() - mAnalogClock.getWidth()))
- + offsetX);
+ + ANALOG_CLOCK_SHIFT_FACTOR * offsetX);
mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight()))
- + offsetY);
+ + ANALOG_CLOCK_SHIFT_FACTOR * offsetY);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index e373ca1..06488b8 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -142,8 +142,7 @@
addBuiltinClock(() -> new DefaultClockController(res, layoutInflater, colorExtractor));
addBuiltinClock(() -> new BubbleClockController(res, layoutInflater, colorExtractor));
- addBuiltinClock(() -> new StretchAnalogClockController(res, layoutInflater,
- colorExtractor));
+ addBuiltinClock(() -> new AnalogClockController(res, layoutInflater, colorExtractor));
// Store the size of the display for generation of clock preview.
DisplayMetrics dm = res.getDisplayMetrics();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
deleted file mode 100644
index 8cdd632..0000000
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.keyguard.clock;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.view.View;
-
-import java.util.Calendar;
-import java.util.TimeZone;
-
-/**
- * Analog clock where the minute hand extends off of the screen.
- */
-public class StretchAnalogClock extends View {
-
- private static final int DEFAULT_COLOR = Color.parseColor("#F5C983");
- private static final float HOUR_STROKE_WIDTH = 60f;
- private static final float MINUTE_STROKE_WIDTH = 20f;
- private static final float CENTER_GAP_AND_CIRCLE_RADIUS = 80f;
-
- private final Paint mHourPaint = new Paint();
- private final Paint mMinutePaint = new Paint();
- private Calendar mTime = Calendar.getInstance(TimeZone.getDefault());
- private TimeZone mTimeZone;
-
- public StretchAnalogClock(Context context) {
- this(context, null);
- }
-
- public StretchAnalogClock(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public StretchAnalogClock(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public StretchAnalogClock(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init();
- }
-
- /**
- * Call when the time changes to update the clock hands.
- */
- public void onTimeChanged() {
- mTime.setTimeInMillis(System.currentTimeMillis());
- invalidate();
- }
-
- /**
- * Call when the time zone has changed to update clock hands.
- *
- * @param timeZone The updated time zone that will be used.
- */
- public void onTimeZoneChanged(TimeZone timeZone) {
- mTime.setTimeZone(timeZone);
- }
-
- /**
- * Set the colors to use on the clock face.
- * @param dark Darker color obtained from color palette.
- * @param light Lighter color obtained from color palette.
- */
- public void setClockColor(int dark, int light) {
- mHourPaint.setColor(dark);
- invalidate();
- }
-
- private void init() {
- mHourPaint.setColor(DEFAULT_COLOR);
- mHourPaint.setStrokeWidth(HOUR_STROKE_WIDTH);
- mHourPaint.setAntiAlias(true);
- mHourPaint.setStrokeCap(Paint.Cap.ROUND);
-
- mMinutePaint.setColor(Color.WHITE);
- mMinutePaint.setStrokeWidth(MINUTE_STROKE_WIDTH);
- mMinutePaint.setAntiAlias(true);
- mMinutePaint.setStrokeCap(Paint.Cap.ROUND);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- final float centerX = getWidth() / 2f;
- final float centerY = getHeight() / 2f;
-
- final float minutesRotation = mTime.get(Calendar.MINUTE) * 6f;
- final float hoursRotation = mTime.get(Calendar.HOUR) * 30
- + mTime.get(Calendar.MINUTE) * 0.5f;
-
- // Compute length of clock hands. Hour hand is 60% the length from center to edge
- // and minute hand is twice the length to make sure it extends past screen edge.
- double sMinuteHandLengthFactor = Math.sin(2d * Math.PI * minutesRotation / 360d);
- float sMinuteHandLength = (float) (2d * (centerY + (centerX - centerY)
- * sMinuteHandLengthFactor * sMinuteHandLengthFactor));
- double sHourHandLengthFactor = Math.sin(2d * Math.PI * hoursRotation / 360d);
- float sHourHandLength = (float) (0.6d * (centerY + (centerX - centerY)
- * sHourHandLengthFactor * sHourHandLengthFactor));
-
- canvas.save();
-
- canvas.rotate(minutesRotation, centerX, centerY);
- canvas.drawLine(
- centerX,
- centerY + CENTER_GAP_AND_CIRCLE_RADIUS,
- centerX,
- centerY - sMinuteHandLength,
- mMinutePaint);
-
- canvas.rotate(hoursRotation - minutesRotation, centerX, centerY);
- canvas.drawLine(
- centerX,
- centerY + CENTER_GAP_AND_CIRCLE_RADIUS,
- centerX,
- centerY - sHourHandLength,
- mHourPaint);
-
- canvas.restore();
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
- onTimeChanged();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 665df77..0332477 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -16,47 +16,65 @@
package com.android.systemui.bubbles;
+import android.os.UserHandle;
import android.view.LayoutInflater;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import java.util.Objects;
+
/**
* Encapsulates the data and UI elements of a bubble.
*/
class Bubble {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "Bubble";
+
private final String mKey;
+ private final String mGroupId;
private final BubbleExpandedView.OnBubbleBlockedListener mListener;
private boolean mInflated;
-
- public BubbleView iconView;
- public BubbleExpandedView expandedView;
public NotificationEntry entry;
+ BubbleView iconView;
+ BubbleExpandedView expandedView;
+
+ private static String groupId(NotificationEntry entry) {
+ UserHandle user = entry.notification.getUser();
+ return user.getIdentifier() + '|' + entry.notification.getPackageName();
+ }
Bubble(NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener) {
entry = e;
mKey = e.key;
+ mGroupId = groupId(e);
mListener = listener;
}
- /** @deprecated use the other constructor to defer View creation. */
- @Deprecated
- Bubble(NotificationEntry e, LayoutInflater inflater, BubbleStackView stackView,
- BubbleExpandedView.OnBubbleBlockedListener listener) {
- this(e, listener);
- inflate(inflater, stackView);
- }
-
public String getKey() {
return mKey;
}
+ public String getGroupId() {
+ return mGroupId;
+ }
+
+ public String getPackageName() {
+ return entry.notification.getPackageName();
+ }
+
boolean isInflated() {
return mInflated;
}
+ public void updateDotVisibility() {
+ if (iconView != null) {
+ iconView.updateDotVisibility();
+ }
+ }
+
void inflate(LayoutInflater inflater, BubbleStackView stackView) {
if (mInflated) {
return;
@@ -73,10 +91,32 @@
mInflated = true;
}
+ void setDismissed() {
+ entry.setBubbleDismissed(true);
+ // TODO: move this somewhere where it can be guaranteed not to run until safe from flicker
+ if (expandedView != null) {
+ expandedView.cleanUpExpandedState();
+ }
+ }
+
void setEntry(NotificationEntry entry) {
+ this.entry = entry;
if (mInflated) {
iconView.update(entry);
expandedView.update(entry);
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Bubble)) return false;
+ Bubble bubble = (Bubble) o;
+ return Objects.equals(mKey, bubble.mKey);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mKey);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 0fcc950..acdcfb2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -77,8 +77,7 @@
* The controller manages addition, removal, and visible state of bubbles on screen.
*/
@Singleton
-public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener,
- ConfigurationController.ConfigurationListener {
+public class BubbleController implements ConfigurationController.ConfigurationListener {
private static final String TAG = "BubbleController";
@@ -174,6 +173,10 @@
@Override
public void onStateChanged(int newState) {
mState = newState;
+ boolean shouldCollapse = (mState != SHADE);
+ if (shouldCollapse) {
+ collapseStack();
+ }
updateVisibility();
}
}
@@ -236,7 +239,6 @@
if (mExpandListener != null) {
mStackView.setExpandListener(mExpandListener);
}
- mStackView.setOnBlockedListener(this);
}
}
@@ -284,28 +286,38 @@
if (mStackView == null) {
return false;
}
- for (Bubble bubble : mBubbleData.getBubbles()) {
- if (!bubble.entry.isBubbleDismissed()) {
- return true;
- }
- }
- return false;
+ return mBubbleData.hasBubbles();
}
/**
* Whether the stack of bubbles is expanded or not.
*/
public boolean isStackExpanded() {
- return mStackView != null && mStackView.isExpanded();
+ return mBubbleData.isExpanded();
+ }
+
+ /**
+ * Tell the stack of bubbles to expand.
+ */
+ public void expandStack() {
+ mBubbleData.setExpanded(true);
}
/**
* Tell the stack of bubbles to collapse.
*/
public void collapseStack() {
- if (mStackView != null) {
- mStackView.collapseStack();
- }
+ mBubbleData.setExpanded(false /* expanded */);
+ }
+
+ void selectBubble(Bubble bubble) {
+ mBubbleData.setSelectedBubble(bubble);
+ }
+
+ @VisibleForTesting
+ void selectBubble(String key) {
+ Bubble bubble = mBubbleData.getBubbleWithKey(key);
+ selectBubble(bubble);
}
/**
@@ -314,8 +326,10 @@
* @param notificationKey the notification key for the bubble to be selected
*/
public void expandStackAndSelectBubble(String notificationKey) {
- if (mStackView != null && mBubbleData.getBubble(notificationKey) != null) {
- mStackView.setExpandedBubble(notificationKey);
+ Bubble bubble = mBubbleData.getBubbleWithKey(notificationKey);
+ if (bubble != null) {
+ mBubbleData.setSelectedBubble(bubble);
+ mBubbleData.setExpanded(true);
}
}
@@ -323,13 +337,7 @@
* Tell the stack of bubbles to be dismissed, this will remove all of the bubbles in the stack.
*/
void dismissStack(@DismissReason int reason) {
- if (mStackView == null) {
- return;
- }
- mStackView.stackDismissed(reason);
-
- updateVisibility();
- mNotificationEntryManager.updateNotifications();
+ mBubbleData.dismissAll(reason);
}
/**
@@ -348,20 +356,7 @@
* @param notif the notification associated with this bubble.
*/
void updateBubble(NotificationEntry notif) {
- if (mStackView != null && mBubbleData.getBubble(notif.key) != null) {
- // It's an update
- mStackView.updateBubble(notif);
- } else {
- // It's new
- ensureStackViewCreated();
- mStackView.addBubble(notif);
- }
- Bubble bubble = mBubbleData.getBubble(notif.key);
- if (shouldAutoExpand(notif)) {
- mStackView.setSelectedBubble(bubble);
- mStackView.setExpanded(true);
- }
- updateVisibility();
+ mBubbleData.notificationEntryUpdated(notif);
}
/**
@@ -371,23 +366,10 @@
*/
@MainThread
void removeBubble(String key, int reason) {
- if (mStackView != null) {
- mStackView.removeBubble(key, reason);
- }
- mNotificationEntryManager.updateNotifications();
- updateVisibility();
- }
-
- @Override
- public void onBubbleBlocked(NotificationEntry entry) {
- Object[] bubbles = mBubbleData.getBubbles().toArray();
- for (int i = 0; i < bubbles.length; i++) {
- NotificationEntry e = ((Bubble) bubbles[i]).entry;
- boolean samePackage = entry.notification.getPackageName().equals(
- e.notification.getPackageName());
- if (samePackage) {
- removeBubble(entry.key, DISMISS_BLOCKED);
- }
+ // TEMP: refactor to change this to pass entry
+ Bubble bubble = mBubbleData.getBubbleWithKey(key);
+ if (bubble != null) {
+ mBubbleData.notificationEntryRemoved(bubble.entry, reason);
}
}
@@ -424,7 +406,6 @@
updateShowInShadeForSuppressNotification(entry);
entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed
updateBubble(entry);
- mStackView.updateDotVisibility(entry.key);
}
}
@@ -446,44 +427,57 @@
}
};
+ @SuppressWarnings("FieldCanBeLocal")
private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() {
+
@Override
public void onBubbleAdded(Bubble bubble) {
-
+ ensureStackViewCreated();
+ mStackView.addBubble(bubble);
}
@Override
public void onBubbleRemoved(Bubble bubble, int reason) {
-
+ if (mStackView != null) {
+ mStackView.removeBubble(bubble);
+ }
}
public void onBubbleUpdated(Bubble bubble) {
-
+ if (mStackView != null) {
+ mStackView.updateBubble(bubble);
+ }
}
@Override
public void onOrderChanged(List<Bubble> bubbles) {
-
}
@Override
public void onSelectionChanged(Bubble selectedBubble) {
-
+ if (mStackView != null) {
+ mStackView.setSelectedBubble(selectedBubble);
+ }
}
@Override
public void onExpandedChanged(boolean expanded) {
-
+ if (mStackView != null) {
+ mStackView.setExpanded(expanded);
+ }
}
@Override
public void showFlyoutText(Bubble bubble, String text) {
-
+ if (mStackView != null) {
+ mStackView.animateInFlyoutForBubble(bubble);
+ }
}
@Override
public void apply() {
-
+ mNotificationEntryManager.updateNotifications();
+ updateVisibility();
}
};
@@ -514,7 +508,6 @@
mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE);
} else if (mStackView != null) {
mStackView.setVisibility(INVISIBLE);
- collapseStack();
}
updateBubblesShowing();
}
@@ -621,14 +614,14 @@
@Override
public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
if (mStackView != null && taskInfo.displayId == Display.DEFAULT_DISPLAY) {
- mStackView.collapseStack();
+ mBubbleData.setExpanded(false);
}
}
@Override
public void onActivityLaunchOnSecondaryDisplayRerouted() {
if (mStackView != null) {
- mStackView.collapseStack();
+ mBubbleData.setExpanded(false);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index fe3f9d1..259665d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -15,14 +15,24 @@
*/
package com.android.systemui.bubbles;
-import androidx.annotation.Nullable;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.bubbles.BubbleController.DismissReason;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -33,6 +43,8 @@
@Singleton
public class BubbleData {
+ private static final String TAG = "BubbleData";
+
/**
* This interface reports changes to the state and appearance of bubbles which should be applied
* as necessary to the UI.
@@ -53,7 +65,7 @@
* A Bubble has been removed. A call to {@link #onOrderChanged(List)} will
* follow.
*/
- void onBubbleRemoved(Bubble bubble, @BubbleController.DismissReason int reason);
+ void onBubbleRemoved(Bubble bubble, @DismissReason int reason);
/**
* An existing bubble has been updated.
@@ -86,46 +98,253 @@
void apply();
}
- private HashMap<String, Bubble> mBubbles = new HashMap<>();
+ private final Context mContext;
+ private final List<Bubble> mBubbles = new ArrayList<>();
+ private Bubble mSelectedBubble;
+ private boolean mExpanded;
private Listener mListener;
@VisibleForTesting
@Inject
- public BubbleData() {}
-
- /**
- * The set of bubbles.
- */
- public Collection<Bubble> getBubbles() {
- return mBubbles.values();
+ public BubbleData(Context context) {
+ mContext = context;
}
- @Nullable
- public Bubble getBubble(String key) {
- return mBubbles.get(key);
+ public boolean hasBubbles() {
+ return !mBubbles.isEmpty();
}
- public void addBubble(Bubble b) {
- mBubbles.put(b.getKey(), b);
+ public boolean isExpanded() {
+ return mExpanded;
}
- @Nullable
- public Bubble removeBubble(String key) {
- return mBubbles.remove(key);
+ public boolean hasBubbleWithKey(String key) {
+ return getBubbleWithKey(key) != null;
}
- public void updateBubble(String key, NotificationEntry newEntry) {
- Bubble oldBubble = mBubbles.get(key);
- if (oldBubble != null) {
- oldBubble.setEntry(newEntry);
+ public void setExpanded(boolean expanded) {
+ if (setExpandedInternal(expanded)) {
+ mListener.apply();
}
}
- public void clear() {
- mBubbles.clear();
+ public void setSelectedBubble(Bubble bubble) {
+ if (setSelectedBubbleInternal(bubble)) {
+ mListener.apply();
+ }
+ }
+
+ public void notificationEntryUpdated(NotificationEntry entry) {
+ Bubble bubble = getBubbleWithKey(entry.key);
+ if (bubble == null) {
+ // Create a new bubble
+ bubble = new Bubble(entry, this::onBubbleBlocked);
+ mBubbles.add(0, bubble); // TODO: reorder/group
+ mListener.onBubbleAdded(bubble);
+ } else {
+ // Updates an existing bubble
+ bubble.setEntry(entry);
+ mListener.onBubbleUpdated(bubble);
+ }
+ if (shouldAutoExpand(entry)) {
+ setSelectedBubbleInternal(bubble);
+ if (!mExpanded) {
+ setExpandedInternal(true);
+ }
+ } else if (mSelectedBubble == null) {
+ setSelectedBubbleInternal(bubble);
+ }
+ // TODO: reorder/group
+ mListener.apply();
+ }
+
+ public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
+ int indexToRemove = indexForKey(entry.key);
+ if (indexToRemove >= 0) {
+ Bubble removed = mBubbles.remove(indexToRemove);
+ removed.setDismissed();
+ mListener.onBubbleRemoved(removed, reason);
+ maybeSendDeleteIntent(reason, removed.entry);
+
+ if (mBubbles.isEmpty()) {
+ setExpandedInternal(false);
+ setSelectedBubbleInternal(null);
+ } else if (removed == mSelectedBubble) {
+ int newIndex = Math.min(indexToRemove, mBubbles.size() - 1);
+ Bubble newSelected = mBubbles.get(newIndex);
+ setSelectedBubbleInternal(newSelected);
+ }
+ // TODO: reorder/group
+ mListener.apply();
+ }
+ }
+
+ public void dismissAll(@DismissReason int reason) {
+ boolean changed = setExpandedInternal(false);
+ while (!mBubbles.isEmpty()) {
+ Bubble bubble = mBubbles.remove(0);
+ bubble.setDismissed();
+ maybeSendDeleteIntent(reason, bubble.entry);
+ mListener.onBubbleRemoved(bubble, reason);
+ changed = true;
+ }
+ if (setSelectedBubbleInternal(null)) {
+ changed = true;
+ }
+ if (changed) {
+ // TODO: reorder/group
+ mListener.apply();
+ }
+ }
+
+ /**
+ * Requests a change to the selected bubble. Calls {@link Listener#onSelectionChanged} if
+ * the value changes.
+ *
+ * @param bubble the new selected bubble
+ * @return true if the state changed as a result
+ */
+ private boolean setSelectedBubbleInternal(Bubble bubble) {
+ if (Objects.equals(bubble, mSelectedBubble)) {
+ return false;
+ }
+ if (bubble != null && !mBubbles.contains(bubble)) {
+ Log.e(TAG, "Cannot select bubble which doesn't exist!"
+ + " (" + bubble + ") bubbles=" + mBubbles);
+ return false;
+ }
+ if (mExpanded) {
+ // TODO: bubble.markAsActive() ?
+ bubble.entry.setShowInShadeWhenBubble(false);
+ }
+ mSelectedBubble = bubble;
+ mListener.onSelectionChanged(mSelectedBubble);
+ return true;
+ }
+
+
+ /**
+ * Requests a change to the expanded state. Calls {@link Listener#onExpandedChanged} if
+ * the value changes.
+ *
+ * @param shouldExpand the new requested state
+ * @return true if the state changed as a result
+ */
+ private boolean setExpandedInternal(boolean shouldExpand) {
+ if (mExpanded == shouldExpand) {
+ return false;
+ }
+ if (shouldExpand) {
+ if (mBubbles.isEmpty()) {
+ Log.e(TAG, "Attempt to expand stack when empty!");
+ return false;
+ }
+ if (mSelectedBubble == null) {
+ Log.e(TAG, "Attempt to expand stack without selected bubble!");
+ return false;
+ }
+ // TODO: bubble.markAsActive() ?
+ mSelectedBubble.entry.setShowInShadeWhenBubble(false);
+ }
+ // TODO: reorder/regroup
+ mExpanded = shouldExpand;
+ mListener.onExpandedChanged(mExpanded);
+ return true;
+ }
+
+ private void maybeSendDeleteIntent(@DismissReason int reason, NotificationEntry entry) {
+ if (reason == BubbleController.DISMISS_USER_GESTURE) {
+ Notification.BubbleMetadata bubbleMetadata = entry.getBubbleMetadata();
+ PendingIntent deleteIntent = bubbleMetadata != null
+ ? bubbleMetadata.getDeleteIntent()
+ : null;
+ if (deleteIntent != null) {
+ try {
+ deleteIntent.send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.w(TAG, "Failed to send delete intent for bubble with key: " + entry.key);
+ }
+ }
+ }
+ }
+
+ private void onBubbleBlocked(NotificationEntry entry) {
+ boolean changed = false;
+ final String blockedPackage = entry.notification.getPackageName();
+ for (Iterator<Bubble> i = mBubbles.iterator(); i.hasNext(); ) {
+ Bubble bubble = i.next();
+ if (bubble.getPackageName().equals(blockedPackage)) {
+ i.remove();
+ mListener.onBubbleRemoved(bubble, BubbleController.DISMISS_BLOCKED);
+ changed = true;
+ }
+ }
+ if (changed) {
+ // TODO: reorder/group
+ mListener.apply();
+ }
+ }
+
+ private int indexForKey(String key) {
+ for (int i = 0; i < mBubbles.size(); i++) {
+ Bubble bubble = mBubbles.get(i);
+ if (bubble.getKey().equals(key)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private Bubble removeBubbleWithKey(String key) {
+ for (int i = 0; i < mBubbles.size(); i++) {
+ Bubble bubble = mBubbles.get(i);
+ if (bubble.getKey().equals(key)) {
+ mBubbles.remove(i);
+ return bubble;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * The set of bubbles.
+ *
+ * @deprecated
+ */
+ @Deprecated
+ public Collection<Bubble> getBubbles() {
+ return Collections.unmodifiableList(mBubbles);
+ }
+
+ @VisibleForTesting(visibility = PRIVATE)
+ Bubble getBubbleWithKey(String key) {
+ for (int i = 0; i < mBubbles.size(); i++) {
+ Bubble bubble = mBubbles.get(i);
+ if (bubble.getKey().equals(key)) {
+ return bubble;
+ }
+ }
+ return null;
}
public void setListener(Listener listener) {
mListener = listener;
}
-}
+
+ boolean shouldAutoExpand(NotificationEntry entry) {
+ Notification.BubbleMetadata metadata = entry.getBubbleMetadata();
+ return metadata != null && metadata.getAutoExpandBubble()
+ && isForegroundApp(entry.notification.getPackageName());
+ }
+
+ /**
+ * Return true if the applications with the package name is running in foreground.
+ *
+ * @param pkgName application package name.
+ */
+ boolean isForegroundApp(String pkgName) {
+ ActivityManager am = mContext.getSystemService(ActivityManager.class);
+ List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1 /* maxNum */);
+ return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 424cd55..18b2e37 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -20,8 +20,6 @@
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import android.annotation.NonNull;
-import android.app.Notification;
-import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
@@ -54,9 +52,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.ViewClippingUtil;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.bubbles.BubbleController.DismissReason;
import com.android.systemui.bubbles.animation.ExpandedAnimationController;
import com.android.systemui.bubbles.animation.PhysicsAnimationLayout;
import com.android.systemui.bubbles.animation.StackAnimationController;
@@ -359,14 +355,13 @@
}
switch (action) {
case AccessibilityNodeInfo.ACTION_DISMISS:
- Dependency.get(BubbleController.class).dismissStack(
- BubbleController.DISMISS_ACCESSIBILITY_ACTION);
+ mBubbleData.dismissAll(BubbleController.DISMISS_ACCESSIBILITY_ACTION);
return true;
case AccessibilityNodeInfo.ACTION_COLLAPSE:
- collapseStack();
+ mBubbleData.setExpanded(false);
return true;
case AccessibilityNodeInfo.ACTION_EXPAND:
- expandStack();
+ mBubbleData.setExpanded(true);
return true;
}
return false;
@@ -393,9 +388,9 @@
* @param key the {@link NotificationEntry#key} associated with the bubble.
*/
public void updateDotVisibility(String key) {
- Bubble b = mBubbleData.getBubble(key);
+ Bubble b = mBubbleData.getBubbleWithKey(key);
if (b != null) {
- b.iconView.updateDotVisibility();
+ b.updateDotVisibility();
}
}
@@ -407,16 +402,6 @@
}
/**
- * Sets the listener to notify when a bubble is blocked.
- */
- public void setOnBlockedListener(BubbleExpandedView.OnBubbleBlockedListener listener) {
- mBlockedListener = listener;
- for (Bubble b : mBubbleData.getBubbles()) {
- b.expandedView.setOnBlockedListener(mBlockedListener);
- }
- }
-
- /**
* Whether the stack of bubbles is expanded or not.
*/
public boolean isExpanded() {
@@ -445,7 +430,7 @@
*/
@Deprecated
void setExpandedBubble(String key) {
- Bubble bubbleToExpand = mBubbleData.getBubble(key);
+ Bubble bubbleToExpand = mBubbleData.getBubbleWithKey(key);
if (bubbleToExpand != null) {
setSelectedBubble(bubbleToExpand);
bubbleToExpand.entry.setShowInShadeWhenBubble(false);
@@ -466,11 +451,36 @@
}
}
+ // via BubbleData.Listener
+ void addBubble(Bubble bubble) {
+ bubble.inflate(mInflater, this);
+ mBubbleContainer.addView(bubble.iconView, 0,
+ new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
+ ViewClippingUtil.setClippingDeactivated(bubble.iconView, true, mClippingParameters);
+ requestUpdate();
+ logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
+ }
+
+ // via BubbleData.Listener
+ void removeBubble(Bubble bubble) {
+ // Remove it from the views
+ int removedIndex = mBubbleContainer.indexOfChild(bubble.iconView);
+ mBubbleContainer.removeViewAt(removedIndex);
+ logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
+ }
+
+ // via BubbleData.Listener
+ void updateBubble(Bubble bubble) {
+ requestUpdate();
+ logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__UPDATED);
+ }
+
/**
* Changes the currently selected bubble. If the stack is already expanded, the newly selected
* bubble will be shown immediately. This does not change the expanded state or change the
* position of any bubble.
*/
+ // via BubbleData.Listener
public void setSelectedBubble(Bubble bubbleToSelect) {
if (mExpandedBubble != null && mExpandedBubble.equals(bubbleToSelect)) {
return;
@@ -489,7 +499,8 @@
logBubbleEvent(previouslySelected, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
logBubbleEvent(bubbleToSelect, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED);
notifyExpansionChanged(previouslySelected.entry, false /* expanded */);
- notifyExpansionChanged(bubbleToSelect.entry, true /* expanded */);
+ notifyExpansionChanged(bubbleToSelect == null ? null : bubbleToSelect.entry,
+ true /* expanded */);
});
}
}
@@ -497,13 +508,15 @@
/**
* Changes the expanded state of the stack.
*
- * @param expanded whether the bubble stack should appear expanded
+ * @param shouldExpand whether the bubble stack should appear expanded
*/
- public void setExpanded(boolean expanded) {
- if (expanded == mIsExpanded) {
+ // via BubbleData.Listener
+ public void setExpanded(boolean shouldExpand) {
+ boolean wasExpanded = mIsExpanded;
+ if (shouldExpand == wasExpanded) {
return;
}
- if (mIsExpanded) {
+ if (wasExpanded) {
// Collapse the stack
animateExpansion(false /* expand */);
logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
@@ -518,131 +531,17 @@
}
/**
- * Adds a bubble to the top of the stack.
- *
- * @param entry the notification to add to the stack of bubbles.
- */
- void addBubble(NotificationEntry entry) {
- Bubble b = new Bubble(entry, mInflater, this /* stackView */, mBlockedListener);
- mBubbleData.addBubble(b);
-
- mBubbleContainer.addView(b.iconView, 0,
- new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
- ViewClippingUtil.setClippingDeactivated(b.iconView, true, mClippingParameters);
-
- requestUpdate();
- logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
-
- animateInFlyoutForBubble(b);
- }
-
- /**
- * Remove a bubble from the stack.
- */
- void removeBubble(String key, int reason) {
- Bubble b = mBubbleData.removeBubble(key);
- if (b == null) {
- return;
- }
- setBubbleDismissed(b, reason);
-
- // Remove it from the views
- int removedIndex = mBubbleContainer.indexOfChild(b.iconView);
- mBubbleContainer.removeViewAt(removedIndex);
-
- int bubbleCount = mBubbleContainer.getChildCount();
- if (bubbleCount == 0) {
- // If no bubbles remain, collapse the entire stack.
- collapseStack();
- return;
- } else if (b.equals(mExpandedBubble)) {
- // Was the current bubble just removed?
- // If we have other bubbles and are expanded go to the next one or previous
- // if the bubble removed was last
- int nextIndex = bubbleCount > removedIndex ? removedIndex : bubbleCount - 1;
- BubbleView expandedBubble = (BubbleView) mBubbleContainer.getChildAt(nextIndex);
- if (mIsExpanded) {
- setExpandedBubble(expandedBubble.getKey());
- } else {
- mExpandedBubble = null;
- }
- }
- // TODO: consider logging reason code
- logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
- }
-
- /**
* Dismiss the stack of bubbles.
+ * @deprecated
*/
+ @Deprecated
void stackDismissed(int reason) {
- for (Bubble bubble : mBubbleData.getBubbles()) {
- setBubbleDismissed(bubble, reason);
- }
- mBubbleData.clear();
- collapseStack();
- mBubbleContainer.removeAllViews();
- mExpandedViewContainer.removeAllViews();
- // TODO: consider logging reason code
+ mBubbleData.dismissAll(reason);
logBubbleEvent(null /* no bubble associated with bubble stack dismiss */,
StatsLog.BUBBLE_UICHANGED__ACTION__STACK_DISMISSED);
}
/**
- * Marks the notification entry as dismissed & calls any delete intents for the bubble.
- *
- * <p>Note: This does not remove the Bubble from BubbleData.
- *
- * @param bubble the Bubble being dismissed
- * @param reason code for the reason the dismiss was triggered
- * @see BubbleController.DismissReason
- */
- private void setBubbleDismissed(Bubble bubble, @DismissReason int reason) {
- if (DEBUG) {
- Log.d(TAG, "dismissBubble: " + bubble + " reason=" + reason);
- }
- bubble.entry.setBubbleDismissed(true);
- bubble.expandedView.cleanUpExpandedState();
-
- if (reason == BubbleController.DISMISS_USER_GESTURE) {
- Notification.BubbleMetadata bubbleMetadata = bubble.entry.getBubbleMetadata();
- PendingIntent deleteIntent = bubbleMetadata != null
- ? bubbleMetadata.getDeleteIntent()
- : null;
- if (deleteIntent != null) {
- try {
- deleteIntent.send();
- } catch (PendingIntent.CanceledException e) {
- Log.w(TAG, "Failed to send delete intent for bubble with key: "
- + (bubble.entry != null ? bubble.entry.key : " null entry"));
- }
- }
- }
- }
-
- /**
- * Updates a bubble in the stack.
- * @param entry the entry to update in the stack.
- */
- public void updateBubble(NotificationEntry entry) {
- Bubble b = mBubbleData.getBubble(entry.key);
- mBubbleData.updateBubble(entry.key, entry);
-
- if (!mIsExpanded) {
- // If alerting it gets promoted to top of the stack.
- if (mBubbleContainer.indexOfChild(b.iconView) != 0) {
- mBubbleContainer.moveViewTo(b.iconView, 0);
- }
- requestUpdate();
- animateInFlyoutForBubble(b /* bubble */);
- }
- if (mIsExpanded && entry.equals(mExpandedBubble.entry)) {
- entry.setShowInShadeWhenBubble(false);
- requestUpdate();
- }
- logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__UPDATED);
- }
-
- /**
* @return the view the touch event is on
*/
@Nullable
@@ -670,7 +569,7 @@
return this;
}
- public View getFlyoutView() {
+ View getFlyoutView() {
return mFlyout;
}
@@ -683,13 +582,8 @@
*/
@Deprecated
@MainThread
- public void collapseStack() {
- if (mIsExpanded) {
- // TODO: Save opened bubble & move it to top of stack
- animateExpansion(false /* shouldExpand */);
- notifyExpansionChanged(mExpandedBubble.entry, mIsExpanded);
- logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
- }
+ void collapseStack() {
+ mBubbleData.setExpanded(false);
}
/**
@@ -712,12 +606,8 @@
*/
@Deprecated
@MainThread
- public void expandStack() {
- if (!mIsExpanded) {
- String expandedBubbleKey = getBubbleAt(0).getKey();
- setExpandedBubble(expandedBubbleKey);
- logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__STACK_EXPANDED);
- }
+ void expandStack() {
+ mBubbleData.setExpanded(true);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 6f50baa..4590470 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -25,9 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.graphics.Rect;
import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.icu.text.DateFormat;
import android.icu.text.DisplayContext;
@@ -37,13 +35,8 @@
import android.os.Trace;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
import android.text.TextUtils;
-import android.text.style.DynamicDrawableSpan;
-import android.text.style.ImageSpan;
import android.text.style.StyleSpan;
-import android.util.MathUtils;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -205,9 +198,9 @@
addMediaLocked(builder);
} else {
builder.addRow(new RowBuilder(mDateUri).setTitle(mLastText));
- addNextAlarmLocked(builder);
- addZenModeLocked(builder);
}
+ addNextAlarmLocked(builder);
+ addZenModeLocked(builder);
addPrimaryActionLocked(builder);
slice = builder.build();
}
@@ -221,32 +214,25 @@
protected void addMediaLocked(ListBuilder listBuilder) {
if (mMediaMetaData != null) {
- SpannableStringBuilder builder = new SpannableStringBuilder();
-
- Icon notificationIcon = mMediaManager == null ? null : mMediaManager.getMediaIcon();
- if (notificationIcon != null) {
- Drawable drawable = notificationIcon.loadDrawable(getContext());
- Rect mediaBounds = new Rect(0 /* left */, 0 /* top */,
- drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
- int iconHeaderSize = getContext().getResources()
- .getDimensionPixelSize(R.dimen.header_icon_size);
- MathUtils.fitRect(mediaBounds, iconHeaderSize);
- drawable.setBounds(mediaBounds);
- builder.append("# ");
- builder.setSpan(new ImageSpan(drawable, DynamicDrawableSpan.ALIGN_CENTER),
- 0 /* start */, 1 /* end */, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- }
-
CharSequence title = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_TITLE);
if (TextUtils.isEmpty(title)) {
title = getContext().getResources().getString(R.string.music_controls_no_title);
}
- builder.append(title);
- listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(builder));
+ listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(title));
CharSequence album = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_ARTIST);
if (!TextUtils.isEmpty(album)) {
- listBuilder.addRow(new RowBuilder(mMediaUri).setTitle(album));
+ RowBuilder albumBuilder = new RowBuilder(mMediaUri);
+ albumBuilder.setTitle(album);
+
+ Icon mediaIcon = mMediaManager == null ? null : mMediaManager.getMediaIcon();
+ IconCompat mediaIconCompat = mediaIcon == null ? null
+ : IconCompat.createFromIcon(getContext(), mediaIcon);
+ if (mediaIconCompat != null) {
+ albumBuilder.addEndItem(mediaIconCompat, ListBuilder.ICON_IMAGE);
+ }
+
+ listBuilder.addRow(albumBuilder);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
index 0eeaa9b..7de8b74 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
@@ -139,43 +139,49 @@
@Override
public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
- if (info.anySimReady) {
- boolean[] slotSeen = new boolean[SIM_SLOTS];
- if (info.listOfCarriers.length == info.subscriptionIds.length) {
- for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) {
- int slot = getSlotIndex(info.subscriptionIds[i]);
- if (slot >= SIM_SLOTS) {
- Log.w(TAG, "updateInfoCarrier - slot: " + slot);
- continue;
+ if (info.airplaneMode) {
+ setVisibility(View.GONE);
+ } else {
+ setVisibility(View.VISIBLE);
+ if (info.anySimReady) {
+ boolean[] slotSeen = new boolean[SIM_SLOTS];
+ if (info.listOfCarriers.length == info.subscriptionIds.length) {
+ for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) {
+ int slot = getSlotIndex(info.subscriptionIds[i]);
+ if (slot >= SIM_SLOTS) {
+ Log.w(TAG, "updateInfoCarrier - slot: " + slot);
+ continue;
+ }
+ if (slot == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ Log.e(TAG,
+ "Invalid SIM slot index for subscription: "
+ + info.subscriptionIds[i]);
+ continue;
+ }
+ mInfos[slot].visible = true;
+ slotSeen[slot] = true;
+ mCarrierGroups[slot].setCarrierText(
+ info.listOfCarriers[i].toString().trim());
+ mCarrierGroups[slot].setVisibility(View.VISIBLE);
}
- if (slot == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- Log.e(TAG,
- "Invalid SIM slot index for subscription: "
- + info.subscriptionIds[i]);
- continue;
+ for (int i = 0; i < SIM_SLOTS; i++) {
+ if (!slotSeen[i]) {
+ mInfos[i].visible = false;
+ mCarrierGroups[i].setVisibility(View.GONE);
+ }
}
- mInfos[slot].visible = true;
- slotSeen[slot] = true;
- mCarrierGroups[slot].setCarrierText(info.listOfCarriers[i].toString().trim());
- mCarrierGroups[slot].setVisibility(View.VISIBLE);
- }
- for (int i = 0; i < SIM_SLOTS; i++) {
- if (!slotSeen[i]) {
- mInfos[i].visible = false;
- mCarrierGroups[i].setVisibility(View.GONE);
- }
+ } else {
+ Log.e(TAG, "Carrier information arrays not of same length");
}
} else {
- Log.e(TAG, "Carrier information arrays not of same length");
- }
- } else {
- mInfos[0].visible = false;
- mCarrierGroups[0].setCarrierText(info.carrierText);
- mCarrierGroups[0].setVisibility(View.VISIBLE);
- for (int i = 1; i < SIM_SLOTS; i++) {
- mInfos[i].visible = false;
- mCarrierGroups[i].setCarrierText("");
- mCarrierGroups[i].setVisibility(View.GONE);
+ mInfos[0].visible = false;
+ mCarrierGroups[0].setCarrierText(info.carrierText);
+ mCarrierGroups[0].setVisibility(View.VISIBLE);
+ for (int i = 1; i < SIM_SLOTS; i++) {
+ mInfos[i].visible = false;
+ mCarrierGroups[i].setCarrierText("");
+ mCarrierGroups[i].setVisibility(View.GONE);
+ }
}
}
handleUpdateState();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index 91cd652..8a360ee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -15,11 +15,10 @@
package com.android.systemui.qs.tileimpl;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.service.quicksettings.Tile;
-import android.text.SpannableStringBuilder;
import android.text.TextUtils;
-import android.text.style.ForegroundColorSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -27,6 +26,7 @@
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.settingslib.Utils;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSIconView;
@@ -46,6 +46,8 @@
private ViewGroup mLabelContainer;
private View mExpandIndicator;
private View mExpandSpace;
+ private ColorStateList mColorLabelDefault;
+ private ColorStateList mColorLabelUnavailable;
public QSTileView(Context context, QSIconView icon) {
this(context, icon, false);
@@ -62,6 +64,11 @@
createLabel();
setOrientation(VERTICAL);
setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
+ mColorLabelDefault = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary);
+ // The text color for unavailable tiles is textColorSecondary, same as secondaryLabel for
+ // contrast purposes
+ mColorLabelUnavailable = Utils.getColorAttr(getContext(),
+ android.R.attr.textColorSecondary);
}
TextView getLabel() {
@@ -111,12 +118,8 @@
protected void handleStateChanged(QSTile.State state) {
super.handleStateChanged(state);
if (!Objects.equals(mLabel.getText(), state.label) || mState != state.state) {
- if (state.state == Tile.STATE_UNAVAILABLE) {
- int color = QSTileImpl.getColorForState(getContext(), state.state);
- state.label = new SpannableStringBuilder().append(state.label,
- new ForegroundColorSpan(color),
- SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
- }
+ mLabel.setTextColor(state.state == Tile.STATE_UNAVAILABLE ? mColorLabelUnavailable
+ : mColorLabelDefault);
mState = state.state;
mLabel.setText(state.label);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 72559f5..56dbe2b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -608,6 +608,7 @@
mConnectionCallbacks.add(listener);
listener.onConnectionChanged(mOverviewProxy != null);
listener.onInteractionFlagsChanged(mInteractionFlags);
+ listener.onBackButtonAlphaChanged(mBackButtonAlpha, false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 907b3ad..85848ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -151,7 +151,7 @@
? Dependency.get(AutoHideController.class)
: new AutoHideController(context, mHandler);
navBar.setAutoHideController(autoHideController);
- navBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+ navBar.restoreSystemUiVisibilityState();
mNavigationBars.append(displayId, navBar);
if (result != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 2e35f06..97f2dd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -22,7 +22,6 @@
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewParent;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleData;
@@ -120,7 +119,7 @@
for (int i = 0; i < N; i++) {
NotificationEntry ent = activeNotifications.get(i);
if (ent.isRowDismissed() || ent.isRowRemoved()
- || (mBubbleData.getBubble(ent.key) != null && !ent.showInShadeWhenBubble())) {
+ || (mBubbleData.hasBubbleWithKey(ent.key) && !ent.showInShadeWhenBubble())) {
// we don't want to update removed notifications because they could
// temporarily become children if they were isolated before.
continue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 9eecdb9..4d2b56c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -123,6 +123,7 @@
private static final boolean DEBUG = false;
private static final String EXTRA_DISABLE_STATE = "disabled_state";
private static final String EXTRA_DISABLE2_STATE = "disabled2_state";
+ private static final String EXTRA_SYSTEM_UI_VISIBILITY = "system_ui_visibility";
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -156,7 +157,7 @@
private Locale mLocale;
private int mLayoutDirection;
- private int mSystemUiVisibility;
+ private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
private LightBarController mLightBarController;
private AutoHideController mAutoHideController;
@@ -277,6 +278,7 @@
if (savedInstanceState != null) {
mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
+ mSystemUiVisibility = savedInstanceState.getInt(EXTRA_SYSTEM_UI_VISIBILITY, 0);
}
mAccessibilityManagerWrapper.addCallback(mAccessibilityListener);
@@ -363,6 +365,7 @@
super.onSaveInstanceState(outState);
outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
outState.putInt(EXTRA_DISABLE2_STATE, mDisabledFlags2);
+ outState.putInt(EXTRA_SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
if (mNavigationBarView != null) {
mNavigationBarView.getLightTransitionsController().saveState(outState);
}
@@ -492,13 +495,8 @@
}
}
- /**
- * Sets System UI flags to {@link NavigationBarFragment}.
- *
- * @see View#setSystemUiVisibility(int)
- */
- public void setSystemUiVisibility(int systemUiVisibility) {
- mSystemUiVisibility = systemUiVisibility;
+ /** Restores the System UI flags saved state to {@link NavigationBarFragment}. */
+ public void restoreSystemUiVisibilityState() {
final int barMode = computeBarMode(0, mSystemUiVisibility);
if (barMode != -1) {
mNavigationBarMode = barMode;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java b/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java
index 45fc756..1862ed3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java
@@ -22,6 +22,9 @@
import android.view.GestureDetector;
import android.view.MotionEvent;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
+
import com.android.keyguard.AlphaOptimizedImageButton;
import com.android.systemui.R;
@@ -31,7 +34,7 @@
private static final int[] OPTED_OUT_STATE = new int[] { R.attr.optedOut };
private ConfirmedTapListener mConfirmedTapListener;
- private boolean mComponentEnabled = false;
+ private boolean mCaptionsEnabled = false;
private boolean mOptedOut = false;
private GestureDetector mGestureDetector;
@@ -39,16 +42,14 @@
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
- if (mConfirmedTapListener != null) {
- mConfirmedTapListener.onConfirmedTap();
- return true;
- }
- return false;
+ return tryToSendTapConfirmedEvent();
}
};
public CaptionsToggleImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
+ this.setContentDescription(
+ getContext().getString(R.string.volume_odi_captions_content_description));
}
@Override
@@ -66,16 +67,32 @@
return state;
}
- Runnable setComponentEnabled(boolean isComponentEnabled) {
- this.mComponentEnabled = isComponentEnabled;
+ Runnable setCaptionsEnabled(boolean areCaptionsEnabled) {
+ this.mCaptionsEnabled = areCaptionsEnabled;
- return this.setImageResourceAsync(this.mComponentEnabled
+ ViewCompat.replaceAccessibilityAction(
+ this,
+ AccessibilityActionCompat.ACTION_CLICK,
+ mCaptionsEnabled
+ ? getContext().getString(R.string.volume_odi_captions_hint_disable)
+ : getContext().getString(R.string.volume_odi_captions_hint_enable),
+ (view, commandArguments) -> tryToSendTapConfirmedEvent());
+
+ return this.setImageResourceAsync(mCaptionsEnabled
? R.drawable.ic_volume_odi_captions
: R.drawable.ic_volume_odi_captions_disabled);
}
- boolean getComponentEnabled() {
- return this.mComponentEnabled;
+ private boolean tryToSendTapConfirmedEvent() {
+ if (mConfirmedTapListener != null) {
+ mConfirmedTapListener.onConfirmedTap();
+ return true;
+ }
+ return false;
+ }
+
+ boolean getCaptionsEnabled() {
+ return this.mCaptionsEnabled;
}
/** Sets whether or not the current stream has opted out of captions */
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 5095370..8d9c5a3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -596,9 +596,9 @@
}
private void updateCaptionsIcon() {
- boolean componentEnabled = mController.areCaptionsEnabled();
- if (mODICaptionsIcon.getComponentEnabled() != componentEnabled) {
- mHandler.post(mODICaptionsIcon.setComponentEnabled(componentEnabled));
+ boolean captionsEnabled = mController.areCaptionsEnabled();
+ if (mODICaptionsIcon.getCaptionsEnabled() != captionsEnabled) {
+ mHandler.post(mODICaptionsIcon.setCaptionsEnabled(captionsEnabled));
}
boolean isOptedOut = mController.isCaptionStreamOptedOut();
@@ -878,7 +878,6 @@
}
view.setContentDescription(mContext.getString(currStateResId));
-
view.setAccessibilityDelegate(new AccessibilityDelegate() {
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 8e061cc..df534d7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -37,6 +37,7 @@
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -81,6 +82,8 @@
private ConnectivityManager mConnectivityManager;
@Mock
private TelephonyManager mTelephonyManager;
+ @Mock
+ private SubscriptionManager mSubscriptionManager;
private CarrierTextController.CarrierTextCallbackInfo mCarrierTextCallbackInfo;
private CarrierTextController mCarrierTextController;
@@ -94,6 +97,7 @@
mContext.addMockSystemService(WifiManager.class, mWifiManager);
mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
+ mContext.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
mDependency.injectMockDependency(WakefulnessLifecycle.class);
mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
new Handler(mTestableLooper.getLooper()));
@@ -169,6 +173,7 @@
list.add(TEST_SUBSCRIPTION);
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -192,6 +197,7 @@
list.add(TEST_SUBSCRIPTION_ROAMING);
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/AnalogClockControllerTest.java
similarity index 91%
rename from packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java
rename to packages/SystemUI/tests/src/com/android/keyguard/clock/AnalogClockControllerTest.java
index 26fa62b..4bb2395 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/AnalogClockControllerTest.java
@@ -38,9 +38,9 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
-public final class StretchAnalogClockControllerTest extends SysuiTestCase {
+public final class AnalogClockControllerTest extends SysuiTestCase {
- private StretchAnalogClockController mClockController;
+ private AnalogClockController mClockController;
@Mock SysuiColorExtractor mMockColorExtractor;
@Before
@@ -49,7 +49,7 @@
Resources res = getContext().getResources();
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
- mClockController = new StretchAnalogClockController(res, layoutInflater,
+ mClockController = new AnalogClockController(res, layoutInflater,
mMockColorExtractor);
}
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 20f539b..40a5357 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -146,7 +146,7 @@
when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel);
- mBubbleData = new BubbleData();
+ mBubbleData = new BubbleData(mContext);
mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController,
mBubbleData, mConfigurationController);
mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
@@ -177,25 +177,27 @@
public void testRemoveBubble() {
mBubbleController.updateBubble(mRow.getEntry());
assertTrue(mBubbleController.hasBubbles());
-
+ verify(mNotificationEntryManager).updateNotifications();
verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
assertFalse(mStatusBarWindowController.getBubblesShowing());
assertTrue(mRow.getEntry().isBubbleDismissed());
- verify(mNotificationEntryManager).updateNotifications();
+ verify(mNotificationEntryManager, times(2)).updateNotifications();
verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
}
@Test
public void testDismissStack() {
mBubbleController.updateBubble(mRow.getEntry());
+ verify(mNotificationEntryManager, times(1)).updateNotifications();
mBubbleController.updateBubble(mRow2.getEntry());
+ verify(mNotificationEntryManager, times(2)).updateNotifications();
assertTrue(mBubbleController.hasBubbles());
mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
assertFalse(mStatusBarWindowController.getBubblesShowing());
- verify(mNotificationEntryManager).updateNotifications();
+ verify(mNotificationEntryManager, times(3)).updateNotifications();
assertTrue(mRow.getEntry().isBubbleDismissed());
assertTrue(mRow2.getEntry().isBubbleDismissed());
}
@@ -215,7 +217,7 @@
// Expand the stack
BubbleStackView stackView = mBubbleController.getStackView();
- stackView.expandStack();
+ mBubbleController.expandStack();
assertTrue(mBubbleController.isStackExpanded());
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
assertTrue(mStatusBarWindowController.getBubbleExpanded());
@@ -224,7 +226,7 @@
assertFalse(mRow.getEntry().showInShadeWhenBubble());
// Collapse
- stackView.collapseStack();
+ mBubbleController.collapseStack();
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
assertFalse(mBubbleController.isStackExpanded());
assertFalse(mStatusBarWindowController.getBubbleExpanded());
@@ -245,23 +247,24 @@
// Expand
BubbleStackView stackView = mBubbleController.getStackView();
- stackView.expandStack();
+ mBubbleController.expandStack();
assertTrue(mBubbleController.isStackExpanded());
- verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
- // Last added is the one that is expanded
- assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
- assertFalse(mRow2.getEntry().showInShadeWhenBubble());
-
- // Switch which bubble is expanded
- stackView.setExpandedBubble(mRow.getEntry());
+ // First added is the one that is expanded
assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
assertFalse(mRow.getEntry().showInShadeWhenBubble());
+ // Switch which bubble is expanded
+ mBubbleController.selectBubble(mRow2.getEntry().key);
+ stackView.setExpandedBubble(mRow2.getEntry());
+ assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
+ assertFalse(mRow2.getEntry().showInShadeWhenBubble());
+
// collapse for previous bubble
- verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
// expand for selected bubble
- verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
// Collapse
mBubbleController.collapseStack();
@@ -280,7 +283,7 @@
// Expand
BubbleStackView stackView = mBubbleController.getStackView();
- stackView.expandStack();
+ mBubbleController.expandStack();
assertTrue(mBubbleController.isStackExpanded());
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
@@ -299,30 +302,30 @@
// Expand
BubbleStackView stackView = mBubbleController.getStackView();
- stackView.expandStack();
+ mBubbleController.expandStack();
assertTrue(mBubbleController.isStackExpanded());
- verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
- // Last added is the one that is expanded
- assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
- assertFalse(mRow2.getEntry().showInShadeWhenBubble());
+ // First added is the one that is expanded
+ assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
+ assertFalse(mRow.getEntry().showInShadeWhenBubble());
// Dismiss currently expanded
mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
BubbleController.DISMISS_USER_GESTURE);
- verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
// Make sure next bubble is selected
- assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
- verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+ assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
+ verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
// Dismiss that one
mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
BubbleController.DISMISS_USER_GESTURE);
// Make sure state changes and collapse happens
- verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+ verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
assertFalse(mBubbleController.hasBubbles());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java
index 801308f..da31134 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java
@@ -48,7 +48,7 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mStackView = new BubbleStackView(mContext, new BubbleData(), null);
+ mStackView = new BubbleStackView(mContext, new BubbleData(getContext()), null);
mBubble.entry = mNotifEntry;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 63d42a7..c534de7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.content.ContentResolver;
@@ -102,6 +103,7 @@
@Test
public void onBindSlice_readsMedia() {
MediaMetadata metadata = mock(MediaMetadata.class);
+ when(metadata.getText(any())).thenReturn("metadata");
mProvider.onDozingChanged(true);
mProvider.onMetadataChanged(metadata);
mProvider.onBindSlice(mProvider.getUri());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 2172a12..3662c38 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -98,7 +98,7 @@
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
mock(StatusBarStateControllerImpl.class), mEntryManager,
- () -> mShadeController, new BubbleData());
+ () -> mShadeController, new BubbleData(mContext));
Dependency.get(InitController.class).executePostInitTasks();
mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
index 46e3226..7b6a128 100644
--- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
+++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
@@ -111,6 +111,15 @@
@Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ // MotionEventInjector would cancel any injected gesture when any MotionEvent arrives.
+ // For user using an external device to control the pointer movement, it's almost
+ // impossible to perform the gestures. Any slightly unintended movement results in the
+ // cancellation of the gesture.
+ if ((event.isFromSource(InputDevice.SOURCE_MOUSE)
+ && event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE)
+ && mOpenGesturesInProgress.get(EVENT_SOURCE, false)) {
+ return;
+ }
cancelAnyPendingInjectedEvents();
sendMotionEventToNext(event, rawEvent, policyFlags);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index fdc3567..a94d1dc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -806,6 +806,17 @@
mAugmentedAutofillState.injectAugmentedAutofillInfo(options, userId, packageName);
return options;
}
+
+ @Override
+ public boolean isAugmentedAutofillServiceForUser(int callingUid, int userId) {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ return service.isAugmentedAutofillServiceForUserLocked(callingUid);
+ }
+ }
+ return false;
+ }
}
/**
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 4bd6fbd3..f1963b3 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -1165,6 +1165,11 @@
return true;
}
+ boolean isAugmentedAutofillServiceForUserLocked(int callingUid) {
+ return mRemoteAugmentedAutofillServiceInfo != null
+ && mRemoteAugmentedAutofillServiceInfo.applicationInfo.uid == callingUid;
+ }
+
/**
* Sets which packages and activities can trigger augmented autofill.
*
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 593bb2c4..35dfccf 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -23,22 +23,20 @@
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import android.annotation.Nullable;
-import android.app.AppGlobals;
import android.app.backup.BackupTransport;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.util.ArrayUtils;
+import com.android.server.LocalServices;
import com.android.server.backup.transport.TransportClient;
import com.google.android.collect.Sets;
@@ -67,12 +65,13 @@
* </ol>
*/
public static boolean appIsEligibleForBackup(ApplicationInfo app, int userId) {
- return appIsEligibleForBackup(app, AppGlobals.getPackageManager(), userId);
+ return appIsEligibleForBackup(
+ app, LocalServices.getService(PackageManagerInternal.class), userId);
}
@VisibleForTesting
- static boolean appIsEligibleForBackup(ApplicationInfo app,
- IPackageManager packageManager, int userId) {
+ static boolean appIsEligibleForBackup(
+ ApplicationInfo app, PackageManagerInternal packageManager, int userId) {
// 1. their manifest states android:allowBackup="false"
if ((app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) {
return false;
@@ -108,9 +107,9 @@
/**
* Returns whether an app is eligible for backup at runtime. That is, the app has to:
* <ol>
- * <li>Return true for {@link #appIsEligibleForBackup(ApplicationInfo, PackageManager)}
+ * <li>Return true for {@link #appIsEligibleForBackup(ApplicationInfo, int)}
* <li>Return false for {@link #appIsStopped(ApplicationInfo)}
- * <li>Return false for {@link #appIsDisabled(ApplicationInfo, PackageManager)}
+ * <li>Return false for {@link #appIsDisabled(ApplicationInfo, int)}
* <li>Be eligible for the transport via
* {@link BackupTransport#isAppEligibleForBackup(PackageInfo, boolean)}
* </ol>
@@ -149,19 +148,13 @@
/** Avoid backups of 'disabled' apps. */
static boolean appIsDisabled(ApplicationInfo app, int userId) {
- return appIsDisabled(app, AppGlobals.getPackageManager(), userId);
+ return appIsDisabled(app, LocalServices.getService(PackageManagerInternal.class), userId);
}
@VisibleForTesting
- static boolean appIsDisabled(ApplicationInfo app,
- IPackageManager packageManager, int userId) {
- int enabledSetting;
- try {
- enabledSetting = packageManager.getApplicationEnabledSetting(app.packageName, userId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to get application enabled setting: " + e);
- return false;
- }
+ static boolean appIsDisabled(
+ ApplicationInfo app, PackageManagerInternal packageManager, int userId) {
+ int enabledSetting = packageManager.getApplicationEnabledState(app.packageName, userId);
switch (enabledSetting) {
case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 757c2dc..7f411d8 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -60,8 +60,8 @@
import android.view.contentcapture.ContentCaptureCondition;
import android.view.contentcapture.ContentCaptureHelper;
import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.DataRemovalRequest;
import android.view.contentcapture.IContentCaptureManager;
-import android.view.contentcapture.UserDataRemovalRequest;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AbstractRemoteService;
@@ -583,14 +583,14 @@
}
@Override
- public void removeUserData(@NonNull UserDataRemovalRequest request) {
+ public void removeData(@NonNull DataRemovalRequest request) {
Preconditions.checkNotNull(request);
assertCalledByPackageOwner(request.getPackageName());
final int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
final ContentCapturePerUserService service = getServiceForUserLocked(userId);
- service.removeUserDataLocked(request);
+ service.removeDataLocked(request);
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 5649526..b4a1f38 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -57,7 +57,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.view.contentcapture.ContentCaptureCondition;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.WhitelistHelper;
@@ -343,12 +343,12 @@
}
@GuardedBy("mLock")
- public void removeUserDataLocked(@NonNull UserDataRemovalRequest request) {
+ public void removeDataLocked(@NonNull DataRemovalRequest request) {
if (!isEnabledLocked()) {
return;
}
assertCallerLocked(request.getPackageName());
- mRemoteService.onUserDataRemovalRequest(request);
+ mRemoteService.onDataRemovalRequest(request);
}
@GuardedBy("mLock")
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 3fa3fdf..2171033 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -29,7 +29,7 @@
import android.service.contentcapture.SnapshotData;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureContext;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
import com.android.internal.os.IResultReceiver;
@@ -120,10 +120,10 @@
}
/**
- * Called by {@link ContentCaptureServerSession} to request removal of user data.
+ * Called by {@link ContentCaptureServerSession} to request removal of content capture data.
*/
- public void onUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
- scheduleAsyncRequest((s) -> s.onUserDataRemovalRequest(request));
+ public void onDataRemovalRequest(@NonNull DataRemovalRequest request) {
+ scheduleAsyncRequest((s) -> s.onDataRemovalRequest(request));
}
/**
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 6018f00..5c5b477 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -18,11 +18,10 @@
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
-import android.os.SystemProperties;
+
+import com.android.internal.os.RoSystemProperties;
class BluetoothService extends SystemService {
- private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless";
-
private BluetoothManagerService mBluetoothManagerService;
private boolean mInitialized = false;
@@ -48,7 +47,7 @@
publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
mBluetoothManagerService);
} else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY &&
- !SystemProperties.getBoolean(HEADLESS_SYSTEM_USER, false)) {
+ !RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER) {
initialize();
}
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 382fdec..82bba77 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3766,7 +3766,7 @@
return Zygote.MOUNT_EXTERNAL_NONE;
}
if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
- return Zygote.MOUNT_EXTERNAL_NONE;
+ return Zygote.MOUNT_EXTERNAL_DEFAULT;
}
// Determine if caller is holding runtime permission
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index a08c829..588e05d 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -29,6 +29,7 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
@@ -380,8 +381,9 @@
userId = controller.mUserController.getCurrentOrTargetUserId();
}
// temporarily allow receivers and services to open activities from background if the
- // PendingIntent.send() caller was foreground at the time of sendInner() call
- final boolean allowTrampoline = uid != callingUid
+ // PendingIntent.send() caller was foreground at the time of sendInner() call, unless
+ // caller is SYSTEM_UID
+ final boolean allowTrampoline = uid != callingUid && callingUid != Process.SYSTEM_UID
&& controller.mAtmInternal.isUidForeground(callingUid);
// note: we on purpose don't pass in the information about the PendingIntent's creator,
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 3dbea0d..d7d4851 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -17,7 +17,6 @@
package com.android.server.attention;
import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
-import static android.provider.Settings.System.ADAPTIVE_SLEEP;
import static android.service.attention.AttentionService.ATTENTION_FAILURE_CANCELLED;
import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
@@ -47,7 +46,6 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.DeviceConfig;
-import android.provider.Settings;
import android.service.attention.AttentionService;
import android.service.attention.AttentionService.AttentionFailureCodes;
import android.service.attention.AttentionService.AttentionSuccessCodes;
@@ -60,6 +58,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -102,16 +101,25 @@
private final Object mLock;
@GuardedBy("mLock")
private final SparseArray<UserState> mUserStates = new SparseArray<>();
- private final AttentionHandler mAttentionHandler;
+ private AttentionHandler mAttentionHandler;
- private ComponentName mComponentName;
+ @VisibleForTesting
+ ComponentName mComponentName;
public AttentionManagerService(Context context) {
+ this(context, (PowerManager) context.getSystemService(Context.POWER_SERVICE),
+ new Object(), null);
+ mAttentionHandler = new AttentionHandler();
+ }
+
+ @VisibleForTesting
+ AttentionManagerService(Context context, PowerManager powerManager, Object lock,
+ AttentionHandler handler) {
super(context);
mContext = Preconditions.checkNotNull(context);
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mLock = new Object();
- mAttentionHandler = new AttentionHandler();
+ mPowerManager = powerManager;
+ mLock = lock;
+ mAttentionHandler = handler;
}
@Override
@@ -149,7 +157,8 @@
return isServiceEnabled() && isServiceAvailable();
}
- private boolean isServiceEnabled() {
+ @VisibleForTesting
+ protected boolean isServiceEnabled() {
return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE, SERVICE_ENABLED,
DEFAULT_SERVICE_ENABLED);
}
@@ -163,7 +172,8 @@
*
* @return {@code true} if the framework was able to dispatch the request
*/
- private boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
+ @VisibleForTesting
+ boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
Preconditions.checkNotNull(callbackInternal);
if (!isAttentionServiceSupported()) {
@@ -259,37 +269,24 @@
}
/** Cancels the specified attention check. */
- private void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
+ @VisibleForTesting
+ void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
synchronized (mLock) {
final UserState userState = peekCurrentUserStateLocked();
if (userState == null) {
return;
}
-
if (!userState.mCurrentAttentionCheck.mCallbackInternal.equals(callbackInternal)) {
Slog.e(LOG_TAG, "Cannot cancel a non-current request");
return;
}
-
cancel(userState);
}
}
- /** Disables service dependants. */
- private void disableSelf() {
- final long identity = Binder.clearCallingIdentity();
- try {
- if (DEBUG) {
- Slog.d(LOG_TAG, "Disabling self.");
- }
- Settings.System.putInt(mContext.getContentResolver(), ADAPTIVE_SLEEP, 0);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
@GuardedBy("mLock")
- private void freeIfInactiveLocked() {
+ @VisibleForTesting
+ protected void freeIfInactiveLocked() {
// If we are called here, it means someone used the API again - reset the timer then.
mAttentionHandler.removeMessages(AttentionHandler.CHECK_CONNECTION_EXPIRATION);
@@ -306,7 +303,8 @@
@GuardedBy("mLock")
- private UserState getOrCreateCurrentUserStateLocked() {
+ @VisibleForTesting
+ protected UserState getOrCreateCurrentUserStateLocked() {
return getOrCreateUserStateLocked(ActivityManager.getCurrentUser());
}
@@ -322,7 +320,8 @@
@GuardedBy("mLock")
@Nullable
- private UserState peekCurrentUserStateLocked() {
+ @VisibleForTesting
+ protected UserState peekCurrentUserStateLocked() {
return peekUserStateLocked(ActivityManager.getCurrentUser());
}
@@ -418,11 +417,6 @@
public void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
AttentionManagerService.this.cancelAttentionCheck(callbackInternal);
}
-
- @Override
- public void disableSelf() {
- AttentionManagerService.this.disableSelf();
- }
}
private static final class AttentionCheckCache {
@@ -438,7 +432,8 @@
}
}
- private static final class AttentionCheck {
+ @VisibleForTesting
+ static final class AttentionCheck {
private final AttentionCallbackInternal mCallbackInternal;
private final IAttentionCallback mIAttentionCallback;
private boolean mIsDispatched;
@@ -455,7 +450,8 @@
}
}
- private static final class UserState {
+ @VisibleForTesting
+ protected static class UserState {
final ComponentName mComponentName;
final AttentionServiceConnection mConnection = new AttentionServiceConnection();
@@ -473,7 +469,7 @@
final Context mContext;
final Object mLock;
- private UserState(int userId, Context context, Object lock, ComponentName componentName) {
+ UserState(int userId, Context context, Object lock, ComponentName componentName) {
mUserId = userId;
mContext = Preconditions.checkNotNull(context);
mLock = Preconditions.checkNotNull(lock);
@@ -529,7 +525,7 @@
}
}
- private final class AttentionServiceConnection implements ServiceConnection {
+ private class AttentionServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
init(IAttentionService.Stub.asInterface(service));
@@ -564,7 +560,8 @@
}
}
- private class AttentionHandler extends Handler {
+ @VisibleForTesting
+ protected class AttentionHandler extends Handler {
private static final int CHECK_CONNECTION_EXPIRATION = 1;
private static final int ATTENTION_CHECK_TIMEOUT = 2;
@@ -596,7 +593,8 @@
}
}
- private void cancel(UserState userState) {
+ @VisibleForTesting
+ void cancel(UserState userState) {
if (userState == null || userState.mCurrentAttentionCheck == null) {
return;
}
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 258c325..d28482e 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -52,6 +52,7 @@
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.autofill.AutofillManagerInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -159,6 +160,7 @@
private final PackageManager mPm;
private final AppOpsManager mAppOps;
private final ContentCaptureManagerInternal mContentCaptureInternal;
+ private final AutofillManagerInternal mAutofillInternal;
private final IBinder mPermissionOwner;
private HostClipboardMonitor mHostClipboardMonitor = null;
private Thread mHostMonitorThread = null;
@@ -179,6 +181,7 @@
mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mContentCaptureInternal = LocalServices.getService(ContentCaptureManagerInternal.class);
+ mAutofillInternal = LocalServices.getService(AutofillManagerInternal.class);
final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
mPermissionOwner = permOwner;
if (IS_EMULATOR) {
@@ -653,13 +656,18 @@
// Clipboard can only be read by applications with focus..
boolean allowed = mWm.isUidFocused(callingUid);
if (!allowed && mContentCaptureInternal != null) {
- // ...or the Intelligence Service
+ // ...or the Content Capture Service
allowed = mContentCaptureInternal.isContentCaptureServiceForUser(callingUid,
userId);
}
+ if (!allowed && mAutofillInternal != null) {
+ // ...or the Augmented Autofill Service
+ allowed = mAutofillInternal.isAugmentedAutofillServiceForUser(callingUid,
+ userId);
+ }
if (!allowed) {
Slog.e(TAG, "Denying clipboard access to " + callingPackage
- + ", application is not in focus neither is the IntelligeService for "
+ + ", application is not in focus neither is a system service for "
+ "user " + userId);
}
return allowed;
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 948c690..a1a8e35 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -33,6 +33,7 @@
import android.util.Pair;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.TrafficStatsConstants;
import libcore.io.IoUtils;
@@ -381,7 +382,8 @@
protected void setupSocket(
int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort)
throws ErrnoException, IOException {
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+ final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_PROBE);
try {
mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
} finally {
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 1ac09ad..f6ce2dc 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -39,6 +39,7 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.TrafficStatsConstants;
import com.android.net.IProxyCallback;
import com.android.net.IProxyPortListener;
import com.android.net.IProxyService;
@@ -111,7 +112,8 @@
String file;
final Uri pacUrl = mPacUrl;
if (Uri.EMPTY.equals(pacUrl)) return;
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PAC);
+ final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_PAC);
try {
file = get(pacUrl);
} catch (IOException ioe) {
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index a2515c8..580150e 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1228,6 +1228,24 @@
public boolean isUidAllowedOnDisplay(int displayId, int uid) {
return mIWindowManagerInternal.isUidAllowedOnDisplay(displayId, uid);
}
+
+ @BinderThread
+ @Override
+ public void setActive(int clientId, boolean active) {
+ synchronized (mPerUserData.mLock) {
+ final InputMethodClientInfo clientInfo =
+ mPerUserData.getClientFromIdLocked(clientId);
+ if (clientInfo == null) {
+ Slog.e(TAG, "Unknown clientId=" + clientId);
+ return;
+ }
+ try {
+ clientInfo.mClient.setActive(active, false /* fullscreen */);
+ } catch (RemoteException e) {
+ return;
+ }
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsXtraDownloader.java
index c012ee4..7dffcb4 100644
--- a/services/core/java/com/android/server/location/GpsXtraDownloader.java
+++ b/services/core/java/com/android/server/location/GpsXtraDownloader.java
@@ -20,6 +20,8 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.util.TrafficStatsConstants;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -92,7 +94,8 @@
// load balance our requests among the available servers
while (result == null) {
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_GPS);
+ final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_GPS);
try {
result = doDownload(mXtraServers[mNextServerIndex]);
} finally {
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
index a5f2217..fdb499b 100644
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -140,6 +140,7 @@
private AudioPlayerStateMonitor mAudioPlayerStateMonitor;
// Used to notify System UI and Settings when remote volume was changed.
+ @GuardedBy("mLock")
final RemoteCallbackList<IRemoteVolumeController> mRemoteVolumeControllers =
new RemoteCallbackList<>();
@@ -287,17 +288,19 @@
if (!session.isActive()) {
return;
}
- int size = mRemoteVolumeControllers.beginBroadcast();
- MediaSession.Token token = session.getSessionToken();
- for (int i = size - 1; i >= 0; i--) {
- try {
- IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
- cb.remoteVolumeChanged(token, flags);
- } catch (Exception e) {
- Log.w(TAG, "Error sending volume change.", e);
+ synchronized (mLock) {
+ int size = mRemoteVolumeControllers.beginBroadcast();
+ MediaSession.Token token = session.getSessionToken();
+ for (int i = size - 1; i >= 0; i--) {
+ try {
+ IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
+ cb.remoteVolumeChanged(token, flags);
+ } catch (Exception e) {
+ Log.w(TAG, "Error sending volume change.", e);
+ }
}
+ mRemoteVolumeControllers.finishBroadcast();
}
- mRemoteVolumeControllers.finishBroadcast();
}
@Override
@@ -647,19 +650,21 @@
return;
}
- int size = mRemoteVolumeControllers.beginBroadcast();
- MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
- MediaSession.Token token = record == null ? null : record.getSessionToken();
+ synchronized (mLock) {
+ int size = mRemoteVolumeControllers.beginBroadcast();
+ MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
+ MediaSession.Token token = record == null ? null : record.getSessionToken();
- for (int i = size - 1; i >= 0; i--) {
- try {
- IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
- cb.updateRemoteController(token);
- } catch (Exception e) {
- Log.w(TAG, "Error sending default remote volume.", e);
+ for (int i = size - 1; i >= 0; i--) {
+ try {
+ IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
+ cb.updateRemoteController(token);
+ } catch (Exception e) {
+ Log.w(TAG, "Error sending default remote volume.", e);
+ }
}
+ mRemoteVolumeControllers.finishBroadcast();
}
- mRemoteVolumeControllers.finishBroadcast();
}
void pushSession2TokensChangedLocked(int userId) {
@@ -1676,11 +1681,13 @@
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
- try {
- enforceStatusBarServicePermission("listen for volume changes", pid, uid);
- mRemoteVolumeControllers.register(rvc);
- } finally {
- Binder.restoreCallingIdentity(token);
+ synchronized (mLock) {
+ try {
+ enforceStatusBarServicePermission("listen for volume changes", pid, uid);
+ mRemoteVolumeControllers.register(rvc);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
}
@@ -1689,11 +1696,13 @@
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
- try {
- enforceStatusBarServicePermission("listen for volume changes", pid, uid);
- mRemoteVolumeControllers.unregister(rvc);
- } finally {
- Binder.restoreCallingIdentity(token);
+ synchronized (mLock) {
+ try {
+ enforceStatusBarServicePermission("listen for volume changes", pid, uid);
+ mRemoteVolumeControllers.unregister(rvc);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7f1b25ca..042ac8c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1689,6 +1689,9 @@
mPreferencesHelper.lockChannelsForOEM(getContext().getResources().getStringArray(
com.android.internal.R.array.config_nonBlockableNotificationPackages));
+
+ mZenModeHelper.setPriorityOnlyDndExemptPackages(getContext().getResources().getStringArray(
+ com.android.internal.R.array.config_priorityOnlyDndExemptPackages));
}
@Override
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 7e74cc2..1f5b99c 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -80,6 +80,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -96,7 +97,7 @@
private final Context mContext;
private final H mHandler;
private final SettingsObserver mSettingsObserver;
- @VisibleForTesting protected final AppOpsManager mAppOps;
+ private final AppOpsManager mAppOps;
@VisibleForTesting protected final NotificationManager mNotificationManager;
@VisibleForTesting protected ZenModeConfig mDefaultConfig;
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
@@ -123,11 +124,13 @@
@VisibleForTesting protected boolean mIsBootComplete;
+ private String[] mPriorityOnlyDndExemptPackages;
+
public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
mContext = context;
mHandler = new H(looper);
addCallback(mMetrics);
- mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ mAppOps = context.getSystemService(AppOpsManager.class);
mNotificationManager = context.getSystemService(NotificationManager.class);
mDefaultConfig = readDefaultConfig(mContext.getResources());
@@ -214,6 +217,10 @@
loadConfigForUser(user, "onUserUnlocked");
}
+ void setPriorityOnlyDndExemptPackages(String[] packages) {
+ mPriorityOnlyDndExemptPackages = packages;
+ }
+
private void loadConfigForUser(int user, String reason) {
if (mUser == user || user < UserHandle.USER_SYSTEM) return;
mUser = user;
@@ -994,53 +1001,47 @@
for (int usage : AudioAttributes.SDK_USAGES) {
final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
- applyRestrictions(false /*mute*/, usage);
+ applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
- applyRestrictions(muteNotifications || muteEverything, usage);
+ applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
- applyRestrictions(muteCalls || muteEverything, usage);
+ applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
- applyRestrictions(muteAlarms || muteEverything, usage);
+ applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
- applyRestrictions(muteMedia || muteEverything, usage);
+ applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
// normally DND will only restrict touch sounds, not haptic feedback/vibrations
- applyRestrictions(muteSystem || muteEverything, usage,
+ applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage,
AppOpsManager.OP_PLAY_AUDIO);
- applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE);
+ applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE);
} else {
- applyRestrictions(muteSystem || muteEverything, usage);
+ applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage);
}
} else {
- applyRestrictions(muteEverything, usage);
+ applyRestrictions(zenPriorityOnly, muteEverything, usage);
}
}
}
@VisibleForTesting
- protected void applyRestrictions(boolean mute, int usage, int code) {
- final String[] exceptionPackages = null; // none (for now)
-
- // Only do this if we are executing within the system process... otherwise
- // we are running as test code, so don't have access to the protected call.
- if (Process.myUid() == Process.SYSTEM_UID) {
- final long ident = Binder.clearCallingIdentity();
- try {
- mAppOps.setRestriction(code, usage,
- mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mAppOps.setRestriction(code, usage,
+ mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+ zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@VisibleForTesting
- protected void applyRestrictions(boolean mute, int usage) {
- applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE);
- applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO);
+ protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) {
+ applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE);
+ applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7b418b5..77e7df8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2801,6 +2801,11 @@
if (disabledPs.codePath == null || !disabledPs.codePath.exists()
|| disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
+ } else {
+ // We're expecting that the system app should remain disabled, but add
+ // it to expecting better to recover in case the data version cannot
+ // be scanned.
+ mExpectingBetter.put(disabledPs.name, disabledPs.codePath);
}
}
}
@@ -9334,6 +9339,7 @@
| SCAN_UPDATE_SIGNATURE, currentTime, user);
if (scanResult.success) {
synchronized (mPackages) {
+ boolean appIdCreated = false;
try {
final String pkgName = scanResult.pkgSetting.name;
final Map<String, ReconciledPackage> reconcileResult = reconcilePackagesLocked(
@@ -9346,11 +9352,12 @@
Collections.singletonMap(pkgName,
getSharedLibLatestVersionSetting(scanResult))),
mSettings.mKeySetManagerService);
- prepareScanResultLocked(scanResult);
- commitReconciledScanResultLocked(
- reconcileResult.get(pkgName));
+ appIdCreated = optimisticallyRegisterAppId(scanResult);
+ commitReconciledScanResultLocked(reconcileResult.get(pkgName));
} catch (PackageManagerException e) {
- unprepareScanResultLocked(scanResult);
+ if (appIdCreated) {
+ cleanUpAppIdCreation(scanResult);
+ }
throw e;
}
}
@@ -10837,27 +10844,32 @@
}
- /** Prepares the system to commit a {@link ScanResult} in a way that will not fail. */
- private void prepareScanResultLocked(@NonNull ScanResult result)
+ /**
+ * Prepares the system to commit a {@link ScanResult} in a way that will not fail by registering
+ * the app ID required for reconcile.
+ * @return {@code true} if a new app ID was registered and will need to be cleaned up on
+ * failure.
+ */
+ private boolean optimisticallyRegisterAppId(@NonNull ScanResult result)
throws PackageManagerException {
if (!result.existingSettingCopied) {
// THROWS: when we can't allocate a user id. add call to check if there's
// enough space to ensure we won't throw; otherwise, don't modify state
- mSettings.registerAppIdLPw(result.pkgSetting);
+ return mSettings.registerAppIdLPw(result.pkgSetting);
}
+ return false;
}
/**
- * Reverts any changes to the system that were made by
- * {@link #prepareScanResultLocked(ScanResult)}
+ * Reverts any app ID creation that were made by
+ * {@link #optimisticallyRegisterAppId(ScanResult)}. Note: this is only necessary if the
+ * referenced method returned true.
*/
- private void unprepareScanResultLocked(@NonNull ScanResult result) {
- if (!result.existingSettingCopied) {
- // iff we've acquired an app ID for a new package setting, remove it so that it can be
- // acquired by another request.
- if (result.pkgSetting.appId > 0) {
- mSettings.removeAppIdLPw(result.pkgSetting.appId);
- }
+ private void cleanUpAppIdCreation(@NonNull ScanResult result) {
+ // iff we've acquired an app ID for a new package setting, remove it so that it can be
+ // acquired by another request.
+ if (result.pkgSetting.appId > 0) {
+ mSettings.removeAppIdLPw(result.pkgSetting.appId);
}
}
@@ -16701,6 +16713,7 @@
final Map<String, VersionInfo> versionInfos = new ArrayMap<>(requests.size());
final Map<String, PackageSetting> lastStaticSharedLibSettings =
new ArrayMap<>(requests.size());
+ final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
boolean success = false;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
@@ -16740,7 +16753,7 @@
+ " in multi-package install request.");
return;
}
- prepareScanResultLocked(result);
+ createdAppId.put(packageName, optimisticallyRegisterAppId(result));
versionInfos.put(result.pkgSetting.pkg.packageName,
getSettingsVersionForPackage(result.pkgSetting.pkg));
if (result.staticSharedLibraryInfo != null) {
@@ -16797,7 +16810,9 @@
} finally {
if (!success) {
for (ScanResult result : preparedScans.values()) {
- unprepareScanResultLocked(result);
+ if (createdAppId.getOrDefault(result.request.pkg.packageName, false)) {
+ cleanUpAppIdCreation(result);
+ }
}
}
for (PrepareResult result : prepareResults.values()) {
@@ -19890,26 +19905,28 @@
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, false /* checkShell */,
"replace preferred activity");
- synchronized (mPackages) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
- != PackageManager.PERMISSION_GRANTED) {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
+ != PackageManager.PERMISSION_GRANTED) {
+ synchronized (mPackages) {
if (getUidTargetSdkVersionLockedLPr(callingUid)
< Build.VERSION_CODES.FROYO) {
Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
+ Binder.getCallingUid());
return;
}
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
}
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
+ }
- PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
+ synchronized (mPackages) {
+ final PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
if (pir != null) {
// Get all of the existing entries that exactly match this filter.
- ArrayList<PreferredActivity> existing = pir.findFilters(filter);
+ final ArrayList<PreferredActivity> existing = pir.findFilters(filter);
if (existing != null && existing.size() == 1) {
- PreferredActivity cur = existing.get(0);
+ final PreferredActivity cur = existing.get(0);
if (DEBUG_PREFERRED) {
Slog.i(TAG, "Checking replace of preferred:");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
@@ -19939,14 +19956,13 @@
return;
}
}
-
if (existing != null) {
if (DEBUG_PREFERRED) {
Slog.i(TAG, existing.size() + " existing preferred matches for:");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
}
- for (int i = 0; i < existing.size(); i++) {
- PreferredActivity pa = existing.get(i);
+ for (int i = existing.size() - 1; i >= 0; --i) {
+ final PreferredActivity pa = existing.get(i);
if (DEBUG_PREFERRED) {
Slog.i(TAG, "Removing existing preferred activity "
+ pa.mPref.mComponent + ":");
@@ -19956,9 +19972,9 @@
}
}
}
- addPreferredActivityInternal(filter, match, set, activity, true, userId,
- "Replacing preferred");
}
+ addPreferredActivityInternal(filter, match, set, activity, true, userId,
+ "Replacing preferred");
}
@Override
@@ -20032,7 +20048,7 @@
PreferredActivity pa = removed.get(j);
pir.removeFilter(pa);
}
- outUserChanged.setValueAt(thisUserId, true);
+ outUserChanged.put(thisUserId, true);
}
}
}
@@ -20752,8 +20768,16 @@
}
@Override
- public String getAttentionServicePackageName() {
- return mContext.getString(R.string.config_defaultAttentionService);
+ public @Nullable String getAttentionServicePackageName() {
+ final String flattenedComponentName =
+ mContext.getString(R.string.config_defaultAttentionService);
+ if (flattenedComponentName != null) {
+ ComponentName componentName = ComponentName.unflattenFromString(flattenedComponentName);
+ if (componentName != null && componentName.getPackageName() != null) {
+ return componentName.getPackageName();
+ }
+ }
+ return null;
}
private @Nullable String getDocumenterPackageName() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 4e4a0e4..6b804df 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2423,6 +2423,16 @@
sessionParams.setStaged();
break;
case "--enable-rollback":
+ if (params.installerPackageName == null) {
+ // com.android.shell has the TEST_MANAGE_ROLLBACKS
+ // permission needed to enable rollback for non-module
+ // packages, which is likely what the user wants when
+ // enabling rollback through the shell command. Set
+ // the installer to com.android.shell if no installer
+ // has been provided so that the user doesn't have to
+ // remember to set it themselves.
+ params.installerPackageName = "com.android.shell";
+ }
sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
break;
default:
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 41a8a77..dae07bd 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -810,15 +810,20 @@
/**
* Registers a user ID with the system. Potentially allocates a new user ID.
+ * @return {@code true} if a new app ID was created in the process. {@code false} can be
+ * returned in the case that a shared user ID already exists or the explicit app ID is
+ * already registered.
* @throws PackageManagerException If a user ID could not be allocated.
*/
- void registerAppIdLPw(PackageSetting p) throws PackageManagerException {
+ boolean registerAppIdLPw(PackageSetting p) throws PackageManagerException {
+ final boolean createdNew;
if (p.appId == 0) {
// Assign new user ID
p.appId = acquireAndRegisterNewAppIdLPw(p);
+ createdNew = true;
} else {
// Add new setting to list of user IDs
- registerExistingAppIdLPw(p.appId, p, p.name);
+ createdNew = registerExistingAppIdLPw(p.appId, p, p.name);
}
if (p.appId < 0) {
PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -826,6 +831,7 @@
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Package " + p.name + " could not be assigned a valid UID");
}
+ return createdNew;
}
/**
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index d9d21ba..5e829b2 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -16,9 +16,14 @@
package com.android.server.power;
+import static android.provider.Settings.System.ADAPTIVE_SLEEP;
+
+import android.Manifest;
import android.attention.AttentionManagerInternal;
import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.PowerManager;
@@ -83,6 +88,12 @@
@VisibleForTesting
protected AttentionManagerInternal mAttentionManager;
+ @VisibleForTesting
+ protected PackageManager mPackageManager;
+
+ @VisibleForTesting
+ protected ContentResolver mContentResolver;
+
/**
* Current wakefulness of the device. {@see PowerManagerInternal}
*/
@@ -137,6 +148,8 @@
public void systemReady(Context context) {
updateEnabledFromSettings(context);
+ mPackageManager = context.getPackageManager();
+ mContentResolver = context.getContentResolver();
mAttentionManager = LocalServices.getService(AttentionManagerInternal.class);
mMaximumExtensionMillis = context.getResources().getInteger(
com.android.internal.R.integer.config_attentionMaximumExtension);
@@ -162,6 +175,11 @@
return nextScreenDimming;
}
+ if (!serviceHasSufficientPermissions()) {
+ Settings.System.putInt(mContentResolver, ADAPTIVE_SLEEP, 0);
+ return nextScreenDimming;
+ }
+
final long now = SystemClock.uptimeMillis();
final long whenToCheck = nextScreenDimming - getAttentionTimeout();
final long whenToStopExtending = mLastUserActivityTime + mMaximumExtensionMillis;
@@ -263,6 +281,18 @@
return mAttentionManager != null && mAttentionManager.isAttentionServiceSupported();
}
+ /**
+ * Returns {@code true} if the attention service has sufficient permissions, disables the
+ * depending features otherwise.
+ */
+ @VisibleForTesting
+ boolean serviceHasSufficientPermissions() {
+ final String attentionPackage = mPackageManager.getAttentionServicePackageName();
+ return attentionPackage != null && mPackageManager.checkPermission(
+ Manifest.permission.CAMERA, attentionPackage)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
public void dump(PrintWriter pw) {
pw.print("AttentionDetector:");
pw.print(" mMaximumExtensionMillis=" + mMaximumExtensionMillis);
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index b2ac1b8..654c477 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -147,6 +147,8 @@
mLegacyRoleResolver = legacyRoleResolver;
+ RoleControllerManager.initializeRemoteServiceComponentName(context);
+
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
@@ -231,7 +233,7 @@
// Run grants again
Slog.i(LOG_TAG, "Granting default permissions...");
CompletableFuture<Void> result = new CompletableFuture<>();
- getOrCreateControllerService(userId).grantDefaultRoles(FgThread.getExecutor(),
+ getOrCreateController(userId).grantDefaultRoles(FgThread.getExecutor(),
successful -> {
if (successful) {
userState.setPackagesHash(packagesHash);
@@ -318,7 +320,7 @@
}
@NonNull
- private RoleControllerManager getOrCreateControllerService(@UserIdInt int userId) {
+ private RoleControllerManager getOrCreateController(@UserIdInt int userId) {
synchronized (mLock) {
RoleControllerManager controller = mControllers.get(userId);
if (controller == null) {
@@ -330,7 +332,8 @@
} catch (NameNotFoundException e) {
throw new RuntimeException(e);
}
- controller = new RoleControllerManager(context, FgThread.getHandler());
+ controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName(
+ FgThread.getHandler(), context);
mControllers.put(userId, controller);
}
return controller;
@@ -474,7 +477,7 @@
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
- getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, flags,
+ getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags,
callback);
}
@@ -494,7 +497,7 @@
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
- getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName, flags,
+ getOrCreateController(userId).onRemoveRoleHolder(roleName, packageName, flags,
callback);
}
@@ -513,7 +516,7 @@
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
- getOrCreateControllerService(userId).onClearRoleHolders(roleName, flags, callback);
+ getOrCreateController(userId).onClearRoleHolders(roleName, flags, callback);
}
@Override
@@ -738,10 +741,10 @@
}
});
if (packageName != null) {
- getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
+ getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
packageName, 0, callback);
} else {
- getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
+ getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
callback);
}
try {
@@ -762,10 +765,10 @@
}
});
if (packageName != null) {
- getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
+ getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
packageName, 0, callback);
} else {
- getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
+ getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
callback);
}
}
@@ -791,10 +794,10 @@
callback.accept(successful);
});
if (packageName != null) {
- getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
+ getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
packageName, 0, remoteCallback);
} else {
- getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
+ getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
remoteCallback);
}
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 10ed88f..da9bc16 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -64,6 +64,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.CoolingDevice;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
@@ -1798,6 +1799,28 @@
e.writeInt(temp.getType());
e.writeString(temp.getName());
e.writeInt((int) (temp.getValue() * 10));
+ e.writeInt(temp.getStatus());
+ pulledData.add(e);
+ }
+ } catch (RemoteException e) {
+ // Should not happen.
+ Slog.e(TAG, "Disconnected from thermal service. Cannot pull temperatures.");
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ }
+
+ private void pullCoolingDevices(int tagId, long elapsedNanos, long wallClockNanos,
+ List<StatsLogEventWrapper> pulledData) {
+ long callingToken = Binder.clearCallingIdentity();
+ try {
+ List<CoolingDevice> devices = sThermalService.getCurrentCoolingDevices();
+ for (CoolingDevice device : devices) {
+ StatsLogEventWrapper e =
+ new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+ e.writeInt(device.getType());
+ e.writeString(device.getName());
+ e.writeInt((int) (device.getValue()));
pulledData.add(e);
}
} catch (RemoteException e) {
@@ -2084,6 +2107,9 @@
e.writeBoolean(Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 0,
userId) != 0);
+ e.writeBoolean(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED, 1,
+ userId) != 0);
pulledData.add(e);
}
@@ -2268,6 +2294,10 @@
pullTemperature(tagId, elapsedNanos, wallClockNanos, ret);
break;
}
+ case StatsLog.COOLING_DEVICE: {
+ pullCoolingDevices(tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
case StatsLog.DEBUG_ELAPSED_CLOCK: {
pullDebugElapsedClock(tagId, elapsedNanos, wallClockNanos, ret);
break;
@@ -2532,12 +2562,9 @@
private static final class ThermalEventListener extends IThermalEventListener.Stub {
@Override
public void notifyThrottling(Temperature temp) {
- boolean isThrottling = temp.getStatus() >= Temperature.THROTTLING_SEVERE;
StatsLog.write(StatsLog.THERMAL_THROTTLING, temp.getType(),
- isThrottling ?
- StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__START :
- StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__STOP,
- temp.getValue());
+ StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__UNKNOWN,
+ temp.getValue(), temp.getStatus(), temp.getName());
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index b287a0b..7eac07c 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -457,7 +457,7 @@
"pendingActivityLaunch");
try {
starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags,
- resume, pal.r.pendingOptions, null, null /* outRecords */);
+ resume, pal.r.pendingOptions, null);
} catch (Exception e) {
Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
pal.sendErrorResult(e.getMessage());
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 8957444..4ef8753 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -544,11 +544,17 @@
*/
int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
- ActivityRecord[] outActivity) {
+ int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
try {
- return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
- doResume, options, inTask, outActivity);
+ mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(r.intent);
+ mLastStartReason = "startResolvedActivity";
+ mLastStartActivityTimeMs = System.currentTimeMillis();
+ mLastStartActivityRecord[0] = r;
+ mLastStartActivityResult = startActivity(r, sourceRecord, voiceSession, voiceInteractor,
+ startFlags, doResume, options, inTask, mLastStartActivityRecord);
+ mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(mLastStartActivityResult,
+ mLastStartActivityRecord[0]);
+ return mLastStartActivityResult;
} finally {
onExecutionComplete();
}
@@ -965,8 +971,9 @@
: (realCallingUid == Process.SYSTEM_UID)
|| realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
if (realCallingUid != callingUid) {
- // don't abort if the realCallingUid has a visible window
- if (realCallingUidHasAnyVisibleWindow) {
+ // don't abort if the realCallingUid has a visible window, unless realCallingUid is
+ // SYSTEM_UID, in which case it start needs to be explicitly whitelisted
+ if (realCallingUidHasAnyVisibleWindow && realCallingUid != Process.SYSTEM_UID) {
return false;
}
// if the realCallingUid is a persistent system process, abort if the IntentSender
@@ -980,31 +987,6 @@
return false;
}
}
- // If we don't have callerApp at this point, no caller was provided to startActivity().
- // That's the case for PendingIntent-based starts, since the creator's process might not be
- // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
- // caller, so that we can make the decision based on its foreground/whitelisted state.
- if (callerApp == null) {
- callerApp = mService.getProcessController(realCallingPid, realCallingUid);
- }
- if (callerApp != null) {
- // don't abort if the callerApp is instrumenting with background activity starts privs
- if (callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
- return false;
- }
- // don't abort if the caller is currently temporarily whitelisted
- 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 caller is bound by a UID that's currently foreground
- if (isBoundByForegroundUid(callerApp)) {
- return false;
- }
- }
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
== PERMISSION_GRANTED) {
@@ -1029,6 +1011,33 @@
+ " temporarily whitelisted. This will not be supported in future Q builds.");
return false;
}
+ // If we don't have callerApp at this point, no caller was provided to startActivity().
+ // That's the case for PendingIntent-based starts, since the creator's process might not be
+ // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
+ // caller, so that we can make the decision based on its foreground/whitelisted state.
+ int callerAppUid = callingUid;
+ if (callerApp == null) {
+ callerApp = mService.getProcessController(realCallingPid, realCallingUid);
+ callerAppUid = realCallingUid;
+ }
+ // don't abort if the callerApp or other processes of that uid are whitelisted in any way
+ if (callerApp != null) {
+ // first check the original calling process
+ if (callerApp.areBackgroundActivityStartsAllowed()) {
+ return false;
+ }
+ // only if that one wasn't whitelisted, check the other ones
+ final ArraySet<WindowProcessController> uidProcesses =
+ mService.mProcessMap.getProcesses(callerAppUid);
+ if (uidProcesses != null) {
+ for (int i = uidProcesses.size() - 1; i >= 0; i--) {
+ final WindowProcessController proc = uidProcesses.valueAt(i);
+ if (proc != callerApp && proc.areBackgroundActivityStartsAllowed()) {
+ return false;
+ }
+ }
+ }
+ }
// anything that has fallen through would currently be aborted
Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
+ "; callingUid: " + callingUid
@@ -1053,17 +1062,6 @@
return true;
}
- private boolean isBoundByForegroundUid(WindowProcessController callerApp) {
- final ArraySet<Integer> boundClientUids = callerApp.getBoundClientUids();
- for (int i = boundClientUids.size() - 1; i >= 0; --i) {
- final int uid = boundClientUids.valueAt(i);
- if (mService.isUidForeground(uid)) {
- return true;
- }
- }
- return false;
- }
-
// TODO: remove this toast after feature development is done
void showBackgroundActivityBlockedToast(boolean abort, String callingPackage) {
final Resources res = mService.mContext.getResources();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 76774d7..3fa0268 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -373,8 +373,8 @@
private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
/** All processes currently running that might have a window organized by name. */
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
- /** All processes we currently have running mapped by pid */
- final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
+ /** All processes we currently have running mapped by pid and uid */
+ final WindowProcessControllerMap mProcessMap = new WindowProcessControllerMap();
/** This is the process holding what we currently consider to be the "home" activity. */
WindowProcessController mHomeProcess;
/** The currently running heavy-weight process, if any. */
@@ -913,7 +913,7 @@
return getGlobalConfiguration();
}
synchronized (mGlobalLock) {
- final WindowProcessController app = mPidMap.get(pid);
+ final WindowProcessController app = mProcessMap.getProcess(pid);
return app != null ? app.getConfiguration() : getGlobalConfiguration();
}
}
@@ -4640,7 +4640,7 @@
enforceSystemHasVrFeature();
synchronized (mGlobalLock) {
final int pid = Binder.getCallingPid();
- final WindowProcessController wpc = mPidMap.get(pid);
+ final WindowProcessController wpc = mProcessMap.getProcess(pid);
mVrController.setVrThreadLocked(tid, pid, wpc);
}
}
@@ -4659,7 +4659,7 @@
enforceSystemHasVrFeature();
synchronized (mGlobalLock) {
final int pid = Binder.getCallingPid();
- final WindowProcessController proc = mPidMap.get(pid);
+ final WindowProcessController proc = mProcessMap.getProcess(pid);
mVrController.setPersistentVrThreadLocked(tid, pid, proc);
}
}
@@ -5204,9 +5204,10 @@
mH.sendMessage(msg);
}
- for (int i = mPidMap.size() - 1; i >= 0; i--) {
- final int pid = mPidMap.keyAt(i);
- final WindowProcessController app = mPidMap.get(pid);
+ SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap();
+ for (int i = pidMap.size() - 1; i >= 0; i--) {
+ final int pid = pidMap.keyAt(i);
+ final WindowProcessController app = pidMap.get(pid);
if (DEBUG_CONFIGURATION) {
Slog.v(TAG_CONFIGURATION, "Update process config of "
+ app.mName + " to new config " + configCopy);
@@ -5859,7 +5860,7 @@
}
WindowProcessController getProcessController(int pid, int uid) {
- final WindowProcessController proc = mPidMap.get(pid);
+ final WindowProcessController proc = mProcessMap.getProcess(pid);
if (proc == null) return null;
if (UserHandle.isApp(uid) && proc.mUid == uid) {
return proc;
@@ -6423,14 +6424,14 @@
@Override
public void onProcessMapped(int pid, WindowProcessController proc) {
synchronized (mGlobalLock) {
- mPidMap.put(pid, proc);
+ mProcessMap.put(pid, proc);
}
}
@Override
public void onProcessUnMapped(int pid) {
synchronized (mGlobalLock) {
- mPidMap.remove(pid);
+ mProcessMap.remove(pid);
}
}
@@ -6503,7 +6504,7 @@
}
return;
}
- final WindowProcessController process = mPidMap.get(pid);
+ final WindowProcessController process = mProcessMap.getProcess(pid);
if (process == null) {
if (DEBUG_CONFIGURATION) {
Slog.w(TAG, "Trying to update display configuration for invalid "
@@ -6696,7 +6697,7 @@
// Only allow this from foreground processes, so that background
// applications can't abuse it to prevent system UI from being shown.
if (uid >= FIRST_APPLICATION_UID) {
- final WindowProcessController proc = mPidMap.get(pid);
+ final WindowProcessController proc = mProcessMap.getProcess(pid);
if (!proc.isPerceptible()) {
Slog.w(TAG, "Ignoring closeSystemDialogs " + reason
+ " from background process " + proc);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index c1d872f..b5e7067 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -435,6 +435,18 @@
moveFromFullscreen, moveToFullscreen, animationType);
}
+ /**
+ * Cancel existing animation if the destination was modified.
+ */
+ void cancel(final BoundsAnimationTarget target) {
+ final BoundsAnimator existing = mRunningAnimations.get(target);
+ if (existing != null) {
+ // Cancel animation. Since its already started, send animation end to client.
+ if (DEBUG) Slog.d(TAG, "cancel: mTarget= " + target);
+ existing.cancelAndCallAnimationEnd();
+ }
+ }
+
@VisibleForTesting
BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to,
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index c8f8e82..104805f 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -48,6 +48,7 @@
import android.os.RemoteException;
import android.util.AtomicFile;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Xml;
public final class CompatModePackages {
@@ -324,8 +325,9 @@
ActivityRecord starting = stack.restartPackage(packageName);
// Tell all processes that loaded this package about the change.
- for (int i = mService.mPidMap.size() - 1; i >= 0; i--) {
- final WindowProcessController app = mService.mPidMap.valueAt(i);
+ SparseArray<WindowProcessController> pidMap = mService.mProcessMap.getPidMap();
+ for (int i = pidMap.size() - 1; i >= 0; i--) {
+ final WindowProcessController app = pidMap.valueAt(i);
if (!app.mPkgList.contains(packageName)) {
continue;
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 1934e25..bd874ba 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -28,6 +28,7 @@
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.InsetsState.TYPE_TOP_GESTURES;
import static android.view.InsetsState.TYPE_TOP_TAPPABLE_ELEMENT;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
@@ -1230,7 +1231,7 @@
final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
if (layoutInScreenAndInsetDecor && !screenDecor) {
- if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
+ if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
outFrame.set(displayFrames.mUnrestricted);
} else {
outFrame.set(displayFrames.mRestricted);
@@ -1290,7 +1291,7 @@
&& attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
|| forceWindowDrawsBarBackgrounds) {
- impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ impliedFlags |= SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
}
return impliedFlags;
@@ -1722,6 +1723,22 @@
of.set(displayFrames.mDock);
df.set(displayFrames.mDock);
} else {
+
+ // In case we forced the window to draw behind the navigation bar, restrict df/of to
+ // DF.RestrictedOverscan to simulate old compat behavior.
+ Rect parentDisplayFrame = attached.getDisplayFrameLw();
+ Rect parentOverscan = attached.getOverscanFrameLw();
+ final WindowManager.LayoutParams attachedAttrs = attached.mAttrs;
+ if ((attachedAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
+ && (attachedAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
+ && (attachedAttrs.systemUiVisibility
+ & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0) {
+ parentOverscan = new Rect(parentOverscan);
+ parentOverscan.intersect(displayFrames.mRestrictedOverscan);
+ parentDisplayFrame = new Rect(parentDisplayFrame);
+ parentDisplayFrame.intersect(displayFrames.mRestrictedOverscan);
+ }
+
// The effective display frame of the attached window depends on whether it is taking
// care of insetting its content. If not, we need to use the parent's content frame so
// that the entire window is positioned within that content. Otherwise we can use the
@@ -1733,7 +1750,7 @@
// setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
// Otherwise, use the overscan frame.
cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
- ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
+ ? attached.getContentFrameLw() : parentOverscan);
} else {
// If the window is resizing, then we want to base the content frame on our attached
// content frame to resize...however, things can be tricky if the attached window is
@@ -1747,8 +1764,8 @@
cf.intersectUnchecked(displayFrames.mContent);
}
}
- df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
- of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
+ df.set(insetDecors ? parentDisplayFrame : cf);
+ of.set(insetDecors ? parentOverscan : cf);
vf.set(attached.getVisibleFrameLw());
}
// The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be
@@ -1956,7 +1973,7 @@
of.set(displayFrames.mOverscan);
df.set(displayFrames.mOverscan);
pf.set(displayFrames.mOverscan);
- } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+ } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
&& (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
|| type == TYPE_VOLUME_OVERLAY)) {
// Asking for layout as if the nav bar is hidden, lets the application
@@ -2006,7 +2023,7 @@
}
} else if (layoutInScreen || (sysUiFl
& (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
+ | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
+ "): IN_SCREEN");
// A window that has requested to fill the entire screen just
@@ -2051,7 +2068,7 @@
of.set(displayFrames.mOverscan);
df.set(displayFrames.mOverscan);
pf.set(displayFrames.mOverscan);
- } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+ } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
&& (type == TYPE_STATUS_BAR
|| type == TYPE_TOAST
|| type == TYPE_DOCK_DIVIDER
diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
index 3d20501..d774dc3 100644
--- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
@@ -90,8 +90,6 @@
mShowDelayMs = getNavBarExitDuration() * 3;
mPanicThresholdMs = context.getResources()
.getInteger(R.integer.config_immersive_mode_confirmation_panic);
- mWindowManager = (WindowManager)
- mContext.getSystemService(Context.WINDOW_SERVICE);
mVrModeEnabled = vrModeEnabled;
}
@@ -177,7 +175,7 @@
private void handleHide() {
if (mClingWindow != null) {
if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation");
- mWindowManager.removeView(mClingWindow);
+ getWindowManager().removeView(mClingWindow);
mClingWindow = null;
}
}
@@ -275,7 +273,7 @@
super.onAttachedToWindow();
DisplayMetrics metrics = new DisplayMetrics();
- mWindowManager.getDefaultDisplay().getMetrics(metrics);
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
@@ -341,6 +339,19 @@
}
}
+ /**
+ * DO HOLD THE WINDOW MANAGER LOCK WHEN CALLING THIS METHOD
+ * The reason why we add this method is to avoid the deadlock of WMG->WMS and WMS->WMG
+ * when ImmersiveModeConfirmation object is created.
+ */
+ private WindowManager getWindowManager() {
+ if (mWindowManager == null) {
+ mWindowManager = (WindowManager)
+ mContext.getSystemService(Context.WINDOW_SERVICE);
+ }
+ return mWindowManager;
+ }
+
private void handleShow() {
if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation");
@@ -352,7 +363,7 @@
// show the confirmation
WindowManager.LayoutParams lp = getClingWindowLayoutParams();
- mWindowManager.addView(mClingWindow, lp);
+ getWindowManager().addView(mClingWindow, lp);
}
private final Runnable mConfirm = new Runnable() {
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index d6c7b21..7dcbedf 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -60,7 +60,6 @@
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -185,7 +184,6 @@
// front. Newly created tasks, or tasks that are removed from the list will continue to change
// the list. This does not affect affiliated tasks.
private boolean mFreezeTaskListReordering;
- private long mFreezeTaskListReorderingTime;
private long mFreezeTaskListTimeoutMs = FREEZE_TASK_LIST_TIMEOUT_MS;
// Mainly to avoid object recreation on multiple calls.
@@ -220,6 +218,9 @@
}
};
+ private final Runnable mResetFreezeTaskListOnTimeoutRunnable =
+ this::resetFreezeTaskListReorderingOnTimeout;
+
@VisibleForTesting
RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
mService = service;
@@ -255,8 +256,7 @@
}
@VisibleForTesting
- void setFreezeTaskListTimeoutParams(long reorderingTime, long timeoutMs) {
- mFreezeTaskListReorderingTime = reorderingTime;
+ void setFreezeTaskListTimeout(long timeoutMs) {
mFreezeTaskListTimeoutMs = timeoutMs;
}
@@ -272,7 +272,8 @@
// Always update the reordering time when this is called to ensure that the timeout
// is reset
mFreezeTaskListReordering = true;
- mFreezeTaskListReorderingTime = SystemClock.elapsedRealtime();
+ mService.mH.removeCallbacks(mResetFreezeTaskListOnTimeoutRunnable);
+ mService.mH.postDelayed(mResetFreezeTaskListOnTimeoutRunnable, mFreezeTaskListTimeoutMs);
}
/**
@@ -286,6 +287,7 @@
// Once we end freezing the task list, reset the existing task order to the stable state
mFreezeTaskListReordering = false;
+ mService.mH.removeCallbacks(mResetFreezeTaskListOnTimeoutRunnable);
// If the top task is provided, then restore the top task to the front of the list
if (topTask != null) {
@@ -295,6 +297,8 @@
// Resume trimming tasks
trimInactiveRecentTasks();
+
+ mService.getTaskChangeNotificationController().notifyTaskStackChanged();
}
/**
@@ -302,13 +306,8 @@
* before we need to iterate the task list in order (either for purposes of returning the list
* to SystemUI or if we need to trim tasks in order)
*/
+ @VisibleForTesting
void resetFreezeTaskListReorderingOnTimeout() {
- // Unfreeze the recent task list if the time heuristic has passed
- if (mFreezeTaskListReorderingTime
- > (SystemClock.elapsedRealtime() - mFreezeTaskListTimeoutMs)) {
- return;
- }
-
final ActivityStack focusedStack = mService.getTopDisplayFocusedStack();
final TaskRecord topTask = focusedStack != null
? focusedStack.topTask()
@@ -875,9 +874,6 @@
final Set<Integer> includedUsers = getProfileIds(userId);
includedUsers.add(Integer.valueOf(userId));
- // Check if the frozen task list has timed out
- resetFreezeTaskListReorderingOnTimeout();
-
final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
final int size = mTasks.size();
int numVisibleTasks = 0;
@@ -1654,8 +1650,8 @@
pw.println("mRecentsUid=" + mRecentsUid);
pw.println("mRecentsComponent=" + mRecentsComponent);
pw.println("mFreezeTaskListReordering=" + mFreezeTaskListReordering);
- pw.println("mFreezeTaskListReorderingTime (time since)="
- + (SystemClock.elapsedRealtime() - mFreezeTaskListReorderingTime) + "ms");
+ pw.println("mFreezeTaskListReorderingPendingTimeout="
+ + mService.mH.hasCallbacks(mResetFreezeTaskListOnTimeoutRunnable));
if (mTasks.isEmpty()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f9fd541..9f42324 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -22,6 +22,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -312,11 +313,12 @@
/**
* Returns true if the callingUid has any non-toast window currently visible to the user.
+ * Also ignores TYPE_APPLICATION_STARTING, since those windows don't belong to apps.
*/
boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
return forAllWindows(w ->
w.getOwningUid() == callingUid && w.mAttrs.type != TYPE_TOAST
- && w.isVisibleNow(),
+ && w.mAttrs.type != TYPE_APPLICATION_STARTING && w.isVisibleNow(),
true /* traverseTopToBottom */);
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index bdb4d04..7515b3f 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -388,7 +388,9 @@
* @return true if bounds were updated to some non-empty value.
*/
boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) {
+ boolean animating = false;
if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
+ animating = true;
getFinalAnimationBounds(mTmpRect2);
} else {
mTmpRect2.set(inOutBounds);
@@ -398,6 +400,13 @@
if (updated) {
inOutBounds.set(mTmpRect3);
+ // The final boundary is updated while there is an existing boundary animation. Let's
+ // cancel this animation to prevent the obsolete animation overwritten updated bounds.
+ if (animating && !inOutBounds.equals(mBoundsAnimationTarget)) {
+ final DisplayContent displayContent = getDisplayContent();
+ displayContent.mBoundsAnimationController.getHandler().post(() ->
+ displayContent.mBoundsAnimationController.cancel(this));
+ }
// Once we've set the bounds based on the rotation of the old bounds in the new
// orientation, clear the animation target bounds since they are obsolete, and
// cancel any currently running animations
@@ -1585,7 +1594,6 @@
mBoundsAnimatingRequested = false;
mBoundsAnimating = true;
- mCancelCurrentBoundsAnimation = false;
mAnimationType = animationType;
// If we are changing UI mode, as in the PiP to fullscreen
@@ -1645,7 +1653,7 @@
mBoundsAnimationTarget, false /* forceUpdate */);
}
- if (finalStackSize != null) {
+ if (finalStackSize != null && !mCancelCurrentBoundsAnimation) {
setPinnedStackSize(finalStackSize, null);
} else {
// We have been canceled, so the final stack size is null, still run the
@@ -1758,6 +1766,7 @@
}
final @BoundsAnimationController.AnimationType int animationType = intendedAnimationType;
+ mCancelCurrentBoundsAnimation = false;
displayContent.mBoundsAnimationController.getHandler().post(() -> {
displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
finalToBounds, animationDuration, finalSchedulePipModeChangedState,
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 4ca35f7..eb919eb 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -372,18 +372,39 @@
mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
}
- public boolean areBackgroundActivityStartsAllowed() {
- return mAllowBackgroundActivityStarts;
+ boolean areBackgroundActivityStartsAllowed() {
+ // allow if the whitelisting flag was explicitly set
+ if (mAllowBackgroundActivityStarts) {
+ return true;
+ }
+ // allow if the proc is instrumenting with background activity starts privs
+ if (mInstrumentingWithBackgroundActivityStartPrivileges) {
+ return true;
+ }
+ // allow if the caller has an activity in any foreground task
+ if (hasActivityInVisibleTask()) {
+ return true;
+ }
+ // allow if the caller is bound by a UID that's currently foreground
+ if (isBoundByForegroundUid()) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isBoundByForegroundUid() {
+ for (int i = mBoundClientUids.size() - 1; i >= 0; --i) {
+ if (mAtm.isUidForeground(mBoundClientUids.valueAt(i))) {
+ return true;
+ }
+ }
+ return false;
}
public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
mBoundClientUids = boundClientUids;
}
- public ArraySet<Integer> getBoundClientUids() {
- return mBoundClientUids;
- }
-
public void setInstrumenting(boolean instrumenting,
boolean hasBackgroundActivityStartPrivileges) {
mInstrumenting = instrumenting;
@@ -394,14 +415,6 @@
return mInstrumenting;
}
- /**
- * @return true if the instrumentation was started by a holder of
- * START_ACTIVITIES_FROM_BACKGROUND permission
- */
- boolean isInstrumentingWithBackgroundActivityStartPrivileges() {
- return mInstrumentingWithBackgroundActivityStartPrivileges;
- }
-
public void setPerceptible(boolean perceptible) {
mPerceptible = perceptible;
}
@@ -487,7 +500,7 @@
}
}
- boolean hasActivityInVisibleTask() {
+ private boolean hasActivityInVisibleTask() {
for (int i = mActivities.size() - 1; i >= 0; --i) {
TaskRecord task = mActivities.get(i).getTaskRecord();
if (task == null) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessControllerMap.java b/services/core/java/com/android/server/wm/WindowProcessControllerMap.java
new file mode 100644
index 0000000..2767972
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowProcessControllerMap.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.util.ArraySet;
+import android.util.SparseArray;
+
+import java.util.Map;
+import java.util.HashMap;
+
+final class WindowProcessControllerMap {
+
+ /** All processes we currently have running mapped by pid */
+ private final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
+ /** All processes we currently have running mapped by uid */
+ private final Map<Integer, ArraySet<WindowProcessController>> mUidMap = new HashMap<>();
+
+ /** Retrieves a currently running process for pid. */
+ WindowProcessController getProcess(int pid) {
+ return mPidMap.get(pid);
+ }
+
+ /** Retrieves all currently running processes for uid. */
+ ArraySet<WindowProcessController> getProcesses(int uid) {
+ return mUidMap.get(uid);
+ }
+
+ SparseArray<WindowProcessController> getPidMap() {
+ return mPidMap;
+ }
+
+ void put(int pid, WindowProcessController proc) {
+ // if there is a process for this pid already in mPidMap it'll get replaced automagically,
+ // but we actually need to remove it from mUidMap too before adding the new one
+ final WindowProcessController prevProc = mPidMap.get(pid);
+ if (prevProc != null) {
+ removeProcessFromUidMap(prevProc);
+ }
+ // put process into mPidMap
+ mPidMap.put(pid, proc);
+ // put process into mUidMap
+ final int uid = proc.mUid;
+ ArraySet<WindowProcessController> procSet = mUidMap.getOrDefault(uid,
+ new ArraySet<WindowProcessController>());
+ procSet.add(proc);
+ mUidMap.put(uid, procSet);
+ }
+
+ void remove(int pid) {
+ final WindowProcessController proc = mPidMap.get(pid);
+ if (proc != null) {
+ // remove process from mPidMap
+ mPidMap.remove(pid);
+ // remove process from mUidMap
+ removeProcessFromUidMap(proc);
+ }
+ }
+
+ private void removeProcessFromUidMap(WindowProcessController proc) {
+ if (proc == null) {
+ return;
+ }
+ final int uid = proc.mUid;
+ ArraySet<WindowProcessController> procSet = mUidMap.get(uid);
+ if (procSet != null) {
+ procSet.remove(proc);
+ if (procSet.isEmpty()) {
+ mUidMap.remove(uid);
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d990e6c..8e18683 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1305,7 +1305,7 @@
void onDisplayChanged(DisplayContent dc) {
super.onDisplayChanged(dc);
// Window was not laid out for this display yet, so make sure mLayoutSeq does not match.
- if (dc != null) {
+ if (dc != null && mInputWindowHandle.displayId != dc.getDisplayId()) {
mLayoutSeq = dc.mLayoutSeq - 1;
mInputWindowHandle.displayId = dc.getDisplayId();
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0cd730b..2a2de77 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -32,7 +32,6 @@
import android.content.Intent;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.database.sqlite.SQLiteCompatibilityWalFlags;
@@ -1248,11 +1247,6 @@
mSystemServiceManager.startService(CONTENT_SUGGESTIONS_SERVICE_CLASS);
traceEnd();
- // NOTE: ClipboardService indirectly depends on IntelligenceService
- traceBeginAndSlog("StartClipboardService");
- mSystemServiceManager.startService(ClipboardService.class);
- traceEnd();
-
traceBeginAndSlog("InitNetworkStackClient");
try {
NetworkStackClient.getInstance().init();
@@ -1887,6 +1881,11 @@
traceEnd();
}
+ // NOTE: ClipboardService depends on ContentCapture and Autofill
+ traceBeginAndSlog("StartClipboardService");
+ mSystemServiceManager.startService(ClipboardService.class);
+ traceEnd();
+
traceBeginAndSlog("AppServiceManager");
mSystemServiceManager.startService(AppBindingService.Lifecycle.class);
traceEnd();
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index 339607b..59aea21 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -36,6 +36,7 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.TrafficStatsConstants;
import libcore.io.IoBridge;
@@ -586,7 +587,8 @@
private boolean createSocket() {
final int SEND_TIMEOUT_MS = 300;
- final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NEIGHBOR);
+ final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+ TrafficStatsConstants.TAG_SYSTEM_NEIGHBOR);
try {
mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
// Setting SNDTIMEO is purely for defensive purposes.
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 164570a..cc64323 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -86,6 +86,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.net.Uri;
import android.os.ConditionVariable;
import android.os.DeadObjectException;
@@ -100,6 +101,7 @@
import com.android.internal.backup.IBackupTransport;
import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.KeyValueBackupJob;
@@ -116,7 +118,6 @@
import com.android.server.backup.testing.TransportTestUtils.TransportMock;
import com.android.server.testing.shadows.FrameworkShadowLooper;
import com.android.server.testing.shadows.ShadowApplicationPackageManager;
-import com.android.server.testing.shadows.ShadowBackupActivityThread;
import com.android.server.testing.shadows.ShadowBackupDataInput;
import com.android.server.testing.shadows.ShadowBackupDataOutput;
import com.android.server.testing.shadows.ShadowEventLog;
@@ -163,8 +164,7 @@
ShadowBackupDataInput.class,
ShadowBackupDataOutput.class,
ShadowEventLog.class,
- ShadowQueuedWork.class,
- ShadowBackupActivityThread.class,
+ ShadowQueuedWork.class
})
@Presubmit
public class KeyValueBackupTaskTest {
@@ -179,6 +179,7 @@
@Mock private IBackupObserver mObserver;
@Mock private IBackupManagerMonitor mMonitor;
@Mock private OnTaskFinishedListener mListener;
+ @Mock private PackageManagerInternal mPackageManagerInternal;
private UserBackupManagerService mBackupManagerService;
private TransportData mTransport;
private ShadowLooper mShadowBackupLooper;
@@ -243,6 +244,11 @@
mShadowBackupLooper = shadowOf(mBackupHandler.getLooper());
ShadowEventLog.setUp();
mReporter = spy(new KeyValueBackupReporter(mBackupManagerService, mObserver, mMonitor));
+
+ when(mPackageManagerInternal.getApplicationEnabledState(any(), anyInt()))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
}
@After
@@ -471,7 +477,7 @@
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgentWithData(PACKAGE_1);
BackupAgent pmAgent = spy(createPmAgent());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+ doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
runTask(task);
@@ -484,7 +490,7 @@
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgentWithData(PACKAGE_1);
BackupAgent pmAgent = spy(createPmAgent());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+ doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
KeyValueBackupTask task =
createKeyValueBackupTask(transportMock, true, PACKAGE_1, PM_PACKAGE);
@@ -498,7 +504,7 @@
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgentWithData(PACKAGE_1);
BackupAgent pmAgent = spy(createPmAgent());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+ doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, false, PACKAGE_1);
runTask(task);
@@ -1307,7 +1313,7 @@
argThat(packageInfo(PM_PACKAGE)), any(), anyInt()))
.then(copyBackupDataTo(backupDataPath));
BackupAgent pmAgent = spy(createPmAgent());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+ doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
agentOnBackupDo(
pmAgent,
(oldState, dataOutput, newState) -> {
@@ -1371,7 +1377,7 @@
setUpAgent(PACKAGE_1);
when(transportMock.transport.finishBackup()).thenReturn(BackupTransport.TRANSPORT_OK);
BackupAgent pmAgent = spy(createPmAgent());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+ doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
agentOnBackupDo(
pmAgent,
(oldState, dataOutput, newState) -> {
@@ -1395,7 +1401,7 @@
setUpAgent(PACKAGE_1);
when(transportMock.transport.finishBackup()).thenReturn(BackupTransport.TRANSPORT_OK);
BackupAgent pmAgent = spy(createPmAgent());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+ doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
agentOnBackupDo(
pmAgent,
(oldState, dataOutput, newState) -> {
@@ -1957,7 +1963,7 @@
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgent(PACKAGE_1);
BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+ doReturn(pmAgent).when(mBackupManagerService).makeMetadataAgent();
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
runTask(task);
@@ -1970,7 +1976,7 @@
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgent(PACKAGE_1);
BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+ doReturn(pmAgent).when(mBackupManagerService).makeMetadataAgent();
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
runTask(task);
@@ -1983,7 +1989,7 @@
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgent(PACKAGE_1);
BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+ doReturn(pmAgent).when(mBackupManagerService).makeMetadataAgent();
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
runTask(task);
@@ -1996,7 +2002,7 @@
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgent(PACKAGE_1);
BackupAgent pmAgent = spy(createPmAgent());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+ doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
agentOnBackupDo(
pmAgent, (oldState, dataOutput, newState) -> runInWorkerThread(task::markCancel));
@@ -2011,7 +2017,7 @@
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgent(PACKAGE_1);
BackupAgent pmAgent = spy(createPmAgent());
- when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+ doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
agentOnBackupDo(
pmAgent, (oldState, dataOutput, newState) -> runInWorkerThread(task::markCancel));
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupActivityThread.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupActivityThread.java
deleted file mode 100644
index ca2e3b6..0000000
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupActivityThread.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.testing.shadows;
-
-import android.app.ActivityThread;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowActivityThread;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-import javax.annotation.Nonnull;
-
-/**
- * Extends the existing {@link ShadowActivityThread} to add support for
- * {@link PackageManager#getApplicationEnabledSetting(String)} in the shadow {@link PackageManager}
- * returned by {@link ShadowBackupActivityThread#getPackageManager()}.
- */
-@Implements(value = ActivityThread.class, isInAndroidSdk = false, looseSignatures = true)
-public class ShadowBackupActivityThread extends ShadowActivityThread {
- @Implementation
- public static Object getPackageManager() {
- ClassLoader classLoader = ShadowActivityThread.class.getClassLoader();
- Class<?> iPackageManagerClass;
- try {
- iPackageManagerClass = classLoader.loadClass("android.content.pm.IPackageManager");
- } catch (ClassNotFoundException e) {
- throw new RuntimeException(e);
- }
-
- return Proxy.newProxyInstance(
- classLoader,
- new Class[] {iPackageManagerClass},
- new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, @Nonnull Method method, Object[] args)
- throws Exception {
- if (method.getName().equals("getApplicationInfo")) {
- String packageName = (String) args[0];
- int flags = (Integer) args[1];
-
- try {
- return RuntimeEnvironment.application
- .getPackageManager()
- .getApplicationInfo(packageName, flags);
- } catch (PackageManager.NameNotFoundException e) {
- throw new RemoteException(e.getMessage());
- }
- } else if (method.getName().equals("getApplicationEnabledSetting")) {
- return 0;
- } else {
- return null;
- }
- }
- });
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index 2cba9d0..2977414 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -17,6 +17,7 @@
package com.android.server.accessibility;
import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_HOVER_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER;
@@ -116,6 +117,7 @@
MotionEvent mClickDownEvent;
MotionEvent mClickUpEvent;
+ MotionEvent mHoverMoveEvent;
ArgumentCaptor<MotionEvent> mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class);
ArgumentCaptor<MotionEvent> mCaptor2 = ArgumentCaptor.forClass(MotionEvent.class);
@@ -152,6 +154,10 @@
CLICK_POINT.y, 0);
mClickUpEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ mHoverMoveEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, CLICK_POINT.x, CLICK_POINT.y,
+ 0);
+ mHoverMoveEvent.setSource(InputDevice.SOURCE_MOUSE);
+
mIsLineStart = allOf(IS_ACTION_DOWN, isAtPoint(LINE_START), hasStandardInitialization(),
hasTimeFromDown(0));
mIsLineMiddle = allOf(IS_ACTION_MOVE, isAtPoint(LINE_END), hasStandardInitialization(),
@@ -301,6 +307,23 @@
}
@Test
+ public void
+ testOnMotionEvents_fromMouseWithInjectedGestureInProgress_shouldNotCancelAndPassReal()
+ throws RemoteException {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+ mMotionEventInjector.onMotionEvent(mHoverMoveEvent, mHoverMoveEvent, 0);
+ mMessageCapturingHandler.sendAllMessages();
+
+ verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
+ assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
+ }
+
+ @Test
public void testOnMotionEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassReal()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
new file mode 100644
index 0000000..8426a0b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.attention;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IPowerManager;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.service.attention.IAttentionCallback;
+import android.service.attention.IAttentionService;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.attention.AttentionManagerService.AttentionCheck;
+import com.android.server.attention.AttentionManagerService.AttentionHandler;
+import com.android.server.attention.AttentionManagerService.UserState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link com.android.server.attention.AttentionManagerService}
+ */
+@SmallTest
+public class AttentionManagerServiceTest {
+ private AttentionManagerService mSpyAttentionManager;
+ private UserState mSpyUserState;
+ private final int mTimeout = 1000;
+ @Mock private AttentionCallbackInternal mMockAttentionCallbackInternal;
+ @Mock private AttentionHandler mMockHandler;
+ @Mock private IAttentionCallback mMockIAttentionCallback;
+ @Mock private IPowerManager mMockIPowerManager;
+ @Mock Context mContext;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ // setup context mock
+ doReturn(true).when(mContext).bindServiceAsUser(any(), any(), anyInt(), any());
+ // setup power manager mock
+ PowerManager mPowerManager;
+ doReturn(true).when(mMockIPowerManager).isInteractive();
+ mPowerManager = new PowerManager(mContext, mMockIPowerManager, null);
+
+ Object mLock = new Object();
+ // setup a spy on attention manager
+ AttentionManagerService mAttentionManager = new AttentionManagerService(
+ mContext,
+ mPowerManager,
+ mLock,
+ mMockHandler);
+ mSpyAttentionManager = Mockito.spy(mAttentionManager);
+ // setup a spy on user state
+ ComponentName componentName = new ComponentName("a", "b");
+ mSpyAttentionManager.mComponentName = componentName;
+ UserState mUserState = new UserState(0,
+ mContext,
+ mLock,
+ componentName);
+ mUserState.mService = new MockIAttentionService();
+ mSpyUserState = spy(mUserState);
+ }
+
+ @Test
+ public void testCancelAttentionCheck_noCrashWhenNoUserStateLocked() {
+ mSpyAttentionManager.cancelAttentionCheck(null);
+ }
+
+ @Test
+ public void testCancelAttentionCheck_noCrashWhenCallbackMismatched() {
+ mSpyUserState.mCurrentAttentionCheck =
+ new AttentionCheck(mMockAttentionCallbackInternal, mMockIAttentionCallback);
+ doReturn(mSpyUserState).when(mSpyAttentionManager).peekCurrentUserStateLocked();
+ mSpyAttentionManager.cancelAttentionCheck(null);
+ }
+
+ @Test
+ public void testCancelAttentionCheck_cancelCallbackWhenMatched() {
+ mSpyUserState.mCurrentAttentionCheck =
+ new AttentionCheck(mMockAttentionCallbackInternal, mMockIAttentionCallback);
+ doReturn(mSpyUserState).when(mSpyAttentionManager).peekCurrentUserStateLocked();
+ mSpyAttentionManager.cancelAttentionCheck(mMockAttentionCallbackInternal);
+ verify(mSpyAttentionManager).cancel(any());
+ }
+
+ @Test
+ public void testCheckAttention_returnFalseWhenPowerManagerNotInteract() throws RemoteException {
+ doReturn(false).when(mMockIPowerManager).isInteractive();
+ AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
+ assertThat(mSpyAttentionManager.checkAttention(mTimeout, callback)).isFalse();
+ }
+
+ @Test
+ public void testCheckAttention_callOnSuccess() throws RemoteException {
+ doReturn(true).when(mSpyAttentionManager).isServiceEnabled();
+ doReturn(true).when(mMockIPowerManager).isInteractive();
+ doReturn(mSpyUserState).when(mSpyAttentionManager).getOrCreateCurrentUserStateLocked();
+ doNothing().when(mSpyAttentionManager).freeIfInactiveLocked();
+
+ AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
+ mSpyAttentionManager.checkAttention(mTimeout, callback);
+ verify(callback).onSuccess(anyInt(), anyLong());
+ }
+
+ private class MockIAttentionService implements IAttentionService {
+ public void checkAttention(IAttentionCallback callback) throws RemoteException {
+ callback.onSuccess(0, 0);
+ }
+ public void cancelAttentionCheck(IAttentionCallback callback) {
+ }
+ public IBinder asBinder() {
+ return null;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
deleted file mode 100644
index 97a6e66..0000000
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
+++ /dev/null
@@ -1,1217 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.backup.testutils;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ChangedPackages;
-import android.content.pm.IDexModuleRegisterCallback;
-import android.content.pm.IOnPermissionsChangeListener;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageDeleteObserver2;
-import android.content.pm.IPackageInstaller;
-import android.content.pm.IPackageManager;
-import android.content.pm.IPackageMoveObserver;
-import android.content.pm.IPackageStatsObserver;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.KeySet;
-import android.content.pm.ModuleInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.content.pm.SuspendDialogInfo;
-import android.content.pm.VerifierDeviceIdentity;
-import android.content.pm.VersionedPackage;
-import android.content.pm.dex.IArtManager;
-import android.graphics.Bitmap;
-import android.os.IBinder;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-
-import java.util.List;
-
-/**
- * Stub for IPackageManager to use in tests.
- */
-public class IPackageManagerStub implements IPackageManager {
- public static PackageInfo sPackageInfo;
- public static int sApplicationEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-
- @Override
- public PackageInfo getPackageInfo(String packageName, int flags, int userId)
- throws RemoteException {
- return sPackageInfo;
- }
-
- @Override
- public int getApplicationEnabledSetting(String packageName, int userId) throws RemoteException {
- return sApplicationEnabledSetting;
- }
-
- @Override
- public void checkPackageStartable(String packageName, int userId) throws RemoteException {
-
- }
-
- @Override
- public boolean isPackageAvailable(String packageName, int userId) throws RemoteException {
- return false;
- }
-
- @Override
- public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage, int flags,
- int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public int getPackageUid(String packageName, int flags, int userId) throws RemoteException {
- return 0;
- }
-
- @Override
- public int[] getPackageGids(String packageName, int flags, int userId) throws RemoteException {
- return new int[0];
- }
-
- @Override
- public String[] currentToCanonicalPackageNames(String[] names) throws RemoteException {
- return new String[0];
- }
-
- @Override
- public String[] canonicalToCurrentPackageNames(String[] names) throws RemoteException {
- return new String[0];
- }
-
- @Override
- public PermissionInfo getPermissionInfo(String name, String packageName, int flags)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice queryPermissionsByGroup(String group, int flags)
- throws RemoteException {
- return null;
- }
-
- @Override
- public PermissionGroupInfo getPermissionGroupInfo(String name, int flags)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice getAllPermissionGroups(int flags) throws RemoteException {
- return null;
- }
-
- @Override
- public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ActivityInfo getActivityInfo(ComponentName className, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public boolean activitySupportsIntent(ComponentName className, Intent intent,
- String resolvedType)
- throws RemoteException {
- return false;
- }
-
- @Override
- public ActivityInfo getReceiverInfo(ComponentName className, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ServiceInfo getServiceInfo(ComponentName className, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ProviderInfo getProviderInfo(ComponentName className, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public int checkPermission(String permName, String pkgName, int userId) throws RemoteException {
- return 0;
- }
-
- @Override
- public int checkUidPermission(String permName, int uid) throws RemoteException {
- return 0;
- }
-
- @Override
- public boolean addPermission(PermissionInfo info) throws RemoteException {
- return false;
- }
-
- @Override
- public void removePermission(String name) throws RemoteException {
-
- }
-
- @Override
- public void grantRuntimePermission(String packageName, String permissionName, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public void revokeRuntimePermission(String packageName, String permissionName, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public void resetRuntimePermissions() throws RemoteException {
-
- }
-
- @Override
- public int getPermissionFlags(String permissionName, String packageName, int userId)
- throws RemoteException {
- return 0;
- }
-
- @Override
- public void updatePermissionFlags(String permissionName, String packageName, int flagMask,
- int flagValues, boolean checkAdjustPolicyFlagPermission, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public List<String> getWhitelistedRestrictedPermissions(String packageName, int flags,
- int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public boolean addWhitelistedRestrictedPermission(String packageName, String permission,
- int whitelistFlags, int userId) throws RemoteException {
- return false;
- }
-
- @Override
- public boolean removeWhitelistedRestrictedPermission(String packageName, String permission,
- int whitelistFlags, int userId) throws RemoteException {
- return false;
- }
-
- @Override
- public boolean shouldShowRequestPermissionRationale(String permissionName, String packageName,
- int userId) throws RemoteException {
- return false;
- }
-
- @Override
- public boolean isProtectedBroadcast(String actionName) throws RemoteException {
- return false;
- }
-
- @Override
- public int checkSignatures(String pkg1, String pkg2) throws RemoteException {
- return 0;
- }
-
- @Override
- public int checkUidSignatures(int uid1, int uid2) throws RemoteException {
- return 0;
- }
-
- @Override
- public List<String> getAllPackages() throws RemoteException {
- return null;
- }
-
- @Override
- public String[] getPackagesForUid(int uid) throws RemoteException {
- return new String[0];
- }
-
- @Override
- public String getNameForUid(int uid) throws RemoteException {
- return null;
- }
-
- @Override
- public String[] getNamesForUids(int[] uids) throws RemoteException {
- return new String[0];
- }
-
- @Override
- public int getUidForSharedUser(String sharedUserName) throws RemoteException {
- return 0;
- }
-
- @Override
- public int getFlagsForUid(int uid) throws RemoteException {
- return 0;
- }
-
- @Override
- public int getPrivateFlagsForUid(int uid) throws RemoteException {
- return 0;
- }
-
- @Override
- public boolean isUidPrivileged(int uid) throws RemoteException {
- return false;
- }
-
- @Override
- public String[] getAppOpPermissionPackages(String permissionName) throws RemoteException {
- return new String[0];
- }
-
- @Override
- public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ResolveInfo findPersistentPreferredActivity(Intent intent, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public boolean canForwardTo(Intent intent, String resolvedType, int sourceUserId,
- int targetUserId) throws RemoteException {
- return false;
- }
-
- @Override
- public ParceledListSlice queryIntentActivities(Intent intent, String resolvedType, int flags,
- int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice queryIntentActivityOptions(ComponentName caller, Intent[] specifics,
- String[] specificTypes, Intent intent, String resolvedType, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice queryIntentReceivers(Intent intent, String resolvedType, int flags,
- int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice queryIntentServices(Intent intent, String resolvedType, int flags,
- int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice queryIntentContentProviders(Intent intent, String resolvedType,
- int flags, int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice getInstalledPackages(int flags, int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice getPackagesHoldingPermissions(String[] permissions, int flags,
- int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice getInstalledApplications(int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice getPersistentApplications(int flags) throws RemoteException {
- return null;
- }
-
- @Override
- public ProviderInfo resolveContentProvider(String name, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo)
- throws RemoteException {
-
- }
-
- @Override
- public ParceledListSlice queryContentProviders(String processName, int uid, int flags,
- String metaDataKey) throws RemoteException {
- return null;
- }
-
- @Override
- public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice queryInstrumentation(String targetPackage, int flags)
- throws RemoteException {
- return null;
- }
-
- @Override
- public void finishPackageInstall(int token, boolean didLaunch) throws RemoteException {
-
- }
-
- @Override
- public void setInstallerPackageName(String targetPackage, String installerPackageName)
- throws RemoteException {
-
- }
-
- @Override
- public void setApplicationCategoryHint(String packageName, int categoryHint,
- String callerPackageName) throws RemoteException {
-
- }
-
- @Override
- public void deletePackageAsUser(String packageName, int versionCode,
- IPackageDeleteObserver observer, int userId, int flags) throws RemoteException {
-
- }
-
- @Override
- public void deletePackageVersioned(VersionedPackage versionedPackage,
- IPackageDeleteObserver2 observer, int userId, int flags) throws RemoteException {
-
- }
-
- @Override
- public String getInstallerPackageName(String packageName) throws RemoteException {
- return null;
- }
-
- @Override
- public void resetApplicationPreferences(int userId) throws RemoteException {
-
- }
-
- @Override
- public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags)
- throws RemoteException {
- return null;
- }
-
- @Override
- public void setLastChosenActivity(Intent intent, String resolvedType, int flags,
- IntentFilter filter, int match, ComponentName activity) throws RemoteException {
-
- }
-
- @Override
- public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set,
- ComponentName activity, int userId) throws RemoteException {
-
- }
-
- @Override
- public void replacePreferredActivity(IntentFilter filter, int match, ComponentName[] set,
- ComponentName activity, int userId) throws RemoteException {
-
- }
-
- @Override
- public void clearPackagePreferredActivities(String packageName) throws RemoteException {
-
- }
-
- @Override
- public int getPreferredActivities(List<IntentFilter> outFilters,
- List<ComponentName> outActivities, String packageName) throws RemoteException {
- return 0;
- }
-
- @Override
- public void addPersistentPreferredActivity(IntentFilter filter, ComponentName activity,
- int userId) throws RemoteException {
-
- }
-
- @Override
- public void clearPackagePersistentPreferredActivities(String packageName, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage,
- int sourceUserId, int targetUserId, int flags) throws RemoteException {
-
- }
-
- @Override
- public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage)
- throws RemoteException {
-
- }
-
- @Override
- public String[] setDistractingPackageRestrictionsAsUser(String[] packageNames,
- int restrictionFlags, int userId) throws RemoteException {
- return new String[0];
- }
-
- @Override
- public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
- PersistableBundle appExtras, PersistableBundle launcherExtras, SuspendDialogInfo dialogInfo,
- String callingPackage, int userId) throws RemoteException {
- return new String[0];
- }
-
- @Override
- public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId)
- throws RemoteException {
- return new String[0];
- }
-
- @Override
- public boolean isPackageSuspendedForUser(String packageName, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public byte[] getPreferredActivityBackup(int userId) throws RemoteException {
- return new byte[0];
- }
-
- @Override
- public void restorePreferredActivities(byte[] backup, int userId) throws RemoteException {
-
- }
-
- @Override
- public byte[] getDefaultAppsBackup(int userId) throws RemoteException {
- return new byte[0];
- }
-
- @Override
- public void restoreDefaultApps(byte[] backup, int userId) throws RemoteException {
-
- }
-
- @Override
- public byte[] getIntentFilterVerificationBackup(int userId) throws RemoteException {
- return new byte[0];
- }
-
- @Override
- public void restoreIntentFilterVerification(byte[] backup, int userId) throws RemoteException {
-
- }
-
- @Override
- public ComponentName getHomeActivities(List<ResolveInfo> outHomeCandidates)
- throws RemoteException {
- return null;
- }
-
- @Override
- public void setHomeActivity(ComponentName className, int userId) throws RemoteException {
-
- }
-
- @Override
- public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags,
- int userId) throws RemoteException {
-
- }
-
- @Override
- public int getComponentEnabledSetting(ComponentName componentName, int userId)
- throws RemoteException {
- return 0;
- }
-
- @Override
- public void setApplicationEnabledSetting(String packageName, int newState, int flags,
- int userId,
- String callingPackage) throws RemoteException {
-
- }
-
- @Override
- public void logAppProcessStartIfNeeded(String processName, int uid, String seinfo,
- String apkFile,
- int pid) throws RemoteException {
-
- }
-
- @Override
- public void flushPackageRestrictionsAsUser(int userId) throws RemoteException {
-
- }
-
- @Override
- public void setPackageStoppedState(String packageName, boolean stopped, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public void freeStorageAndNotify(String volumeUuid, long freeStorageSize, int storageFlags,
- IPackageDataObserver observer) throws RemoteException {
-
- }
-
- @Override
- public void freeStorage(String volumeUuid, long freeStorageSize, int storageFlags,
- IntentSender pi) throws RemoteException {
-
- }
-
- @Override
- public void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer)
- throws RemoteException {
-
- }
-
- @Override
- public void deleteApplicationCacheFilesAsUser(String packageName, int userId,
- IPackageDataObserver observer) throws RemoteException {
-
- }
-
- @Override
- public void clearApplicationUserData(String packageName, IPackageDataObserver observer,
- int userId) throws RemoteException {
-
- }
-
- @Override
- public void clearApplicationProfileData(String packageName) throws RemoteException {
-
- }
-
- @Override
- public void getPackageSizeInfo(String packageName, int userHandle,
- IPackageStatsObserver observer)
- throws RemoteException {
-
- }
-
- @Override
- public String[] getSystemSharedLibraryNames() throws RemoteException {
- return new String[0];
- }
-
- @Override
- public ParceledListSlice getSystemAvailableFeatures() throws RemoteException {
- return null;
- }
-
- @Override
- public boolean hasSystemFeature(String name, int version) throws RemoteException {
- return false;
- }
-
- @Override
- public void enterSafeMode() throws RemoteException {
-
- }
-
- @Override
- public boolean isSafeMode() throws RemoteException {
- return false;
- }
-
- @Override
- public void systemReady() throws RemoteException {
-
- }
-
- @Override
- public boolean hasSystemUidErrors() throws RemoteException {
- return false;
- }
-
- @Override
- public void performFstrimIfNeeded() throws RemoteException {
-
- }
-
- @Override
- public void updatePackagesIfNeeded() throws RemoteException {
-
- }
-
- @Override
- public void notifyPackageUse(String packageName, int reason) throws RemoteException {
-
- }
-
- @Override
- public void notifyDexLoad(String loadingPackageName, List<String> classLoadersNames,
- List<String> classPaths, String loaderIsa) throws RemoteException {
-
- }
-
- @Override
- public void registerDexModule(String packageName, String dexModulePath, boolean isSharedModule,
- IDexModuleRegisterCallback callback) throws RemoteException {
-
- }
-
- @Override
- public boolean performDexOptMode(String packageName, boolean checkProfiles,
- String targetCompilerFilter, boolean force, boolean bootComplete, String splitName)
- throws RemoteException {
- return false;
- }
-
- @Override
- public boolean performDexOptSecondary(String packageName, String targetCompilerFilter,
- boolean force) throws RemoteException {
- return false;
- }
-
- @Override
- public boolean compileLayouts(String packageName) throws RemoteException {
- return false;
- }
-
- @Override
- public void dumpProfiles(String packageName) throws RemoteException {
-
- }
-
- @Override
- public void forceDexOpt(String packageName) throws RemoteException {
-
- }
-
- @Override
- public boolean runBackgroundDexoptJob(List<String> packageNames) throws RemoteException {
- return false;
- }
-
- @Override
- public void reconcileSecondaryDexFiles(String packageName) throws RemoteException {
-
- }
-
- @Override
- public int getMoveStatus(int moveId) throws RemoteException {
- return 0;
- }
-
- @Override
- public void registerMoveCallback(IPackageMoveObserver callback) throws RemoteException {
-
- }
-
- @Override
- public void unregisterMoveCallback(IPackageMoveObserver callback) throws RemoteException {
-
- }
-
- @Override
- public int movePackage(String packageName, String volumeUuid) throws RemoteException {
- return 0;
- }
-
- @Override
- public int movePrimaryStorage(String volumeUuid) throws RemoteException {
- return 0;
- }
-
- @Override
- public boolean addPermissionAsync(PermissionInfo info) throws RemoteException {
- return false;
- }
-
- @Override
- public boolean setInstallLocation(int loc) throws RemoteException {
- return false;
- }
-
- @Override
- public int getInstallLocation() throws RemoteException {
- return 0;
- }
-
- @Override
- public int installExistingPackageAsUser(String packageName, int userId, int installFlags,
- int installReason) throws RemoteException {
- return 0;
- }
-
- @Override
- public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
-
- }
-
- @Override
- public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
- long millisecondsToDelay) throws RemoteException {
-
- }
-
- @Override
- public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)
- throws RemoteException {
-
- }
-
- @Override
- public int getIntentVerificationStatus(String packageName, int userId) throws RemoteException {
- return 0;
- }
-
- @Override
- public boolean updateIntentVerificationStatus(String packageName, int status, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public ParceledListSlice getIntentFilterVerifications(String packageName)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice getAllIntentFilters(String packageName) throws RemoteException {
- return null;
- }
-
- @Override
- public boolean setDefaultBrowserPackageName(String packageName, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public String getDefaultBrowserPackageName(int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
- return null;
- }
-
- @Override
- public boolean isFirstBoot() throws RemoteException {
- return false;
- }
-
- @Override
- public boolean isOnlyCoreApps() throws RemoteException {
- return false;
- }
-
- @Override
- public boolean isDeviceUpgrading() throws RemoteException {
- return false;
- }
-
- @Override
- public void setPermissionEnforced(String permission, boolean enforced) throws RemoteException {
-
- }
-
- @Override
- public boolean isPermissionEnforced(String permission) throws RemoteException {
- return false;
- }
-
- @Override
- public boolean isStorageLow() throws RemoteException {
- return false;
- }
-
- @Override
- public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public boolean getApplicationHiddenSettingAsUser(String packageName, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden)
- throws RemoteException {
-
- }
-
- @Override
- public boolean setSystemAppInstallState(String packageName, boolean installed, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public IPackageInstaller getPackageInstaller() throws RemoteException {
- return null;
- }
-
- @Override
- public boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public boolean getBlockUninstallForUser(String packageName, int userId) throws RemoteException {
- return false;
- }
-
- @Override
- public KeySet getKeySetByAlias(String packageName, String alias) throws RemoteException {
- return null;
- }
-
- @Override
- public KeySet getSigningKeySet(String packageName) throws RemoteException {
- return null;
- }
-
- @Override
- public boolean isPackageSignedByKeySet(String packageName, KeySet ks) throws RemoteException {
- return false;
- }
-
- @Override
- public boolean isPackageSignedByKeySetExactly(String packageName, KeySet ks)
- throws RemoteException {
- return false;
- }
-
- @Override
- public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener)
- throws RemoteException {
-
- }
-
- @Override
- public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener)
- throws RemoteException {
-
- }
-
- @Override
- public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public void grantDefaultPermissionsToEnabledTelephonyDataServices(String[] packageNames,
- int userId) throws RemoteException {
-
- }
-
- @Override
- public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(String[] packageNames,
- int userId) throws RemoteException {
-
- }
-
- @Override
- public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public String getPermissionControllerPackageName() throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice getInstantApps(int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public byte[] getInstantAppCookie(String packageName, int userId) throws RemoteException {
- return new byte[0];
- }
-
- @Override
- public boolean setInstantAppCookie(String packageName, byte[] cookie, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public Bitmap getInstantAppIcon(String packageName, int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public boolean isInstantApp(String packageName, int userId) throws RemoteException {
- return false;
- }
-
- @Override
- public boolean setRequiredForSystemUser(String packageName, boolean systemUserApp)
- throws RemoteException {
- return false;
- }
-
- @Override
- public void setUpdateAvailable(String packageName, boolean updateAvaialble)
- throws RemoteException {
-
- }
-
- @Override
- public String getServicesSystemSharedLibraryPackageName() throws RemoteException {
- return null;
- }
-
- @Override
- public String getSharedSystemSharedLibraryPackageName() throws RemoteException {
- return null;
- }
-
- @Override
- public ChangedPackages getChangedPackages(int sequenceNumber, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public boolean isPackageDeviceAdminOnAnyUser(String packageName) throws RemoteException {
- return false;
- }
-
- @Override
- public int getInstallReason(String packageName, int userId) throws RemoteException {
- return 0;
- }
-
- @Override
- public ParceledListSlice getSharedLibraries(String packageName, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public ParceledListSlice getDeclaredSharedLibraries(String packageName, int flags, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public boolean canRequestPackageInstalls(String packageName, int userId)
- throws RemoteException {
- return false;
- }
-
- @Override
- public void deletePreloadsFileCache() throws RemoteException {
-
- }
-
- @Override
- public ComponentName getInstantAppResolverComponent() throws RemoteException {
- return null;
- }
-
- @Override
- public ComponentName getInstantAppResolverSettingsComponent() throws RemoteException {
- return null;
- }
-
- @Override
- public ComponentName getInstantAppInstallerComponent() throws RemoteException {
- return null;
- }
-
- @Override
- public String getInstantAppAndroidId(String packageName, int userId) throws RemoteException {
- return null;
- }
-
- @Override
- public IArtManager getArtManager() throws RemoteException {
- return null;
- }
-
- @Override
- public void setHarmfulAppWarning(String packageName, CharSequence warning, int userId)
- throws RemoteException {
-
- }
-
- @Override
- public CharSequence getHarmfulAppWarning(String packageName, int userId)
- throws RemoteException {
- return null;
- }
-
- @Override
- public boolean hasSigningCertificate(String packageName, byte[] signingCertificate, int flags)
- throws RemoteException {
- return false;
- }
-
- @Override
- public boolean hasUidSigningCertificate(int uid, byte[] signingCertificate, int flags)
- throws RemoteException {
- return false;
- }
-
- @Override
- public String getSystemTextClassifierPackageName() throws RemoteException {
- return null;
- }
-
- @Override
- public String getWellbeingPackageName() throws RemoteException {
- return null;
- }
-
- @Override
- public String getSystemCaptionsServicePackageName() throws RemoteException {
- return null;
- }
-
- @Override
- public String getAttentionServicePackageName() throws RemoteException {
- return null;
- }
-
- public String getIncidentReportApproverPackageName() throws RemoteException {
- return null;
- }
-
- @Override
- public String getAppPredictionServicePackageName() {
- return null;
- }
-
- @Override
- public boolean isPackageStateProtected(String packageName, int userId) throws RemoteException {
- return false;
- }
-
- @Override
- public void sendDeviceCustomizationReadyBroadcast() throws RemoteException {
-
- }
-
- @Override
- public List<ModuleInfo> getInstalledModules(int flags) throws RemoteException {
- return null;
- }
-
- @Override
- public ModuleInfo getModuleInfo(String packageName, int flags) throws RemoteException {
- return null;
- }
-
- @Override
- public int getRuntimePermissionsVersion(int userId) throws RemoteException {
- return 0;
- }
-
- @Override
- public void setRuntimePermissionsVersion(int version, int userId) throws RemoteException {
-
- }
-
- @Override
- public IBinder asBinder() {
- return null;
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
index a92b576..a901175 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
@@ -20,6 +20,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -36,7 +37,6 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.server.backup.UserBackupManagerService;
-import com.android.server.backup.testutils.IPackageManagerStub;
import org.junit.Before;
import org.junit.Test;
@@ -54,14 +54,12 @@
private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
- private IPackageManagerStub mPackageManagerStub;
private PackageManagerInternal mMockPackageManagerInternal;
private int mUserId;
@Before
public void setUp() throws Exception {
- mPackageManagerStub = new IPackageManagerStub();
mMockPackageManagerInternal = mock(PackageManagerInternal.class);
mUserId = UserHandle.USER_SYSTEM;
@@ -76,7 +74,7 @@
applicationInfo.packageName = TEST_PACKAGE_NAME;
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isFalse();
}
@@ -91,7 +89,7 @@
applicationInfo.packageName = TEST_PACKAGE_NAME;
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isFalse();
}
@@ -105,7 +103,7 @@
applicationInfo.packageName = UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isFalse();
}
@@ -118,12 +116,11 @@
applicationInfo.uid = Process.SYSTEM_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
-
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isTrue();
}
@@ -136,12 +133,11 @@
applicationInfo.uid = Process.FIRST_APPLICATION_UID;
applicationInfo.backupAgentName = null;
applicationInfo.packageName = TEST_PACKAGE_NAME;
-
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isTrue();
}
@@ -154,12 +150,11 @@
applicationInfo.uid = Process.FIRST_APPLICATION_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
-
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isTrue();
}
@@ -172,12 +167,11 @@
applicationInfo.uid = Process.SYSTEM_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
-
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isFalse();
}
@@ -190,12 +184,11 @@
applicationInfo.uid = Process.FIRST_APPLICATION_UID;
applicationInfo.backupAgentName = null;
applicationInfo.packageName = TEST_PACKAGE_NAME;
-
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isFalse();
}
@@ -208,12 +201,11 @@
applicationInfo.uid = Process.FIRST_APPLICATION_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
-
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
- mPackageManagerStub, mUserId);
+ mMockPackageManagerInternal, mUserId);
assertThat(isEligible).isFalse();
}
@@ -226,12 +218,11 @@
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
applicationInfo.enabled = true;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-
- boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
- mUserId);
+ boolean isDisabled =
+ AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
assertThat(isDisabled).isFalse();
}
@@ -244,12 +235,12 @@
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
applicationInfo.enabled = false;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
- boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
- mUserId);
+ boolean isDisabled =
+ AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
assertThat(isDisabled).isTrue();
}
@@ -261,12 +252,12 @@
applicationInfo.uid = Process.FIRST_APPLICATION_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
- boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
- mUserId);
+ boolean isDisabled =
+ AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
assertThat(isDisabled).isFalse();
}
@@ -278,12 +269,12 @@
applicationInfo.uid = Process.FIRST_APPLICATION_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
- boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
- mUserId);
+ boolean isDisabled =
+ AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
assertThat(isDisabled).isTrue();
}
@@ -295,12 +286,11 @@
applicationInfo.uid = Process.FIRST_APPLICATION_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
-
- boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
- mUserId);
+ boolean isDisabled =
+ AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
assertThat(isDisabled).isTrue();
}
@@ -312,12 +302,11 @@
applicationInfo.uid = Process.FIRST_APPLICATION_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
applicationInfo.packageName = TEST_PACKAGE_NAME;
+ when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
- IPackageManagerStub.sApplicationEnabledSetting =
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
-
- boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
- mUserId);
+ boolean isDisabled =
+ AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
assertThat(isDisabled).isTrue();
}
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index 5de41ea..4de00f7 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -29,6 +29,7 @@
import android.attention.AttentionManagerInternal;
import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.pm.PackageManager;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.SystemClock;
@@ -49,6 +50,8 @@
public class AttentionDetectorTest extends AndroidTestCase {
@Mock
+ private PackageManager mPackageManager;
+ @Mock
private AttentionManagerInternal mAttentionManagerInternal;
@Mock
private Runnable mOnUserAttention;
@@ -60,6 +63,9 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ when(mPackageManager.getAttentionServicePackageName()).thenReturn("com.google.android.as");
+ when(mPackageManager.checkPermission(any(), any())).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
when(mAttentionManagerInternal.checkAttention(anyLong(), any()))
.thenReturn(true);
mAttentionDetector = new TestableAttentionDetector();
@@ -108,6 +114,27 @@
}
@Test
+ public void testOnUserActivity_doesntCheckIfNotSufficientPermissions() {
+ when(mPackageManager.checkPermission(any(), any())).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+
+ long when = registerAttention();
+ verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
+ assertThat(mNextDimming).isEqualTo(when);
+ }
+
+ @Test
+ public void testOnUserActivity_disablesSettingIfNotSufficientPermissions() {
+ when(mPackageManager.checkPermission(any(), any())).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+
+ registerAttention();
+ boolean enabled = Settings.System.getIntForUser(getContext().getContentResolver(),
+ Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT) == 1;
+ assertFalse(enabled);
+ }
+
+ @Test
public void testOnUserActivity_doesntCrashIfNoAttentionService() {
mAttentionManagerInternal = null;
registerAttention();
@@ -211,6 +238,8 @@
TestableAttentionDetector() {
super(AttentionDetectorTest.this.mOnUserAttention, new Object());
mAttentionManager = mAttentionManagerInternal;
+ mPackageManager = AttentionDetectorTest.this.mPackageManager;
+ mContentResolver = getContext().getContentResolver();
mMaximumExtensionMillis = 10000L;
}
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 355ff63..2d101dd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -349,6 +349,7 @@
when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
+ mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
// write to a test file; the system file isn't readable from tests
mFile = new File(mContext.getCacheDir(), "test.xml");
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index 91d3e5e..7e3d4b4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -206,6 +206,7 @@
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.addService(WindowManagerInternal.class, mock(WindowManagerInternal.class));
+ mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
mUsers = new ArrayList<>();
mUsers.add(new UserInfo(0, "system", 0));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 08d8333..8936450 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -110,6 +110,7 @@
private ZenModeHelper mZenModeHelperSpy;
private Context mContext;
private ContentResolver mContentResolver;
+ @Mock AppOpsManager mAppOps;
@Before
public void setUp() {
@@ -127,6 +128,7 @@
e.toString());
}
+ when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOps);
when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
mConditionProviders = new ConditionProviders(mContext, new UserProfiles(),
AppGlobals.getPackageManager());
@@ -219,10 +221,10 @@
Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0);
mZenModeHelperSpy.applyRestrictions();
- doNothing().when(mZenModeHelperSpy).applyRestrictions(anyBoolean(), anyInt());
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ doNothing().when(mZenModeHelperSpy).applyRestrictions(eq(false), anyBoolean(), anyInt());
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
AudioAttributes.USAGE_ALARM);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
AudioAttributes.USAGE_MEDIA);
}
@@ -233,9 +235,9 @@
Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0);
mZenModeHelperSpy.applyRestrictions();
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, false,
AudioAttributes.USAGE_ALARM);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, false,
AudioAttributes.USAGE_MEDIA);
}
@@ -244,13 +246,13 @@
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
mZenModeHelperSpy.applyRestrictions();
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true,
AudioAttributes.USAGE_ALARM);
// Media is a catch-all that includes games
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true,
AudioAttributes.USAGE_MEDIA);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true,
AudioAttributes.USAGE_GAME);
}
@@ -262,17 +264,17 @@
mZenModeHelperSpy.applyRestrictions();
// Total silence will silence alarms, media and system noises (but not vibrations)
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
AudioAttributes.USAGE_ALARM);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
AudioAttributes.USAGE_MEDIA);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
AudioAttributes.USAGE_GAME);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_VIBRATE);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
AudioAttributes.USAGE_UNKNOWN);
}
@@ -283,19 +285,19 @@
mZenModeHelperSpy.applyRestrictions();
// Alarms only mode will not silence alarms
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
AudioAttributes.USAGE_ALARM);
// Alarms only mode will not silence media
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
AudioAttributes.USAGE_MEDIA);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
AudioAttributes.USAGE_GAME);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
AudioAttributes.USAGE_UNKNOWN);
// Alarms only will silence system noises (but not vibrations)
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
}
@@ -306,9 +308,9 @@
mZenModeHelperSpy.applyRestrictions();
// Alarms only mode will silence calls despite priority-mode config
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST);
}
@@ -319,7 +321,7 @@
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
mZenModeHelperSpy.applyRestrictions();
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
AudioAttributes.USAGE_ALARM);
}
@@ -334,19 +336,64 @@
for (int usage : AudioAttributes.SDK_USAGES) {
if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
// only mute audio, not vibrations
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, usage,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true, usage,
AppOpsManager.OP_PLAY_AUDIO);
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, usage,
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, false, usage,
AppOpsManager.OP_VIBRATE);
} else {
boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
!= AudioAttributes.SUPPRESSIBLE_NEVER;
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, shouldMute, usage);
}
}
}
@Test
+ public void testApplyRestrictions_whitelist_priorityOnlyMode() {
+ mZenModeHelperSpy.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+ mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
+ mZenModeHelperSpy.applyRestrictions();
+
+ for (int usage : AudioAttributes.SDK_USAGES) {
+ verify(mAppOps).setRestriction(
+ eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(new String[]{PKG_O}));
+ verify(mAppOps).setRestriction(
+ eq(AppOpsManager.OP_VIBRATE), eq(usage), anyInt(), eq(new String[]{PKG_O}));
+ }
+ }
+
+ @Test
+ public void testApplyRestrictions_whitelist_alarmsOnlyMode() {
+ mZenModeHelperSpy.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+ mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_ALARMS;
+ mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
+ mZenModeHelperSpy.applyRestrictions();
+
+ for (int usage : AudioAttributes.SDK_USAGES) {
+ verify(mAppOps).setRestriction(
+ eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(null));
+ verify(mAppOps).setRestriction(
+ eq(AppOpsManager.OP_VIBRATE), eq(usage), anyInt(), eq(null));
+ }
+ }
+
+ @Test
+ public void testApplyRestrictions_whitelist_totalSilenceMode() {
+ mZenModeHelperSpy.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+ mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_NO_INTERRUPTIONS;
+ mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
+ mZenModeHelperSpy.applyRestrictions();
+
+ for (int usage : AudioAttributes.SDK_USAGES) {
+ verify(mAppOps).setRestriction(
+ eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(null));
+ verify(mAppOps).setRestriction(
+ eq(AppOpsManager.OP_VIBRATE), eq(usage), anyInt(), eq(null));
+ }
+ }
+
+ @Test
public void testZenUpgradeNotification() {
// shows zen upgrade notification if stored settings says to shows,
// zen has not been updated, boot is completed
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
index 96db38b..a7bbe6e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -87,7 +87,7 @@
mController.doPendingActivityLaunches(resume);
verify(mStarter, times(1)).startResolvedActivity(eq(activity), eq(source), eq(null),
- eq(null), eq(startFlags), eq(resume), eq(null), eq(null), eq(null));
+ eq(null), eq(startFlags), eq(resume), eq(null), eq(null));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index af04858..3392bc4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -712,7 +712,6 @@
mRecentTasks.add(mTasks.get(4));
// Freeze the list
- long freezeTime = SystemClock.elapsedRealtime();
mRecentTasks.setFreezeTaskListReordering();
assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
@@ -720,13 +719,11 @@
mRecentTasks.add(mTasks.get(2));
mRecentTasks.add(mTasks.get(1));
- // Override the freeze timeout params to simulate the timeout (simulate the freeze at 100ms
- // ago with a timeout of 1ms)
- mRecentTasks.setFreezeTaskListTimeoutParams(freezeTime - 100, 1);
-
ActivityStack stack = mTasks.get(2).getStack();
stack.moveToFront("", mTasks.get(2));
doReturn(stack).when(mTestService.mRootActivityContainer).getTopDisplayFocusedStack();
+
+ // Simulate the reset from the timeout
mRecentTasks.resetFreezeTaskListReorderingOnTimeout();
assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 263f650..f51ce13 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -44,14 +45,18 @@
private static final int FAKE_CALLING_UID = 667;
@Test
- public void testIsAnyNonToastWindowVisibleForUid_oneToastOneNonToastBothVisible() {
+ public void testIsAnyNonToastWindowVisibleForUid_oneToastOneAppStartOneNonToastBothVisible() {
final WindowState toastyToast = createWindow(null, TYPE_TOAST, "toast", FAKE_CALLING_UID);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);
+ final WindowState appStart = createWindow(null, TYPE_APPLICATION_STARTING, "appStarting",
+ FAKE_CALLING_UID);
toastyToast.mHasSurface = true;
app.mHasSurface = true;
+ appStart.mHasSurface = true;
assertTrue(toastyToast.isVisibleNow());
assertTrue(app.isVisibleNow());
+ assertTrue(appStart.isVisibleNow());
assertTrue(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
}
@@ -65,6 +70,16 @@
}
@Test
+ public void testIsAnyNonToastWindowVisibleForUid_onlyAppStartingVisible() {
+ final WindowState appStart = createWindow(null, TYPE_APPLICATION_STARTING, "appStarting",
+ FAKE_CALLING_UID);
+ appStart.mHasSurface = true;
+
+ assertTrue(appStart.isVisibleNow());
+ assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
+ }
+
+ @Test
public void testIsAnyNonToastWindowVisibleForUid_aFewNonToastButNoneVisible() {
final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar", FAKE_CALLING_UID);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
new file mode 100644
index 0000000..cb7bff3
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link WindowProcessControllerMap} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:WindowProcessControllerMapTests
+ */
+@SmallTest
+@Presubmit
+public class WindowProcessControllerMapTests extends ActivityTestsBase {
+
+ private static final int FAKE_UID1 = 666;
+ private static final int FAKE_UID2 = 667;
+ private static final int FAKE_PID1 = 668;
+ private static final int FAKE_PID2 = 669;
+ private static final int FAKE_PID3 = 670;
+ private static final int FAKE_PID4 = 671;
+
+ private WindowProcessControllerMap mProcessMap;
+ private WindowProcessController pid1uid1;
+ private WindowProcessController pid1uid2;
+ private WindowProcessController pid2uid1;
+ private WindowProcessController pid3uid1;
+ private WindowProcessController pid4uid2;
+
+ @Before
+ public void setUp() throws Exception {
+ mProcessMap = new WindowProcessControllerMap();
+ pid1uid1 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid1fakeuid1", FAKE_UID1,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid1uid1.setPid(FAKE_PID1);
+ pid1uid2 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid1fakeuid2", FAKE_UID2,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid1uid2.setPid(FAKE_PID1);
+ pid2uid1 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid2fakeuid1", FAKE_UID1,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid2uid1.setPid(FAKE_PID2);
+ pid3uid1 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid3fakeuid1", FAKE_UID1,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid3uid1.setPid(FAKE_PID3);
+ pid4uid2 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid4fakeuid2", FAKE_UID2,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid4uid2.setPid(FAKE_PID4);
+ }
+
+ @Test
+ public void testAdditionsAndRemovals() {
+ // test various additions and removals
+ mProcessMap.put(FAKE_PID1, pid1uid1);
+ mProcessMap.put(FAKE_PID2, pid2uid1);
+ assertEquals(pid1uid1, mProcessMap.getProcess(FAKE_PID1));
+ assertEquals(pid2uid1, mProcessMap.getProcess(FAKE_PID2));
+ ArraySet<WindowProcessController> uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+ assertTrue(uid1processes.contains(pid1uid1));
+ assertTrue(uid1processes.contains(pid2uid1));
+ assertEquals(uid1processes.size(), 2);
+
+ mProcessMap.remove(FAKE_PID2);
+ mProcessMap.put(FAKE_PID3, pid3uid1);
+ uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+ assertTrue(uid1processes.contains(pid1uid1));
+ assertFalse(uid1processes.contains(pid2uid1));
+ assertTrue(uid1processes.contains(pid3uid1));
+ assertEquals(uid1processes.size(), 2);
+
+ mProcessMap.put(FAKE_PID4, pid4uid2);
+ ArraySet<WindowProcessController> uid2processes = mProcessMap.getProcesses(FAKE_UID2);
+ assertTrue(uid2processes.contains(pid4uid2));
+ assertEquals(uid2processes.size(), 1);
+
+ mProcessMap.remove(FAKE_PID1);
+ mProcessMap.remove(FAKE_PID3);
+ assertNull(mProcessMap.getProcesses(FAKE_UID1));
+ assertEquals(mProcessMap.getProcess(FAKE_PID4), pid4uid2);
+ }
+
+ @Test
+ public void testReplacement() {
+ // test that replacing a process is handled correctly
+ mProcessMap.put(FAKE_PID1, pid1uid1);
+ ArraySet<WindowProcessController> uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+ assertTrue(uid1processes.contains(pid1uid1));
+ assertEquals(uid1processes.size(), 1);
+
+ mProcessMap.put(FAKE_PID1, pid1uid2);
+ assertNull(mProcessMap.getProcesses(FAKE_UID1));
+ ArraySet<WindowProcessController> uid2processes = mProcessMap.getProcesses(FAKE_UID2);
+ assertTrue(uid2processes.contains(pid1uid2));
+ assertEquals(uid2processes.size(), 1);
+ assertEquals(mProcessMap.getProcess(FAKE_PID1), pid1uid2);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 4f8fe5b..715353e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -397,7 +397,9 @@
app.mLayoutSeq = 1;
mDisplayContent.mLayoutSeq = 1;
- app.onDisplayChanged(mDisplayContent);
+ DisplayContent newDisplay = createNewDisplay();
+
+ app.onDisplayChanged(newDisplay);
assertThat(app.mLayoutSeq, not(is(mDisplayContent.mLayoutSeq)));
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 79e6851..5b7d816 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -1095,6 +1095,14 @@
Slog.d(TAG, "Clear notification");
mUsbNotificationId = 0;
}
+ // Not relevant for automotive.
+ if (mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE)
+ && id == SystemMessage.NOTE_USB_CHARGING) {
+ mUsbNotificationId = 0;
+ return;
+ }
+
if (id != 0) {
CharSequence title = r.getText(titleRes);
PendingIntent pi;
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 71a28b5..eb568e0 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Build;
@@ -174,4 +175,21 @@
in.readString(),
UserHandle.CREATOR.createFromParcel(in));
}
+
+ /**
+ * Determines if two {@link PhoneAccountHandle}s are from the same package.
+ *
+ * @param a Phone account handle to check for same {@link ConnectionService} package.
+ * @param b Other phone account handle to check for same {@link ConnectionService} package.
+ * @return {@code true} if the two {@link PhoneAccountHandle}s passed in belong to the same
+ * {@link ConnectionService} / package, {@code false} otherwise. Note: {@code null} phone
+ * account handles are considered equivalent to other {@code null} phone account handles.
+ * @hide
+ */
+ public static boolean areFromSamePackage(@Nullable PhoneAccountHandle a,
+ @Nullable PhoneAccountHandle b) {
+ String aPackageName = a != null ? a.getComponentName().getPackageName() : null;
+ String bPackageName = b != null ? b.getComponentName().getPackageName() : null;
+ return Objects.equals(aPackageName, bPackageName);
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index cf15b92..c57f9e6 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -39,6 +39,7 @@
import android.util.Log;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -123,6 +124,16 @@
private String mMnc;
/**
+ * EHPLMNs associated with the subscription
+ */
+ private String[] mEhplmns;
+
+ /**
+ * HPLMNs associated with the subscription
+ */
+ private String[] mHplmns;
+
+ /**
* ISO Country code for the subscription's provider
*/
private String mCountryIso;
@@ -316,6 +327,14 @@
}
/**
+ * @hide
+ */
+ public void setAssociatedPlmns(String[] ehplmns, String[] hplmns) {
+ mEhplmns = ehplmns;
+ mHplmns = hplmns;
+ }
+
+ /**
* Creates and returns an icon {@code Bitmap} to represent this {@code SubscriptionInfo} in a
* user interface.
*
@@ -467,6 +486,20 @@
}
/**
+ * @hide
+ */
+ public List<String> getEhplmns() {
+ return mEhplmns == null ? Collections.emptyList() : Arrays.asList(mEhplmns);
+ }
+
+ /**
+ * @hide
+ */
+ public List<String> getHplmns() {
+ return mHplmns == null ? Collections.emptyList() : Arrays.asList(mHplmns);
+ }
+
+ /**
* @return the profile class of this subscription.
* @hide
*/
@@ -600,7 +633,7 @@
String mcc = source.readString();
String mnc = source.readString();
String countryIso = source.readString();
- Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
+ Bitmap iconBitmap = source.readParcelable(Bitmap.class.getClassLoader());
boolean isEmbedded = source.readBoolean();
UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
String cardString = source.readString();
@@ -611,11 +644,15 @@
int carrierid = source.readInt();
int profileClass = source.readInt();
int subType = source.readInt();
+ String[] ehplmns = source.readStringArray();
+ String[] hplmns = source.readStringArray();
- return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
- nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
- isEmbedded, accessRules, cardString, cardId, isOpportunistic, groupUUID,
- isGroupDisabled, carrierid, profileClass, subType);
+ SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
+ carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc,
+ countryIso, isEmbedded, accessRules, cardString, cardId, isOpportunistic,
+ groupUUID, isGroupDisabled, carrierid, profileClass, subType);
+ info.setAssociatedPlmns(ehplmns, hplmns);
+ return info;
}
@Override
@@ -638,7 +675,7 @@
dest.writeString(mMcc);
dest.writeString(mMnc);
dest.writeString(mCountryIso);
- mIconBitmap.writeToParcel(dest, flags);
+ dest.writeParcelable(mIconBitmap, flags);
dest.writeBoolean(mIsEmbedded);
dest.writeTypedArray(mAccessRules, flags);
dest.writeString(mCardString);
@@ -649,6 +686,8 @@
dest.writeInt(mCarrierId);
dest.writeInt(mProfileClass);
dest.writeInt(mSubscriptionType);
+ dest.writeStringArray(mEhplmns);
+ dest.writeStringArray(mHplmns);
}
@Override
@@ -686,6 +725,8 @@
+ " isOpportunistic " + mIsOpportunistic + " mGroupUUID=" + mGroupUUID
+ " mIsGroupDisabled=" + mIsGroupDisabled
+ " profileClass=" + mProfileClass
+ + " ehplmns = " + Arrays.toString(mEhplmns)
+ + " hplmns = " + Arrays.toString(mHplmns)
+ " subscriptionType=" + mSubscriptionType + "}";
}
@@ -729,6 +770,8 @@
&& TextUtils.equals(mDisplayName, toCompare.mDisplayName)
&& TextUtils.equals(mCarrierName, toCompare.mCarrierName)
&& Arrays.equals(mAccessRules, toCompare.mAccessRules)
- && mProfileClass == toCompare.mProfileClass;
+ && mProfileClass == toCompare.mProfileClass
+ && Arrays.equals(mEhplmns, toCompare.mEhplmns)
+ && Arrays.equals(mHplmns, toCompare.mHplmns);
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 0c63411..0808adf 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -458,6 +458,18 @@
public static final String CARRIER_ID = "carrier_id";
/**
+ * @hide A comma-separated list of EHPLMNs associated with the subscription
+ * <P>Type: TEXT (String)</P>
+ */
+ public static final String EHPLMNS = "ehplmns";
+
+ /**
+ * @hide A comma-separated list of HPLMNs associated with the subscription
+ * <P>Type: TEXT (String)</P>
+ */
+ public static final String HPLMNS = "hplmns";
+
+ /**
* TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
* <P>Type: TEXT (String)</P>
* @hide
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
index e8fcac1..de4f174 100644
--- a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.content.Intent;
import android.os.IInterface;
import android.os.RemoteException;
import android.telephony.SubscriptionManager;
@@ -42,32 +41,6 @@
private static final String LOG_TAG = "ImsFeature";
- /**
- * Action to broadcast when ImsService is up.
- * Internal use only.
- * Only defined here separately compatibility purposes with the old ImsService.
- * @hide
- */
- public static final String ACTION_IMS_SERVICE_UP =
- "com.android.ims.IMS_SERVICE_UP";
-
- /**
- * Action to broadcast when ImsService is down.
- * Internal use only.
- * Only defined here separately for compatibility purposes with the old ImsService.
- * @hide
- */
- public static final String ACTION_IMS_SERVICE_DOWN =
- "com.android.ims.IMS_SERVICE_DOWN";
-
- /**
- * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
- * A long value; the phone ID corresponding to the IMS service coming up or down.
- * Only defined here separately for compatibility purposes with the old ImsService.
- * @hide
- */
- public static final String EXTRA_PHONE_ID = "android:phone_id";
-
// Invalid feature value
public static final int INVALID = -1;
// ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
@@ -162,30 +135,6 @@
}
}
}
- sendImsServiceIntent(state);
- }
-
- /**
- * Provide backwards compatibility using deprecated service UP/DOWN intents.
- */
- private void sendImsServiceIntent(@ImsState int state) {
- if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- return;
- }
- Intent intent;
- switch (state) {
- case ImsFeature.STATE_NOT_AVAILABLE:
- case ImsFeature.STATE_INITIALIZING:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- break;
- case ImsFeature.STATE_READY:
- intent = new Intent(ACTION_IMS_SERVICE_UP);
- break;
- default:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- }
- intent.putExtra(EXTRA_PHONE_ID, mSlotId);
- mContext.sendBroadcast(intent);
}
/**
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 5e3f398..74af6bf 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -20,7 +20,6 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.Context;
-import android.content.Intent;
import android.os.IInterface;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -395,30 +394,6 @@
}
}
}
- sendImsServiceIntent(state);
- }
-
- /**
- * Provide backwards compatibility using deprecated service UP/DOWN intents.
- */
- private void sendImsServiceIntent(@ImsState int state) {
- if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- return;
- }
- Intent intent;
- switch (state) {
- case ImsFeature.STATE_UNAVAILABLE:
- case ImsFeature.STATE_INITIALIZING:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- break;
- case ImsFeature.STATE_READY:
- intent = new Intent(ACTION_IMS_SERVICE_UP);
- break;
- default:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- }
- intent.putExtra(EXTRA_PHONE_ID, mSlotId);
- mContext.sendBroadcast(intent);
}
/**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 80fb58d..12b20ef 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -344,10 +344,22 @@
return true;
}
// if the calling package is null then return now as there's no way to perform the
- // DevicePolicyManager device / profile owner checks.
+ // DevicePolicyManager device / profile owner and AppOp checks
if (callingPackage == null) {
return false;
}
+ // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op.
+ long token = Binder.clearCallingIdentity();
+ AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(
+ Context.APP_OPS_SERVICE);
+ try {
+ if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
+ callingPackage) == AppOpsManager.MODE_ALLOWED) {
+ return true;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
// Allow access to a device / profile owner app.
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
diff --git a/tests/FlickerTests/lib/Android.bp b/tests/FlickerTests/lib/Android.bp
index 982fcba..5d8ed2c 100644
--- a/tests/FlickerTests/lib/Android.bp
+++ b/tests/FlickerTests/lib/Android.bp
@@ -20,7 +20,7 @@
srcs: ["src/**/*.java"],
static_libs: [
"androidx.test.janktesthelper",
- "cts-amwm-util",
+ "cts-wm-util",
"platformprotosnano",
"layersprotosnano",
"truth-prebuilt",
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index e0d74e0..c9e3404 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -34,6 +34,8 @@
public final class FrameworksTestsFilter extends SelectTest {
private static final String[] SELECTED_TESTS = {
+ // Test specifications for FrameworksMockingCoreTests.
+ "android.app.activity.ActivityThreadClientTest",
// Test specifications for FrameworksCoreTests.
"android.app.servertransaction.", // all tests under the package.
"android.view.DisplayCutoutTest",
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 9832485..3da22b4 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -129,12 +129,20 @@
constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM | android::ResTable_map::TYPE_FLAGS;
if (attr->type_mask & kMask) {
for (const auto& symbol : attr->symbols) {
- printer_->Print(symbol.symbol.name.value().entry);
- if (symbol.symbol.id) {
- printer_->Print("(");
+ if (symbol.symbol.name) {
+ printer_->Print(symbol.symbol.name.value().entry);
+
+ if (symbol.symbol.id) {
+ printer_->Print("(");
+ printer_->Print(symbol.symbol.id.value().to_string());
+ printer_->Print(")");
+ }
+ } else if (symbol.symbol.id) {
printer_->Print(symbol.symbol.id.value().to_string());
- printer_->Print(")");
+ } else {
+ printer_->Print("???");
}
+
printer_->Println(StringPrintf("=0x%08x", symbol.value));
}
}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 950c6f8..9d4b837 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -967,6 +967,10 @@
* from the top-level domain and all the labels in domain_suffix_match shall be included in the
* certificate. The certificate may include additional sub-level labels in addition to the
* required labels.
+ * <p>More than one match string can be provided by using semicolons to separate the strings
+ * (e.g., example.org;example.com). When multiple strings are specified, a match with any one of
+ * the values is considered a sufficient match for the certificate, i.e., the conditions are
+ * ORed ogether.
* <p>For example, domain_suffix_match=example.com would match test.example.com but would not
* match test-example.com.
* @param domain The domain value