Merge "Changing assist item strings to verbs"
diff --git a/Android.mk b/Android.mk
index 6186c55..75e9a24 100644
--- a/Android.mk
+++ b/Android.mk
@@ -618,6 +618,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
framework-protos \
android.hidl.base-V1.0-java \
+ android.hardware.health-V1.0-java \
+ android.hardware.health-V2.0-java \
android.hardware.cas-V1.0-java \
android.hardware.health-V1.0-java-constants \
android.hardware.thermal-V1.0-java-constants \
diff --git a/api/current.txt b/api/current.txt
index 9bbdee1..3ca021e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -362,6 +362,7 @@
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
+ field public static final int cantSaveState = 16844142; // 0x101056e
field public static final deprecated int capitalize = 16843113; // 0x1010169
field public static final int category = 16843752; // 0x10103e8
field public static final int centerBright = 16842956; // 0x10100cc
@@ -5643,8 +5644,10 @@
method public static java.lang.String suppressedEffectsToString(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy> CREATOR;
+ field public static final int PRIORITY_CATEGORY_ALARMS = 32; // 0x20
field public static final int PRIORITY_CATEGORY_CALLS = 8; // 0x8
field public static final int PRIORITY_CATEGORY_EVENTS = 2; // 0x2
+ field public static final int PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER = 64; // 0x40
field public static final int PRIORITY_CATEGORY_MESSAGES = 4; // 0x4
field public static final int PRIORITY_CATEGORY_REMINDERS = 1; // 0x1
field public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 16; // 0x10
@@ -10999,6 +11002,7 @@
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
method public java.lang.CharSequence getDisabledMessage();
+ method public int getDisabledReason();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
method public android.content.Intent getIntent();
@@ -11017,6 +11021,13 @@
method public boolean isPinned();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
+ field public static final int DISABLED_REASON_APP_CHANGED = 2; // 0x2
+ field public static final int DISABLED_REASON_BACKUP_NOT_SUPPORTED = 101; // 0x65
+ field public static final int DISABLED_REASON_BY_APP = 1; // 0x1
+ field public static final int DISABLED_REASON_NOT_DISABLED = 0; // 0x0
+ field public static final int DISABLED_REASON_OTHER_RESTORE_ISSUE = 103; // 0x67
+ field public static final int DISABLED_REASON_SIGNATURE_MISMATCH = 102; // 0x66
+ field public static final int DISABLED_REASON_VERSION_LOWER = 100; // 0x64
field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
}
@@ -37240,6 +37251,7 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+ field public static final int FLAG_DONT_SAVE_ON_FINISH = 2; // 0x2
field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
field public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0; // 0x0
field public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1; // 0x1
@@ -37261,6 +37273,7 @@
method public android.service.autofill.SaveInfo.Builder setFlags(int);
method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, android.content.IntentSender);
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
+ method public android.service.autofill.SaveInfo.Builder setTriggerId(android.view.autofill.AutofillId);
method public android.service.autofill.SaveInfo.Builder setValidator(android.service.autofill.Validator);
}
@@ -40034,8 +40047,12 @@
field public static final java.lang.String EXTRA_MBMS_DOWNLOAD_RESULT = "android.telephony.extra.MBMS_DOWNLOAD_RESULT";
field public static final java.lang.String EXTRA_MBMS_FILE_INFO = "android.telephony.extra.MBMS_FILE_INFO";
field public static final int RESULT_CANCELLED = 2; // 0x2
+ field public static final int RESULT_DOWNLOAD_FAILURE = 6; // 0x6
field public static final int RESULT_EXPIRED = 3; // 0x3
+ field public static final int RESULT_FILE_ROOT_UNREACHABLE = 8; // 0x8
field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_OUT_OF_STORAGE = 7; // 0x7
+ field public static final int RESULT_SERVICE_ID_NOT_DEFINED = 5; // 0x5
field public static final int RESULT_SUCCESSFUL = 1; // 0x1
field public static final int STATUS_ACTIVELY_DOWNLOADING = 1; // 0x1
field public static final int STATUS_PENDING_DOWNLOAD = 2; // 0x2
@@ -45745,8 +45762,8 @@
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
method public void bringToFront();
- method public void buildDrawingCache();
- method public void buildDrawingCache(boolean);
+ method public deprecated void buildDrawingCache();
+ method public deprecated void buildDrawingCache(boolean);
method public void buildLayer();
method public boolean callOnClick();
method public boolean canResolveLayoutDirection();
@@ -45771,7 +45788,7 @@
method protected int computeVerticalScrollRange();
method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
method public void createContextMenu(android.view.ContextMenu);
- method public void destroyDrawingCache();
+ method public deprecated void destroyDrawingCache();
method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
method public boolean dispatchCapturedPointerEvent(android.view.MotionEvent);
method public void dispatchConfigurationChanged(android.content.res.Configuration);
@@ -45852,10 +45869,10 @@
method public static int getDefaultSize(int, int);
method public android.view.Display getDisplay();
method public final int[] getDrawableState();
- method public android.graphics.Bitmap getDrawingCache();
- method public android.graphics.Bitmap getDrawingCache(boolean);
- method public int getDrawingCacheBackgroundColor();
- method public int getDrawingCacheQuality();
+ method public deprecated android.graphics.Bitmap getDrawingCache();
+ method public deprecated android.graphics.Bitmap getDrawingCache(boolean);
+ method public deprecated int getDrawingCacheBackgroundColor();
+ method public deprecated int getDrawingCacheQuality();
method public void getDrawingRect(android.graphics.Rect);
method public long getDrawingTime();
method public float getElevation();
@@ -45994,7 +46011,7 @@
method public boolean isClickable();
method public boolean isContextClickable();
method public boolean isDirty();
- method public boolean isDrawingCacheEnabled();
+ method public deprecated boolean isDrawingCacheEnabled();
method public boolean isDuplicateParentStateEnabled();
method public boolean isEnabled();
method public final boolean isFocusable();
@@ -46165,9 +46182,9 @@
method public void setContentDescription(java.lang.CharSequence);
method public void setContextClickable(boolean);
method public void setDefaultFocusHighlightEnabled(boolean);
- method public void setDrawingCacheBackgroundColor(int);
- method public void setDrawingCacheEnabled(boolean);
- method public void setDrawingCacheQuality(int);
+ method public deprecated void setDrawingCacheBackgroundColor(int);
+ method public deprecated void setDrawingCacheEnabled(boolean);
+ method public deprecated void setDrawingCacheQuality(int);
method public void setDuplicateParentStateEnabled(boolean);
method public void setElevation(float);
method public void setEnabled(boolean);
@@ -46318,9 +46335,9 @@
field public static final int DRAG_FLAG_GLOBAL_URI_READ = 1; // 0x1
field public static final int DRAG_FLAG_GLOBAL_URI_WRITE = 2; // 0x2
field public static final int DRAG_FLAG_OPAQUE = 512; // 0x200
- field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
- field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
- field public static final int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
+ field public static final deprecated int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
+ field public static final deprecated int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
+ field public static final deprecated int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
field protected static final int[] EMPTY_STATE_SET;
field protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
field protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
@@ -46712,7 +46729,7 @@
method public android.animation.LayoutTransition getLayoutTransition();
method public int getNestedScrollAxes();
method public android.view.ViewGroupOverlay getOverlay();
- method public int getPersistentDrawingCache();
+ method public deprecated int getPersistentDrawingCache();
method public boolean getTouchscreenBlocksFocus();
method public int indexOfChild(android.view.View);
method public final deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -46765,7 +46782,7 @@
method public void setAddStatesFromChildren(boolean);
method public deprecated void setAlwaysDrawnWithCacheEnabled(boolean);
method public deprecated void setAnimationCacheEnabled(boolean);
- method protected void setChildrenDrawingCacheEnabled(boolean);
+ method protected deprecated void setChildrenDrawingCacheEnabled(boolean);
method protected void setChildrenDrawingOrderEnabled(boolean);
method protected deprecated void setChildrenDrawnWithCacheEnabled(boolean);
method public void setClipChildren(boolean);
@@ -46777,7 +46794,7 @@
method public void setLayoutTransition(android.animation.LayoutTransition);
method public void setMotionEventSplittingEnabled(boolean);
method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
- method public void setPersistentDrawingCache(int);
+ method public deprecated void setPersistentDrawingCache(int);
method protected void setStaticTransformationsEnabled(boolean);
method public void setTouchscreenBlocksFocus(boolean);
method public void setTransitionGroup(boolean);
@@ -46795,10 +46812,10 @@
field public static final int FOCUS_BLOCK_DESCENDANTS = 393216; // 0x60000
field public static final int LAYOUT_MODE_CLIP_BOUNDS = 0; // 0x0
field public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1; // 0x1
- field public static final int PERSISTENT_ALL_CACHES = 3; // 0x3
- field public static final int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
- field public static final int PERSISTENT_NO_CACHE = 0; // 0x0
- field public static final int PERSISTENT_SCROLLING_CACHE = 2; // 0x2
+ field public static final deprecated int PERSISTENT_ALL_CACHES = 3; // 0x3
+ field public static final deprecated int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
+ field public static final deprecated int PERSISTENT_NO_CACHE = 0; // 0x0
+ field public static final deprecated int PERSISTENT_SCROLLING_CACHE = 2; // 0x2
}
public static class ViewGroup.LayoutParams {
diff --git a/api/system-current.txt b/api/system-current.txt
index ea077fe..5c3e1c9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -494,6 +494,7 @@
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
+ field public static final int cantSaveState = 16844142; // 0x101056e
field public static final deprecated int capitalize = 16843113; // 0x1010169
field public static final int category = 16843752; // 0x10103e8
field public static final int centerBright = 16842956; // 0x10100cc
@@ -5851,8 +5852,10 @@
method public static java.lang.String suppressedEffectsToString(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy> CREATOR;
+ field public static final int PRIORITY_CATEGORY_ALARMS = 32; // 0x20
field public static final int PRIORITY_CATEGORY_CALLS = 8; // 0x8
field public static final int PRIORITY_CATEGORY_EVENTS = 2; // 0x2
+ field public static final int PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER = 64; // 0x40
field public static final int PRIORITY_CATEGORY_MESSAGES = 4; // 0x4
field public static final int PRIORITY_CATEGORY_REMINDERS = 1; // 0x1
field public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 16; // 0x10
@@ -11722,6 +11725,7 @@
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
method public java.lang.CharSequence getDisabledMessage();
+ method public int getDisabledReason();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
method public android.content.Intent getIntent();
@@ -11740,6 +11744,13 @@
method public boolean isPinned();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
+ field public static final int DISABLED_REASON_APP_CHANGED = 2; // 0x2
+ field public static final int DISABLED_REASON_BACKUP_NOT_SUPPORTED = 101; // 0x65
+ field public static final int DISABLED_REASON_BY_APP = 1; // 0x1
+ field public static final int DISABLED_REASON_NOT_DISABLED = 0; // 0x0
+ field public static final int DISABLED_REASON_OTHER_RESTORE_ISSUE = 103; // 0x67
+ field public static final int DISABLED_REASON_SIGNATURE_MISMATCH = 102; // 0x66
+ field public static final int DISABLED_REASON_VERSION_LOWER = 100; // 0x64
field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
}
@@ -27217,7 +27228,6 @@
}
public static final class TvInputManager.Hardware {
- method public boolean dispatchKeyEventToHdmi(android.view.KeyEvent);
method public void overrideAudioSink(int, java.lang.String, int, int, int);
method public void setStreamVolume(float);
method public boolean setSurface(android.view.Surface, android.media.tv.TvStreamConfig);
@@ -40336,6 +40346,7 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+ field public static final int FLAG_DONT_SAVE_ON_FINISH = 2; // 0x2
field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
field public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0; // 0x0
field public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1; // 0x1
@@ -40357,6 +40368,7 @@
method public android.service.autofill.SaveInfo.Builder setFlags(int);
method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, android.content.IntentSender);
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
+ method public android.service.autofill.SaveInfo.Builder setTriggerId(android.view.autofill.AutofillId);
method public android.service.autofill.SaveInfo.Builder setValidator(android.service.autofill.Validator);
}
@@ -43544,8 +43556,12 @@
field public static final java.lang.String EXTRA_MBMS_FILE_INFO = "android.telephony.extra.MBMS_FILE_INFO";
field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload";
field public static final int RESULT_CANCELLED = 2; // 0x2
+ field public static final int RESULT_DOWNLOAD_FAILURE = 6; // 0x6
field public static final int RESULT_EXPIRED = 3; // 0x3
+ field public static final int RESULT_FILE_ROOT_UNREACHABLE = 8; // 0x8
field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_OUT_OF_STORAGE = 7; // 0x7
+ field public static final int RESULT_SERVICE_ID_NOT_DEFINED = 5; // 0x5
field public static final int RESULT_SUCCESSFUL = 1; // 0x1
field public static final int STATUS_ACTIVELY_DOWNLOADING = 1; // 0x1
field public static final int STATUS_PENDING_DOWNLOAD = 2; // 0x2
@@ -49471,8 +49487,8 @@
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
method public void bringToFront();
- method public void buildDrawingCache();
- method public void buildDrawingCache(boolean);
+ method public deprecated void buildDrawingCache();
+ method public deprecated void buildDrawingCache(boolean);
method public void buildLayer();
method public boolean callOnClick();
method public boolean canResolveLayoutDirection();
@@ -49497,7 +49513,7 @@
method protected int computeVerticalScrollRange();
method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
method public void createContextMenu(android.view.ContextMenu);
- method public void destroyDrawingCache();
+ method public deprecated void destroyDrawingCache();
method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
method public boolean dispatchCapturedPointerEvent(android.view.MotionEvent);
method public void dispatchConfigurationChanged(android.content.res.Configuration);
@@ -49578,10 +49594,10 @@
method public static int getDefaultSize(int, int);
method public android.view.Display getDisplay();
method public final int[] getDrawableState();
- method public android.graphics.Bitmap getDrawingCache();
- method public android.graphics.Bitmap getDrawingCache(boolean);
- method public int getDrawingCacheBackgroundColor();
- method public int getDrawingCacheQuality();
+ method public deprecated android.graphics.Bitmap getDrawingCache();
+ method public deprecated android.graphics.Bitmap getDrawingCache(boolean);
+ method public deprecated int getDrawingCacheBackgroundColor();
+ method public deprecated int getDrawingCacheQuality();
method public void getDrawingRect(android.graphics.Rect);
method public long getDrawingTime();
method public float getElevation();
@@ -49720,7 +49736,7 @@
method public boolean isClickable();
method public boolean isContextClickable();
method public boolean isDirty();
- method public boolean isDrawingCacheEnabled();
+ method public deprecated boolean isDrawingCacheEnabled();
method public boolean isDuplicateParentStateEnabled();
method public boolean isEnabled();
method public final boolean isFocusable();
@@ -49891,9 +49907,9 @@
method public void setContentDescription(java.lang.CharSequence);
method public void setContextClickable(boolean);
method public void setDefaultFocusHighlightEnabled(boolean);
- method public void setDrawingCacheBackgroundColor(int);
- method public void setDrawingCacheEnabled(boolean);
- method public void setDrawingCacheQuality(int);
+ method public deprecated void setDrawingCacheBackgroundColor(int);
+ method public deprecated void setDrawingCacheEnabled(boolean);
+ method public deprecated void setDrawingCacheQuality(int);
method public void setDuplicateParentStateEnabled(boolean);
method public void setElevation(float);
method public void setEnabled(boolean);
@@ -50044,9 +50060,9 @@
field public static final int DRAG_FLAG_GLOBAL_URI_READ = 1; // 0x1
field public static final int DRAG_FLAG_GLOBAL_URI_WRITE = 2; // 0x2
field public static final int DRAG_FLAG_OPAQUE = 512; // 0x200
- field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
- field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
- field public static final int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
+ field public static final deprecated int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
+ field public static final deprecated int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
+ field public static final deprecated int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
field protected static final int[] EMPTY_STATE_SET;
field protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
field protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
@@ -50438,7 +50454,7 @@
method public android.animation.LayoutTransition getLayoutTransition();
method public int getNestedScrollAxes();
method public android.view.ViewGroupOverlay getOverlay();
- method public int getPersistentDrawingCache();
+ method public deprecated int getPersistentDrawingCache();
method public boolean getTouchscreenBlocksFocus();
method public int indexOfChild(android.view.View);
method public final deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -50491,7 +50507,7 @@
method public void setAddStatesFromChildren(boolean);
method public deprecated void setAlwaysDrawnWithCacheEnabled(boolean);
method public deprecated void setAnimationCacheEnabled(boolean);
- method protected void setChildrenDrawingCacheEnabled(boolean);
+ method protected deprecated void setChildrenDrawingCacheEnabled(boolean);
method protected void setChildrenDrawingOrderEnabled(boolean);
method protected deprecated void setChildrenDrawnWithCacheEnabled(boolean);
method public void setClipChildren(boolean);
@@ -50503,7 +50519,7 @@
method public void setLayoutTransition(android.animation.LayoutTransition);
method public void setMotionEventSplittingEnabled(boolean);
method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
- method public void setPersistentDrawingCache(int);
+ method public deprecated void setPersistentDrawingCache(int);
method protected void setStaticTransformationsEnabled(boolean);
method public void setTouchscreenBlocksFocus(boolean);
method public void setTransitionGroup(boolean);
@@ -50521,10 +50537,10 @@
field public static final int FOCUS_BLOCK_DESCENDANTS = 393216; // 0x60000
field public static final int LAYOUT_MODE_CLIP_BOUNDS = 0; // 0x0
field public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1; // 0x1
- field public static final int PERSISTENT_ALL_CACHES = 3; // 0x3
- field public static final int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
- field public static final int PERSISTENT_NO_CACHE = 0; // 0x0
- field public static final int PERSISTENT_SCROLLING_CACHE = 2; // 0x2
+ field public static final deprecated int PERSISTENT_ALL_CACHES = 3; // 0x3
+ field public static final deprecated int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
+ field public static final deprecated int PERSISTENT_NO_CACHE = 0; // 0x0
+ field public static final deprecated int PERSISTENT_SCROLLING_CACHE = 2; // 0x2
}
public static class ViewGroup.LayoutParams {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 7ee261e..639877f 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -275,6 +275,10 @@
method public android.media.tv.TvInputManager.Hardware acquireTvInputHardware(int, android.media.tv.TvInputManager.HardwareCallback, android.media.tv.TvInputInfo);
}
+ public static final class TvInputManager.Hardware {
+ method public boolean dispatchKeyEventToHdmi(android.view.KeyEvent);
+ }
+
public class TvView extends android.view.ViewGroup {
method public void requestUnblockContent(android.media.tv.TvContentRating);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index fe861e1..132a787 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -362,6 +362,7 @@
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
+ field public static final int cantSaveState = 16844142; // 0x101056e
field public static final deprecated int capitalize = 16843113; // 0x1010169
field public static final int category = 16843752; // 0x10103e8
field public static final int centerBright = 16842956; // 0x10100cc
@@ -5669,8 +5670,10 @@
method public static java.lang.String suppressedEffectsToString(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy> CREATOR;
+ field public static final int PRIORITY_CATEGORY_ALARMS = 32; // 0x20
field public static final int PRIORITY_CATEGORY_CALLS = 8; // 0x8
field public static final int PRIORITY_CATEGORY_EVENTS = 2; // 0x2
+ field public static final int PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER = 64; // 0x40
field public static final int PRIORITY_CATEGORY_MESSAGES = 4; // 0x4
field public static final int PRIORITY_CATEGORY_REMINDERS = 1; // 0x1
field public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 16; // 0x10
@@ -11080,6 +11083,7 @@
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
method public java.lang.CharSequence getDisabledMessage();
+ method public int getDisabledReason();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
method public android.content.Intent getIntent();
@@ -11096,8 +11100,16 @@
method public boolean isEnabled();
method public boolean isImmutable();
method public boolean isPinned();
+ method public boolean isVisibleToPublisher();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
+ field public static final int DISABLED_REASON_APP_CHANGED = 2; // 0x2
+ field public static final int DISABLED_REASON_BACKUP_NOT_SUPPORTED = 101; // 0x65
+ field public static final int DISABLED_REASON_BY_APP = 1; // 0x1
+ field public static final int DISABLED_REASON_NOT_DISABLED = 0; // 0x0
+ field public static final int DISABLED_REASON_OTHER_RESTORE_ISSUE = 103; // 0x67
+ field public static final int DISABLED_REASON_SIGNATURE_MISMATCH = 102; // 0x66
+ field public static final int DISABLED_REASON_VERSION_LOWER = 100; // 0x64
field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
}
@@ -37534,6 +37546,7 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+ field public static final int FLAG_DONT_SAVE_ON_FINISH = 2; // 0x2
field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
field public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0; // 0x0
field public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1; // 0x1
@@ -37555,6 +37568,7 @@
method public android.service.autofill.SaveInfo.Builder setFlags(int);
method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, android.content.IntentSender);
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
+ method public android.service.autofill.SaveInfo.Builder setTriggerId(android.view.autofill.AutofillId);
method public android.service.autofill.SaveInfo.Builder setValidator(android.service.autofill.Validator);
}
@@ -40415,8 +40429,12 @@
field public static final java.lang.String EXTRA_MBMS_DOWNLOAD_RESULT = "android.telephony.extra.MBMS_DOWNLOAD_RESULT";
field public static final java.lang.String EXTRA_MBMS_FILE_INFO = "android.telephony.extra.MBMS_FILE_INFO";
field public static final int RESULT_CANCELLED = 2; // 0x2
+ field public static final int RESULT_DOWNLOAD_FAILURE = 6; // 0x6
field public static final int RESULT_EXPIRED = 3; // 0x3
+ field public static final int RESULT_FILE_ROOT_UNREACHABLE = 8; // 0x8
field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_OUT_OF_STORAGE = 7; // 0x7
+ field public static final int RESULT_SERVICE_ID_NOT_DEFINED = 5; // 0x5
field public static final int RESULT_SUCCESSFUL = 1; // 0x1
field public static final int STATUS_ACTIVELY_DOWNLOADING = 1; // 0x1
field public static final int STATUS_PENDING_DOWNLOAD = 2; // 0x2
@@ -46315,8 +46333,8 @@
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
method public void bringToFront();
- method public void buildDrawingCache();
- method public void buildDrawingCache(boolean);
+ method public deprecated void buildDrawingCache();
+ method public deprecated void buildDrawingCache(boolean);
method public void buildLayer();
method public boolean callOnClick();
method public boolean canResolveLayoutDirection();
@@ -46341,7 +46359,7 @@
method protected int computeVerticalScrollRange();
method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
method public void createContextMenu(android.view.ContextMenu);
- method public void destroyDrawingCache();
+ method public deprecated void destroyDrawingCache();
method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
method public boolean dispatchCapturedPointerEvent(android.view.MotionEvent);
method public void dispatchConfigurationChanged(android.content.res.Configuration);
@@ -46422,10 +46440,10 @@
method public static int getDefaultSize(int, int);
method public android.view.Display getDisplay();
method public final int[] getDrawableState();
- method public android.graphics.Bitmap getDrawingCache();
- method public android.graphics.Bitmap getDrawingCache(boolean);
- method public int getDrawingCacheBackgroundColor();
- method public int getDrawingCacheQuality();
+ method public deprecated android.graphics.Bitmap getDrawingCache();
+ method public deprecated android.graphics.Bitmap getDrawingCache(boolean);
+ method public deprecated int getDrawingCacheBackgroundColor();
+ method public deprecated int getDrawingCacheQuality();
method public void getDrawingRect(android.graphics.Rect);
method public long getDrawingTime();
method public float getElevation();
@@ -46566,7 +46584,7 @@
method public boolean isContextClickable();
method public boolean isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
method public boolean isDirty();
- method public boolean isDrawingCacheEnabled();
+ method public deprecated boolean isDrawingCacheEnabled();
method public boolean isDuplicateParentStateEnabled();
method public boolean isEnabled();
method public final boolean isFocusable();
@@ -46740,9 +46758,9 @@
method public void setContentDescription(java.lang.CharSequence);
method public void setContextClickable(boolean);
method public void setDefaultFocusHighlightEnabled(boolean);
- method public void setDrawingCacheBackgroundColor(int);
- method public void setDrawingCacheEnabled(boolean);
- method public void setDrawingCacheQuality(int);
+ method public deprecated void setDrawingCacheBackgroundColor(int);
+ method public deprecated void setDrawingCacheEnabled(boolean);
+ method public deprecated void setDrawingCacheQuality(int);
method public void setDuplicateParentStateEnabled(boolean);
method public void setElevation(float);
method public void setEnabled(boolean);
@@ -46894,9 +46912,9 @@
field public static final int DRAG_FLAG_GLOBAL_URI_READ = 1; // 0x1
field public static final int DRAG_FLAG_GLOBAL_URI_WRITE = 2; // 0x2
field public static final int DRAG_FLAG_OPAQUE = 512; // 0x200
- field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
- field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
- field public static final int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
+ field public static final deprecated int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
+ field public static final deprecated int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
+ field public static final deprecated int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
field protected static final int[] EMPTY_STATE_SET;
field protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
field protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
@@ -47292,7 +47310,7 @@
method public android.animation.LayoutTransition getLayoutTransition();
method public int getNestedScrollAxes();
method public android.view.ViewGroupOverlay getOverlay();
- method public int getPersistentDrawingCache();
+ method public deprecated int getPersistentDrawingCache();
method public boolean getTouchscreenBlocksFocus();
method public int indexOfChild(android.view.View);
method public final deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -47345,7 +47363,7 @@
method public void setAddStatesFromChildren(boolean);
method public deprecated void setAlwaysDrawnWithCacheEnabled(boolean);
method public deprecated void setAnimationCacheEnabled(boolean);
- method protected void setChildrenDrawingCacheEnabled(boolean);
+ method protected deprecated void setChildrenDrawingCacheEnabled(boolean);
method protected void setChildrenDrawingOrderEnabled(boolean);
method protected deprecated void setChildrenDrawnWithCacheEnabled(boolean);
method public void setClipChildren(boolean);
@@ -47357,7 +47375,7 @@
method public void setLayoutTransition(android.animation.LayoutTransition);
method public void setMotionEventSplittingEnabled(boolean);
method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
- method public void setPersistentDrawingCache(int);
+ method public deprecated void setPersistentDrawingCache(int);
method protected void setStaticTransformationsEnabled(boolean);
method public void setTouchscreenBlocksFocus(boolean);
method public void setTransitionGroup(boolean);
@@ -47375,10 +47393,10 @@
field public static final int FOCUS_BLOCK_DESCENDANTS = 393216; // 0x60000
field public static final int LAYOUT_MODE_CLIP_BOUNDS = 0; // 0x0
field public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1; // 0x1
- field public static final int PERSISTENT_ALL_CACHES = 3; // 0x3
- field public static final int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
- field public static final int PERSISTENT_NO_CACHE = 0; // 0x0
- field public static final int PERSISTENT_SCROLLING_CACHE = 2; // 0x2
+ field public static final deprecated int PERSISTENT_ALL_CACHES = 3; // 0x3
+ field public static final deprecated int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
+ field public static final deprecated int PERSISTENT_NO_CACHE = 0; // 0x0
+ field public static final deprecated int PERSISTENT_SCROLLING_CACHE = 2; // 0x2
}
public static class ViewGroup.LayoutParams {
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 6526123..d1af71d 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -260,9 +260,9 @@
sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
- SurfaceComposerClient::openGlobalTransaction();
- control->setLayer(0x40000000);
- SurfaceComposerClient::closeGlobalTransaction();
+ SurfaceComposerClient::Transaction t;
+ t.setLayer(control, 0x40000000)
+ .apply();
sp<Surface> s = control->getSurface();
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 07a064cf..37f6ed7 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -33,18 +33,18 @@
{
EncodedBuffer::Pointer snapshot = iter->rp()->copy();
size_t bytesToWrite = 0;
- uint32_t varint = 0;
+ uint64_t varint = 0;
switch (wireType) {
case WIRE_TYPE_VARINT:
varint = iter->readRawVarint();
- if(!skip) return buf->writeRawVarint(varint);
+ if(!skip) return buf->writeRawVarint64(varint);
break;
case WIRE_TYPE_FIXED64:
bytesToWrite = 8;
break;
case WIRE_TYPE_LENGTH_DELIMITED:
bytesToWrite = iter->readRawVarint();
- if(!skip) buf->writeRawVarint(bytesToWrite);
+ if(!skip) buf->writeRawVarint32(bytesToWrite);
break;
case WIRE_TYPE_FIXED32:
bytesToWrite = 4;
@@ -76,7 +76,6 @@
uint8_t wireType = read_wire_type(varint);
uint32_t fieldId = read_field_id(varint);
const Privacy* policy = parentPolicy->lookup(fieldId);
-
if (policy == NULL || !policy->IsMessageType() || !policy->HasChildren()) {
bool skip = !spec.CheckPremission(policy);
size_t amt = buf->size();
@@ -99,7 +98,7 @@
}
buf->writeHeader(fieldId, wireType);
- buf->writeRawVarint(finalSize);
+ buf->writeRawVarint32(finalSize);
while (!q.empty()) {
EncodedBuffer* subField = q.front();
EncodedBuffer::iterator it = subField->begin();
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index c5b3b68..4c95007 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -112,6 +112,7 @@
../../core/java/android/os/IStatsCompanionService.aidl \
../../core/java/android/os/IStatsManager.aidl \
src/StatsService.cpp \
+ src/AnomalyMonitor.cpp \
src/stats_util.cpp \
src/LogEntryPrinter.cpp \
src/LogReader.cpp \
diff --git a/cmds/statsd/src/AnomalyMonitor.cpp b/cmds/statsd/src/AnomalyMonitor.cpp
index 92fe844..4fbbc7a 100644
--- a/cmds/statsd/src/AnomalyMonitor.cpp
+++ b/cmds/statsd/src/AnomalyMonitor.cpp
@@ -90,6 +90,36 @@
}
}
+// More efficient than repeatedly calling remove(mPq.top()) since it batches the
+// updates to the registered alarm.
+unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>
+ AnomalyMonitor::popSoonerThan(uint32_t timestampSec) {
+
+ if (DEBUG) ALOGD("Removing alarms with time <= %u", timestampSec);
+ unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> oldAlarms;
+ std::lock_guard<std::mutex> lock(mLock);
+
+ for (sp<const AnomalyAlarm> t = mPq.top();
+ t != nullptr && t->timestampSec <= timestampSec; t = mPq.top()) {
+ oldAlarms.insert(t);
+ mPq.pop(); // remove t
+ }
+ // Always update registered alarm time (if anything has changed).
+ if (!oldAlarms.empty()) {
+ if (mPq.empty()) {
+ if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
+ mRegisteredAlarmTimeSec = 0;
+ if (mStatsCompanionService != nullptr) {
+ mStatsCompanionService->cancelAnomalyAlarm();
+ }
+ } else {
+ // Always update the registered alarm in this case (unlike remove()).
+ updateRegisteredAlarmTime_l(mPq.top()->timestampSec);
+ }
+ }
+ return oldAlarms;
+}
+
void AnomalyMonitor::updateRegisteredAlarmTime_l(uint32_t timestampSec) {
if (DEBUG) ALOGD("Updating reg alarm time to %u", timestampSec);
mRegisteredAlarmTimeSec = timestampSec;
diff --git a/cmds/statsd/src/AnomalyMonitor.h b/cmds/statsd/src/AnomalyMonitor.h
index d78be54..7c6e5e8 100644
--- a/cmds/statsd/src/AnomalyMonitor.h
+++ b/cmds/statsd/src/AnomalyMonitor.h
@@ -21,12 +21,14 @@
#include <indexed_priority_queue.h>
#include <utils/RefBase.h>
+#include <unordered_set>
#include <queue>
#include <vector>
using namespace android;
using android::os::IStatsCompanionService;
+using std::unordered_set;
namespace android {
namespace os {
@@ -86,6 +88,13 @@
void remove(sp<const AnomalyAlarm> alarm);
/**
+ * Returns and removes all alarms whose timestamp <= the given timestampSec.
+ * Always updates the registered alarm if return is non-empty.
+ */
+ unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>
+ popSoonerThan(uint32_t timestampSec);
+
+ /**
* Returns the projected alarm timestamp that is registered with
* StatsCompanionService. This may not be equal to the soonest alarm,
* but should be within minDiffToUpdateRegisteredAlarmTimeSec of it.
diff --git a/cmds/statsd/src/indexed_priority_queue.h b/cmds/statsd/src/indexed_priority_queue.h
index c749c3e..81e8b3d 100644
--- a/cmds/statsd/src/indexed_priority_queue.h
+++ b/cmds/statsd/src/indexed_priority_queue.h
@@ -55,6 +55,8 @@
void push(sp<const AA> a);
/** Removes a from the priority queue. If not present or a==nullptr, does nothing. */
void remove(sp<const AA> a);
+ /** Removes the top element, if there is one. */
+ void pop();
/** Removes all elements. */
void clear();
/** Returns whether priority queue contains a (not just a copy of a, but a itself). */
@@ -127,6 +129,28 @@
sift_down(idx);
}
+// The same as, but slightly more efficient than, remove(top()).
+template <class AA, class Comparator>
+void indexed_priority_queue<AA, Comparator>::pop() {
+ sp<const AA> a = top();
+ if (a == nullptr) return;
+ const size_t idx = 1;
+ if (idx == size()) { // if a is the last element
+ pq.pop_back();
+ indices.erase(a);
+ return;
+ }
+ // move last element (guaranteed not to be at idx) to idx, then delete a
+ sp<const AA> last_a = pq.back();
+ pq[idx] = last_a;
+ pq.pop_back();
+ indices[last_a] = idx;
+ indices.erase(a);
+
+ // get the heap back in order (since the element at idx is not in order)
+ sift_down(idx);
+}
+
template <class AA, class Comparator>
void indexed_priority_queue<AA, Comparator>::clear() {
pq.clear();
diff --git a/cmds/statsd/tests/AnomalyMonitor_test.cpp b/cmds/statsd/tests/AnomalyMonitor_test.cpp
new file mode 100644
index 0000000..d5b6811
--- /dev/null
+++ b/cmds/statsd/tests/AnomalyMonitor_test.cpp
@@ -0,0 +1,66 @@
+// Copyright (C) 2017 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.
+
+#define LOG_TAG "statsd_test"
+
+#include "../src/AnomalyMonitor.h"
+
+#include <gtest/gtest.h>
+
+using namespace android::os::statsd;
+
+#ifdef __ANDROID__
+TEST(AnomalyMonitor, popSoonerThan) {
+ unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> set;
+ AnomalyMonitor am(2);
+
+ set = am.popSoonerThan(5);
+ EXPECT_TRUE(set.empty());
+
+ sp<const AnomalyAlarm> a = new AnomalyAlarm{10};
+ sp<const AnomalyAlarm> b = new AnomalyAlarm{20};
+ sp<const AnomalyAlarm> c = new AnomalyAlarm{20};
+ sp<const AnomalyAlarm> d = new AnomalyAlarm{30};
+ sp<const AnomalyAlarm> e = new AnomalyAlarm{40};
+ sp<const AnomalyAlarm> f = new AnomalyAlarm{50};
+
+ am.add(a);
+ am.add(b);
+ am.add(c);
+ am.add(d);
+ am.add(e);
+ am.add(f);
+
+ set = am.popSoonerThan(5);
+ EXPECT_TRUE(set.empty());
+
+ set = am.popSoonerThan(30);
+ EXPECT_EQ(4u, set.size());
+ EXPECT_EQ(1u, set.count(a));
+ EXPECT_EQ(1u, set.count(b));
+ EXPECT_EQ(1u, set.count(c));
+ EXPECT_EQ(1u, set.count(d));
+
+ set = am.popSoonerThan(60);
+ EXPECT_EQ(2u, set.size());
+ EXPECT_EQ(1u, set.count(e));
+ EXPECT_EQ(1u, set.count(f));
+
+ set = am.popSoonerThan(80);
+ EXPECT_EQ(0u, set.size());
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/indexed_priority_queue_test.cpp b/cmds/statsd/tests/indexed_priority_queue_test.cpp
index e4d4d25..74a482e 100644
--- a/cmds/statsd/tests/indexed_priority_queue_test.cpp
+++ b/cmds/statsd/tests/indexed_priority_queue_test.cpp
@@ -182,6 +182,40 @@
EXPECT_FALSE(ipq.contains(nullptr));
}
+TEST(indexed_priority_queue, pop) {
+ indexed_priority_queue<AATest, AATest::Smaller> ipq;
+ sp<const AATest> a = new AATest{1};
+ sp<const AATest> b = new AATest{2};
+ sp<const AATest> c = new AATest{3};
+
+ ipq.push(c);
+ ipq.push(b);
+ ipq.push(a);
+ EXPECT_EQ(3u, ipq.size());
+
+ ipq.pop();
+ EXPECT_EQ(2u, ipq.size());
+ EXPECT_FALSE(ipq.contains(a));
+ EXPECT_TRUE(ipq.contains(b));
+ EXPECT_TRUE(ipq.contains(c));
+
+ ipq.pop();
+ EXPECT_EQ(1u, ipq.size());
+ EXPECT_FALSE(ipq.contains(a));
+ EXPECT_FALSE(ipq.contains(b));
+ EXPECT_TRUE(ipq.contains(c));
+
+ ipq.pop();
+ EXPECT_EQ(0u, ipq.size());
+ EXPECT_FALSE(ipq.contains(a));
+ EXPECT_FALSE(ipq.contains(b));
+ EXPECT_FALSE(ipq.contains(c));
+ EXPECT_TRUE(ipq.empty());
+
+ ipq.pop(); // pop an empty queue
+ EXPECT_TRUE(ipq.empty());
+}
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d988a42..252959a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1879,7 +1879,7 @@
if (isFinishing()) {
if (mAutoFillResetNeeded) {
- getAutofillManager().commit();
+ getAutofillManager().onActivityFinished();
} else if (mIntent != null
&& mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
// Activity was launched when user tapped a link in the Autofill Save UI - since
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5e61727..dff43ed 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,13 +16,6 @@
package android.app;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -670,138 +663,6 @@
/** Invalid stack ID. */
public static final int INVALID_STACK_ID = -1;
- /** First static stack ID.
- * @hide */
- private static final int FIRST_STATIC_STACK_ID = 0;
-
- /** ID of stack where fullscreen activities are normally launched into.
- * @hide */
- public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
-
- /** ID of stack where freeform/resized activities are normally launched into.
- * @hide */
- public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;
-
- /** ID of stack that occupies a dedicated region of the screen.
- * @hide */
- public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;
-
- /** ID of stack that always on top (always visible) when it exist.
- * @hide */
- public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
-
- /** Last static stack stack ID.
- * @hide */
- private static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
-
- /** Start of ID range used by stacks that are created dynamically.
- * @hide */
- public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
-
- // TODO: Figure-out a way to remove this.
- /** @hide */
- public static boolean isStaticStack(int stackId) {
- return stackId >= FIRST_STATIC_STACK_ID && stackId <= LAST_STATIC_STACK_ID;
- }
-
- // TODO: It seems this mostly means a stack on a secondary display now. Need to see if
- // there are other meanings. If not why not just use information from the display?
- /** @hide */
- public static boolean isDynamicStack(int stackId) {
- return stackId >= FIRST_DYNAMIC_STACK_ID;
- }
-
- /**
- * Returns true if we try to maintain focus in the current stack when the top activity
- * finishes.
- * @hide
- */
- // TODO: Figure-out a way to remove. Probably isn't needed in the new world...
- public static boolean keepFocusInStackIfPossible(int stackId) {
- return stackId == FREEFORM_WORKSPACE_STACK_ID
- || stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID;
- }
-
- /**
- * Returns true if the windows of tasks being moved to the target stack from the source
- * stack should be replaced, meaning that window manager will keep the old window around
- * until the new is ready.
- * @hide
- */
- public static boolean replaceWindowsOnTaskMove(int sourceStackId, int targetStackId) {
- return sourceStackId == FREEFORM_WORKSPACE_STACK_ID
- || targetStackId == FREEFORM_WORKSPACE_STACK_ID;
- }
-
- /**
- * Returns true if the top task in the task is allowed to return home when finished and
- * there are other tasks in the stack.
- * @hide
- */
- public static boolean allowTopTaskToReturnHome(int stackId) {
- return stackId != PINNED_STACK_ID;
- }
-
- /**
- * Returns true if the stack should be resized to match the bounds specified by
- * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack.
- * @hide
- */
- public static boolean resizeStackWithLaunchBounds(int stackId) {
- return stackId == PINNED_STACK_ID;
- }
-
- /**
- * Returns true if a window from the specified stack with {@param stackId} are normally
- * fullscreen, i. e. they can become the top opaque fullscreen window, meaning that it
- * controls system bars, lockscreen occluded/dismissing state, screen rotation animation,
- * etc.
- * @hide
- */
- // TODO: What about the other side of docked stack if we move this to WindowConfiguration?
- public static boolean normallyFullscreenWindows(int stackId) {
- return stackId != PINNED_STACK_ID && stackId != FREEFORM_WORKSPACE_STACK_ID
- && stackId != DOCKED_STACK_ID;
- }
-
- /** Returns the stack id for the input windowing mode.
- * @hide */
- // TODO: To be removed once we are not using stack id for stuff...
- public static int getStackIdForWindowingMode(int windowingMode) {
- switch (windowingMode) {
- case WINDOWING_MODE_PINNED: return PINNED_STACK_ID;
- case WINDOWING_MODE_FREEFORM: return FREEFORM_WORKSPACE_STACK_ID;
- case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return DOCKED_STACK_ID;
- case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return FULLSCREEN_WORKSPACE_STACK_ID;
- case WINDOWING_MODE_FULLSCREEN: return FULLSCREEN_WORKSPACE_STACK_ID;
- default: return INVALID_STACK_ID;
- }
- }
-
- /** Returns the windowing mode that should be used for this input stack id.
- * @hide */
- // TODO: To be removed once we are not using stack id for stuff...
- public static int getWindowingModeForStackId(int stackId, boolean inSplitScreenMode) {
- final int windowingMode;
- switch (stackId) {
- case FULLSCREEN_WORKSPACE_STACK_ID:
- windowingMode = inSplitScreenMode
- ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY : WINDOWING_MODE_FULLSCREEN;
- break;
- case PINNED_STACK_ID:
- windowingMode = WINDOWING_MODE_PINNED;
- break;
- case DOCKED_STACK_ID:
- windowingMode = WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
- break;
- case FREEFORM_WORKSPACE_STACK_ID:
- windowingMode = WINDOWING_MODE_FREEFORM;
- break;
- default :
- windowingMode = WINDOWING_MODE_UNDEFINED;
- }
- return windowingMode;
- }
}
/**
@@ -1571,7 +1432,6 @@
}
dest.writeInt(stackId);
dest.writeInt(userId);
- dest.writeLong(firstActiveTime);
dest.writeLong(lastActiveTime);
dest.writeInt(affiliatedTaskId);
dest.writeInt(affiliatedTaskColor);
@@ -1600,7 +1460,6 @@
TaskDescription.CREATOR.createFromParcel(source) : null;
stackId = source.readInt();
userId = source.readInt();
- firstActiveTime = source.readLong();
lastActiveTime = source.readLong();
affiliatedTaskId = source.readInt();
affiliatedTaskColor = source.readInt();
@@ -1643,31 +1502,6 @@
public static final int RECENT_IGNORE_UNAVAILABLE = 0x0002;
/**
- * Provides a list that contains recent tasks for all
- * profiles of a user.
- * @hide
- */
- public static final int RECENT_INCLUDE_PROFILES = 0x0004;
-
- /**
- * Ignores all tasks that are on the home stack.
- * @hide
- */
- public static final int RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS = 0x0008;
-
- /**
- * Ignores the top task in the docked stack.
- * @hide
- */
- public static final int RECENT_INGORE_DOCKED_STACK_TOP_TASK = 0x0010;
-
- /**
- * Ignores all tasks that are on the pinned stack.
- * @hide
- */
- public static final int RECENT_INGORE_PINNED_STACK_TASKS = 0x0020;
-
- /**
* <p></p>Return a list of the tasks that the user has recently launched, with
* the most recent being first and older ones after in order.
*
@@ -1702,33 +1536,7 @@
public List<RecentTaskInfo> getRecentTasks(int maxNum, int flags)
throws SecurityException {
try {
- return getService().getRecentTasks(maxNum,
- flags, UserHandle.myUserId()).getList();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Same as {@link #getRecentTasks(int, int)} but returns the recent tasks for a
- * specific user. It requires holding
- * the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
- * @param maxNum The maximum number of entries to return in the list. The
- * actual number returned may be smaller, depending on how many tasks the
- * user has started and the maximum number the system can remember.
- * @param flags Information about what to return. May be any combination
- * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}.
- *
- * @return Returns a list of RecentTaskInfo records describing each of
- * the recent tasks. Most recently activated tasks go first.
- *
- * @hide
- */
- public List<RecentTaskInfo> getRecentTasksForUser(int maxNum, int flags, int userId)
- throws SecurityException {
- try {
- return getService().getRecentTasks(maxNum,
- flags, userId).getList();
+ return getService().getRecentTasks(maxNum, flags, UserHandle.myUserId()).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index a68c3a5..f14831d 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -17,7 +17,6 @@
package android.app;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index f039516..117854a 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -178,8 +178,8 @@
* SIGUSR1 is delivered. All others are ignored.
*/
void signalPersistentProcesses(int signal);
- ParceledListSlice getRecentTasks(int maxNum,
- int flags, int userId);
+
+ ParceledListSlice getRecentTasks(int maxNum, int flags, int userId);
oneway void serviceDoneExecuting(in IBinder token, int type, int startId, int res);
oneway void activityDestroyed(in IBinder token);
IIntentSender getIntentSender(int type, in String packageName, in IBinder token,
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 54f74b1..1fe2900 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -387,8 +387,6 @@
* such as the Home key and the right soft keys, don't work.
*
* @return true if in keyguard restricted input mode.
- *
- * @see android.view.WindowManagerPolicy#inKeyguardRestrictedKeyInputMode
*/
public boolean inKeyguardRestrictedInputMode() {
try {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 47063f0..c06ad3f 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -32,6 +32,8 @@
import com.android.internal.util.Preconditions;
+import com.android.internal.util.Preconditions;
+
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index eb52cb7..a52dc1e 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -934,8 +934,14 @@
public static final int PRIORITY_CATEGORY_CALLS = 1 << 3;
/** Calls from repeat callers are prioritized. */
public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 1 << 4;
+ /** Alarms are prioritized */
+ public static final int PRIORITY_CATEGORY_ALARMS = 1 << 5;
+ /** Media, system, game (catch-all for non-never suppressible sounds) are prioritized */
+ public static final int PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER = 1 << 6;
private static final int[] ALL_PRIORITY_CATEGORIES = {
+ PRIORITY_CATEGORY_ALARMS,
+ PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER,
PRIORITY_CATEGORY_REMINDERS,
PRIORITY_CATEGORY_EVENTS,
PRIORITY_CATEGORY_MESSAGES,
@@ -1135,6 +1141,9 @@
case PRIORITY_CATEGORY_MESSAGES: return "PRIORITY_CATEGORY_MESSAGES";
case PRIORITY_CATEGORY_CALLS: return "PRIORITY_CATEGORY_CALLS";
case PRIORITY_CATEGORY_REPEAT_CALLERS: return "PRIORITY_CATEGORY_REPEAT_CALLERS";
+ case PRIORITY_CATEGORY_ALARMS: return "PRIORITY_CATEGORY_ALARMS";
+ case PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER:
+ return "PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER";
default: return "PRIORITY_CATEGORY_UNKNOWN_" + priorityCategory;
}
}
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 6b40538..251863c 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -511,7 +511,8 @@
return windowingMode != WINDOWING_MODE_FREEFORM && windowingMode != WINDOWING_MODE_PINNED;
}
- private static String windowingModeToString(@WindowingMode int windowingMode) {
+ /** @hide */
+ public static String windowingModeToString(@WindowingMode int windowingMode) {
switch (windowingMode) {
case WINDOWING_MODE_UNDEFINED: return "undefined";
case WINDOWING_MODE_FULLSCREEN: return "fullscreen";
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c9ad951..e47de75 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -53,6 +53,7 @@
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.XmlUtils;
@@ -9371,6 +9372,57 @@
}
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean secure, boolean comp,
+ boolean extras, boolean clip) {
+ long token = proto.start(fieldId);
+ if (mAction != null) {
+ proto.write(IntentProto.ACTION, mAction);
+ }
+ if (mCategories != null) {
+ for (String category : mCategories) {
+ proto.write(IntentProto.CATEGORIES, category);
+ }
+ }
+ if (mData != null) {
+ proto.write(IntentProto.DATA, secure ? mData.toSafeString() : mData.toString());
+ }
+ if (mType != null) {
+ proto.write(IntentProto.TYPE, mType);
+ }
+ if (mFlags != 0) {
+ proto.write(IntentProto.FLAG, "0x" + Integer.toHexString(mFlags));
+ }
+ if (mPackage != null) {
+ proto.write(IntentProto.PACKAGE, mPackage);
+ }
+ if (comp && mComponent != null) {
+ proto.write(IntentProto.COMPONENT, mComponent.flattenToShortString());
+ }
+ if (mSourceBounds != null) {
+ proto.write(IntentProto.SOURCE_BOUNDS, mSourceBounds.toShortString());
+ }
+ if (mClipData != null) {
+ StringBuilder b = new StringBuilder();
+ if (clip) {
+ mClipData.toShortString(b);
+ } else {
+ mClipData.toShortStringShortItems(b, false);
+ }
+ proto.write(IntentProto.CLIP_DATA, b.toString());
+ }
+ if (extras && mExtras != null) {
+ proto.write(IntentProto.EXTRAS, mExtras.toShortString());
+ }
+ if (mContentUserHint != 0) {
+ proto.write(IntentProto.CONTENT_USER_HINT, mContentUserHint);
+ }
+ if (mSelector != null) {
+ proto.write(IntentProto.SELECTOR, mSelector.toShortString(secure, comp, extras, clip));
+ }
+ proto.end(token);
+ }
+
/**
* Call {@link #toUri} with 0 flags.
* @deprecated Use {@link #toUri} instead.
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index c9bce53..a957aed 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -26,6 +26,7 @@
import android.util.AndroidException;
import android.util.Log;
import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.XmlUtils;
@@ -918,6 +919,15 @@
dest.writeInt(mPort);
}
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ // The original host information is already contained in host and wild, no output now.
+ proto.write(AuthorityEntryProto.HOST, mHost);
+ proto.write(AuthorityEntryProto.WILD, mWild);
+ proto.write(AuthorityEntryProto.PORT, mPort);
+ proto.end(token);
+ }
+
public String getHost() {
return mOrigHost;
}
@@ -1739,6 +1749,59 @@
}
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ if (mActions.size() > 0) {
+ Iterator<String> it = mActions.iterator();
+ while (it.hasNext()) {
+ proto.write(IntentFilterProto.ACTIONS, it.next());
+ }
+ }
+ if (mCategories != null) {
+ Iterator<String> it = mCategories.iterator();
+ while (it.hasNext()) {
+ proto.write(IntentFilterProto.CATEGORIES, it.next());
+ }
+ }
+ if (mDataSchemes != null) {
+ Iterator<String> it = mDataSchemes.iterator();
+ while (it.hasNext()) {
+ proto.write(IntentFilterProto.DATA_SCHEMES, it.next());
+ }
+ }
+ if (mDataSchemeSpecificParts != null) {
+ Iterator<PatternMatcher> it = mDataSchemeSpecificParts.iterator();
+ while (it.hasNext()) {
+ it.next().writeToProto(proto, IntentFilterProto.DATA_SCHEME_SPECS);
+ }
+ }
+ if (mDataAuthorities != null) {
+ Iterator<AuthorityEntry> it = mDataAuthorities.iterator();
+ while (it.hasNext()) {
+ it.next().writeToProto(proto, IntentFilterProto.DATA_AUTHORITIES);
+ }
+ }
+ if (mDataPaths != null) {
+ Iterator<PatternMatcher> it = mDataPaths.iterator();
+ while (it.hasNext()) {
+ it.next().writeToProto(proto, IntentFilterProto.DATA_PATHS);
+ }
+ }
+ if (mDataTypes != null) {
+ Iterator<String> it = mDataTypes.iterator();
+ while (it.hasNext()) {
+ proto.write(IntentFilterProto.DATA_TYPES, it.next());
+ }
+ }
+ if (mPriority != 0 || mHasPartialTypes) {
+ proto.write(IntentFilterProto.PRIORITY, mPriority);
+ proto.write(IntentFilterProto.HAS_PARTIAL_TYPES, mHasPartialTypes);
+ }
+ proto.write(IntentFilterProto.GET_AUTO_VERIFY, getAutoVerify());
+ proto.end(token);
+ }
+
public void dump(Printer du, String prefix) {
StringBuilder sb = new StringBuilder(256);
if (mActions.size() > 0) {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ec48ac5..ad36139a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3711,17 +3711,15 @@
ai.flags |= ApplicationInfo.FLAG_IS_GAME;
}
- if (false) {
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
- false)) {
- ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
+ false)) {
+ ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
- // A heavy-weight application can not be in a custom process.
- // We can do direct compare because we intern all strings.
- if (ai.processName != null && ai.processName != ai.packageName) {
- outError[0] = "cantSaveState applications can not use custom processes";
- }
+ // A heavy-weight application can not be in a custom process.
+ // We can do direct compare because we intern all strings.
+ if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
+ outError[0] = "cantSaveState applications can not use custom processes";
}
}
}
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 6b9c753..2f78161 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
@@ -100,6 +101,13 @@
/** @hide When this is set, the bitmap icon is waiting to be saved. */
public static final int FLAG_ICON_FILE_PENDING_SAVE = 1 << 11;
+ /**
+ * "Shadow" shortcuts are the ones that are restored, but the owner package hasn't been
+ * installed yet.
+ * @hide
+ */
+ public static final int FLAG_SHADOW = 1 << 12;
+
/** @hide */
@IntDef(flag = true,
value = {
@@ -158,6 +166,91 @@
public @interface CloneFlags {}
/**
+ * Shortcut is not disabled.
+ */
+ public static final int DISABLED_REASON_NOT_DISABLED = 0;
+
+ /**
+ * Shortcut has been disabled by the publisher app with the
+ * {@link ShortcutManager#disableShortcuts(List)} API.
+ */
+ public static final int DISABLED_REASON_BY_APP = 1;
+
+ /**
+ * Shortcut has been disabled due to changes to the publisher app. (e.g. a manifest shortcut
+ * no longer exists.)
+ */
+ public static final int DISABLED_REASON_APP_CHANGED = 2;
+
+ /**
+ * A disabled reason that's equal to or bigger than this is due to backup and restore issue.
+ * A shortcut with such a reason wil be visible to the launcher, but not to the publisher.
+ * ({@link #isVisibleToPublisher()} will be false.)
+ */
+ private static final int DISABLED_REASON_RESTORE_ISSUE_START = 100;
+
+ /**
+ * Shortcut has been restored from the previous device, but the publisher app on the current
+ * device is of a lower version. The shortcut will not be usable until the app is upgraded to
+ * the same version or higher.
+ */
+ public static final int DISABLED_REASON_VERSION_LOWER = 100;
+
+ /**
+ * Shortcut has not been restored because the publisher app does not support backup and restore.
+ */
+ public static final int DISABLED_REASON_BACKUP_NOT_SUPPORTED = 101;
+
+ /**
+ * Shortcut has not been restored because the publisher app's signature has changed.
+ */
+ public static final int DISABLED_REASON_SIGNATURE_MISMATCH = 102;
+
+ /**
+ * Shortcut has not been restored for unknown reason.
+ */
+ public static final int DISABLED_REASON_OTHER_RESTORE_ISSUE = 103;
+
+ /** @hide */
+ @IntDef(value = {
+ DISABLED_REASON_NOT_DISABLED,
+ DISABLED_REASON_BY_APP,
+ DISABLED_REASON_APP_CHANGED,
+ DISABLED_REASON_VERSION_LOWER,
+ DISABLED_REASON_BACKUP_NOT_SUPPORTED,
+ DISABLED_REASON_SIGNATURE_MISMATCH,
+ DISABLED_REASON_OTHER_RESTORE_ISSUE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DisabledReason{}
+
+ /** @hide */
+ public static String getDisabledReasonLabel(@DisabledReason int disabledReason) {
+ switch (disabledReason) {
+ case DISABLED_REASON_NOT_DISABLED:
+ return "[Not disabled]";
+ case DISABLED_REASON_BY_APP:
+ return "[Disabled: by app]";
+ case DISABLED_REASON_APP_CHANGED:
+ return "[Disabled: app changed]";
+ case DISABLED_REASON_VERSION_LOWER:
+ return "[Disabled: lower version]";
+ case DISABLED_REASON_BACKUP_NOT_SUPPORTED:
+ return "[Disabled: backup not supported]";
+ case DISABLED_REASON_SIGNATURE_MISMATCH:
+ return "[Disabled: signature mismatch]";
+ case DISABLED_REASON_OTHER_RESTORE_ISSUE:
+ return "[Disabled: unknown restore issue]";
+ }
+ return "[Disabled: unknown reason:" + disabledReason + "]";
+ }
+
+ /** @hide */
+ public static boolean isDisabledForRestoreIssue(@DisabledReason int disabledReason) {
+ return disabledReason >= DISABLED_REASON_RESTORE_ISSUE_START;
+ }
+
+ /**
* Shortcut category for messaging related actions, such as chat.
*/
public static final String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
@@ -240,6 +333,11 @@
private final int mUserId;
+ /** @hide */
+ public static final int VERSION_CODE_UNKNOWN = -1;
+
+ private int mDisabledReason;
+
private ShortcutInfo(Builder b) {
mUserId = b.mContext.getUserId();
@@ -352,6 +450,7 @@
mActivity = source.mActivity;
mFlags = source.mFlags;
mLastChangedTimestamp = source.mLastChangedTimestamp;
+ mDisabledReason = source.mDisabledReason;
// Just always keep it since it's cheep.
mIconResId = source.mIconResId;
@@ -615,13 +714,23 @@
/**
* @hide
+ *
+ * @isUpdating set true if it's "update", as opposed to "replace".
*/
- public void ensureUpdatableWith(ShortcutInfo source) {
+ public void ensureUpdatableWith(ShortcutInfo source, boolean isUpdating) {
+ if (isUpdating) {
+ Preconditions.checkState(isVisibleToPublisher(),
+ "[Framework BUG] Invisible shortcuts can't be updated");
+ }
Preconditions.checkState(mUserId == source.mUserId, "Owner User ID must match");
Preconditions.checkState(mId.equals(source.mId), "ID must match");
Preconditions.checkState(mPackageName.equals(source.mPackageName),
"Package name must match");
- Preconditions.checkState(!isImmutable(), "Target ShortcutInfo is immutable");
+
+ if (isVisibleToPublisher()) {
+ // Don't do this check for restore-blocked shortcuts.
+ Preconditions.checkState(!isImmutable(), "Target ShortcutInfo is immutable");
+ }
}
/**
@@ -638,7 +747,7 @@
* @hide
*/
public void copyNonNullFieldsFrom(ShortcutInfo source) {
- ensureUpdatableWith(source);
+ ensureUpdatableWith(source, /*isUpdating=*/ true);
if (source.mActivity != null) {
mActivity = source.mActivity;
@@ -1169,6 +1278,19 @@
return mDisabledMessageResId;
}
+ /** @hide */
+ public void setDisabledReason(@DisabledReason int reason) {
+ mDisabledReason = reason;
+ }
+
+ /**
+ * Returns why a shortcut has been disabled.
+ */
+ @DisabledReason
+ public int getDisabledReason() {
+ return mDisabledReason;
+ }
+
/**
* Return the shortcut's categories.
*
@@ -1403,6 +1525,21 @@
return hasFlags(FLAG_IMMUTABLE);
}
+ /** @hide */
+ public boolean isDynamicVisible() {
+ return isDynamic() && isVisibleToPublisher();
+ }
+
+ /** @hide */
+ public boolean isPinnedVisible() {
+ return isPinned() && isVisibleToPublisher();
+ }
+
+ /** @hide */
+ public boolean isManifestVisible() {
+ return isDeclaredInManifest() && isVisibleToPublisher();
+ }
+
/**
* Return if a shortcut is immutable, in which case it cannot be modified with any of
* {@link ShortcutManager} APIs.
@@ -1491,6 +1628,18 @@
}
/**
+ * When the system wasn't able to restore a shortcut, it'll still be registered to the system
+ * but disabled, and such shortcuts will not be visible to the publisher. They're still visible
+ * to launchers though.
+ *
+ * @hide
+ */
+ @TestApi
+ public boolean isVisibleToPublisher() {
+ return !isDisabledForRestoreIssue(mDisabledReason);
+ }
+
+ /**
* Return whether a shortcut only contains "key" information only or not. If true, only the
* following fields are available.
* <ul>
@@ -1668,6 +1817,7 @@
mFlags = source.readInt();
mIconResId = source.readInt();
mLastChangedTimestamp = source.readLong();
+ mDisabledReason = source.readInt();
if (source.readInt() == 0) {
return; // key information only.
@@ -1711,6 +1861,7 @@
dest.writeInt(mFlags);
dest.writeInt(mIconResId);
dest.writeLong(mLastChangedTimestamp);
+ dest.writeInt(mDisabledReason);
if (hasKeyFieldsOnly()) {
dest.writeInt(0);
@@ -1808,6 +1959,11 @@
sb.append(", flags=0x");
sb.append(Integer.toHexString(mFlags));
sb.append(" [");
+ if ((mFlags & FLAG_SHADOW) != 0) {
+ // Note the shadow flag isn't actually used anywhere and it's just for dumpsys, so
+ // we don't have an isXxx for this.
+ sb.append("Sdw");
+ }
if (!isEnabled()) {
sb.append("Dis");
}
@@ -1848,7 +2004,9 @@
sb.append("packageName=");
sb.append(mPackageName);
- sb.append(", activity=");
+ addIndentOrComma(sb, indent);
+
+ sb.append("activity=");
sb.append(mActivity);
addIndentOrComma(sb, indent);
@@ -1883,6 +2041,11 @@
addIndentOrComma(sb, indent);
+ sb.append("disabledReason=");
+ sb.append(getDisabledReasonLabel(mDisabledReason));
+
+ addIndentOrComma(sb, indent);
+
sb.append("categories=");
sb.append(mCategories);
@@ -1953,7 +2116,7 @@
CharSequence disabledMessage, int disabledMessageResId, String disabledMessageResName,
Set<String> categories, Intent[] intentsWithExtras, int rank, PersistableBundle extras,
long lastChangedTimestamp,
- int flags, int iconResId, String iconResName, String bitmapPath) {
+ int flags, int iconResId, String iconResName, String bitmapPath, int disabledReason) {
mUserId = userId;
mId = id;
mPackageName = packageName;
@@ -1978,5 +2141,6 @@
mIconResId = iconResId;
mIconResName = iconResName;
mBitmapPath = bitmapPath;
+ mDisabledReason = disabledReason;
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9881927..450ced4 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1911,6 +1911,13 @@
long elapsedRealtimeUs, int which);
/**
+ * Returns the {@link Timer} object that tracks the given screen brightness.
+ *
+ * {@hide}
+ */
+ public abstract Timer getScreenBrightnessTimer(int brightnessBin);
+
+ /**
* Returns the time in microseconds that power save mode has been enabled while the device was
* running on battery.
*
@@ -2019,6 +2026,14 @@
long elapsedRealtimeUs, int which);
/**
+ * Returns the {@link Timer} object that tracks how much the phone has been trying to
+ * acquire a signal.
+ *
+ * {@hide}
+ */
+ public abstract Timer getPhoneSignalScanningTimer();
+
+ /**
* Returns the number of times the phone has entered the given signal strength.
*
* {@hide}
@@ -2026,6 +2041,12 @@
public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
/**
+ * Return the {@link Timer} object used to track the given signal strength's duration and
+ * counts.
+ */
+ protected abstract Timer getPhoneSignalStrengthTimer(int strengthBin);
+
+ /**
* Returns the time in microseconds that the mobile network has been active
* (in a high power state).
*
@@ -2108,6 +2129,11 @@
*/
public abstract int getPhoneDataConnectionCount(int dataType, int which);
+ /**
+ * Returns the {@link Timer} object that tracks the phone's data connection type stats.
+ */
+ public abstract Timer getPhoneDataConnectionTimer(int dataType);
+
public static final int WIFI_SUPPL_STATE_INVALID = 0;
public static final int WIFI_SUPPL_STATE_DISCONNECTED = 1;
public static final int WIFI_SUPPL_STATE_INTERFACE_DISABLED = 2;
@@ -2267,6 +2293,13 @@
public abstract int getWifiStateCount(int wifiState, int which);
/**
+ * Returns the {@link Timer} object that tracks the given WiFi state.
+ *
+ * {@hide}
+ */
+ public abstract Timer getWifiStateTimer(int wifiState);
+
+ /**
* Returns the time in microseconds that the wifi supplicant has been
* in a given state.
*
@@ -2282,6 +2315,13 @@
*/
public abstract int getWifiSupplStateCount(int state, int which);
+ /**
+ * Returns the {@link Timer} object that tracks the given wifi supplicant state.
+ *
+ * {@hide}
+ */
+ public abstract Timer getWifiSupplStateTimer(int state);
+
public static final int NUM_WIFI_SIGNAL_STRENGTH_BINS = 5;
/**
@@ -2301,6 +2341,13 @@
public abstract int getWifiSignalStrengthCount(int strengthBin, int which);
/**
+ * Returns the {@link Timer} object that tracks the given WIFI signal strength.
+ *
+ * {@hide}
+ */
+ public abstract Timer getWifiSignalStrengthTimer(int strengthBin);
+
+ /**
* Returns the time in microseconds that the flashlight has been on while the device was
* running on battery.
*
@@ -2487,13 +2534,13 @@
public abstract int getDischargeAmountScreenOffSinceCharge();
/**
- * Get the amount the battery has discharged while the screen was doze,
+ * Get the amount the battery has discharged while the screen was dozing,
* since the last time power was unplugged.
*/
public abstract int getDischargeAmountScreenDoze();
/**
- * Get the amount the battery has discharged while the screen was doze,
+ * Get the amount the battery has discharged while the screen was dozing,
* since the last time the device was charged.
*/
public abstract int getDischargeAmountScreenDozeSinceCharge();
@@ -2626,20 +2673,20 @@
* micro-Ampere-hours. This will be non-zero only if the device's battery has
* a coulomb counter.
*/
- public abstract long getMahDischargeScreenOff(int which);
+ public abstract long getUahDischargeScreenOff(int which);
/**
* Return the amount of battery discharge while the screen was in doze mode, measured in
* micro-Ampere-hours. This will be non-zero only if the device's battery has
* a coulomb counter.
*/
- public abstract long getMahDischargeScreenDoze(int which);
+ public abstract long getUahDischargeScreenDoze(int which);
/**
* Return the amount of battery discharge measured in micro-Ampere-hours. This will be
* non-zero only if the device's battery has a coulomb counter.
*/
- public abstract long getMahDischarge(int which);
+ public abstract long getUahDischarge(int which);
/**
* Returns the estimated real battery capacity, which may be less than the capacity
@@ -2984,7 +3031,7 @@
final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
/ 1000;
final int count = timer.getCountLocked(which);
- if (totalTime != 0) {
+ if (totalTime != 0 || count != 0) {
dumpLine(pw, uid, category, type, totalTime, count);
}
}
@@ -3000,12 +3047,12 @@
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
*/
private static void dumpTimer(ProtoOutputStream proto, long fieldId,
- Timer timer, long rawRealtime, int which) {
+ Timer timer, long rawRealtimeUs, int which) {
if (timer == null) {
return;
}
// Convert from microseconds to milliseconds with rounding
- final long totalTimeMs = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ final long totalTimeMs = (timer.getTotalTimeLocked(rawRealtimeUs, which) + 500) / 1000;
final int count = timer.getCountLocked(which);
if (totalTimeMs != 0 || count != 0) {
final long token = proto.start(fieldId);
@@ -3191,13 +3238,13 @@
/**
* Checkin server version of dump to produce more compact, computer-readable log.
*
- * NOTE: all times are expressed in 'ms'.
+ * NOTE: all times are expressed in microseconds, unless specified otherwise.
*/
public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid,
boolean wifiOnly) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
- final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
- final long rawRealtimeMs = (rawRealtime + 500) / 1000;
+ final long rawRealtimeMs = SystemClock.elapsedRealtime();
+ final long rawRealtime = rawRealtimeMs * 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
@@ -3220,9 +3267,9 @@
rawRealtime, which);
final int connChanges = getNumConnectivityChange(which);
final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
- final long dischargeCount = getMahDischarge(which);
- final long dischargeScreenOffCount = getMahDischargeScreenOff(which);
- final long dischargeScreenDozeCount = getMahDischargeScreenDoze(which);
+ final long dischargeCount = getUahDischarge(which);
+ final long dischargeScreenOffCount = getUahDischargeScreenOff(which);
+ final long dischargeScreenDozeCount = getUahDischargeScreenDoze(which);
final StringBuilder sb = new StringBuilder(128);
@@ -3460,9 +3507,9 @@
BatteryStatsHelper.makemAh(helper.getComputedPower()),
BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
+ int uid = 0;
for (int i=0; i<sippers.size(); i++) {
final BatterySipper bs = sippers.get(i);
- int uid = 0;
String label;
switch (bs.drainType) {
case IDLE:
@@ -3503,6 +3550,9 @@
case CAMERA:
label = "camera";
break;
+ case MEMORY:
+ label = "memory";
+ break;
default:
label = "???";
}
@@ -3523,6 +3573,7 @@
dumpLine(pw, 0 /* uid */, category, GLOBAL_CPU_FREQ_DATA, sb.toString());
}
+ // Dump stats per UID.
for (int iu = 0; iu < NU; iu++) {
final int uid = uidStats.keyAt(iu);
if (reqUid >= 0 && uid != reqUid) {
@@ -4020,7 +4071,7 @@
pw.println(sb.toString());
}
- final long dischargeCount = getMahDischarge(which);
+ final long dischargeCount = getUahDischarge(which);
if (dischargeCount >= 0) {
sb.setLength(0);
sb.append(prefix);
@@ -4030,7 +4081,7 @@
pw.println(sb.toString());
}
- final long dischargeScreenOffCount = getMahDischargeScreenOff(which);
+ final long dischargeScreenOffCount = getUahDischargeScreenOff(which);
if (dischargeScreenOffCount >= 0) {
sb.setLength(0);
sb.append(prefix);
@@ -4040,7 +4091,7 @@
pw.println(sb.toString());
}
- final long dischargeScreenDozeCount = getMahDischargeScreenDoze(which);
+ final long dischargeScreenDozeCount = getUahDischargeScreenDoze(which);
if (dischargeScreenDozeCount >= 0) {
sb.setLength(0);
sb.append(prefix);
@@ -6038,6 +6089,61 @@
return true;
}
+ private static void dumpDurationSteps(ProtoOutputStream proto, long fieldId,
+ LevelStepTracker steps) {
+ if (steps == null) {
+ return;
+ }
+ int count = steps.mNumStepDurations;
+ long token;
+ for (int i = 0; i < count; ++i) {
+ token = proto.start(fieldId);
+ proto.write(SystemProto.BatteryLevelStep.DURATION_MS, steps.getDurationAt(i));
+ proto.write(SystemProto.BatteryLevelStep.LEVEL, steps.getLevelAt(i));
+
+ final long initMode = steps.getInitModeAt(i);
+ final long modMode = steps.getModModeAt(i);
+
+ int ds = SystemProto.BatteryLevelStep.DS_MIXED;
+ if ((modMode & STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
+ switch ((int) (initMode & STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
+ case Display.STATE_OFF:
+ ds = SystemProto.BatteryLevelStep.DS_OFF;
+ break;
+ case Display.STATE_ON:
+ ds = SystemProto.BatteryLevelStep.DS_ON;
+ break;
+ case Display.STATE_DOZE:
+ ds = SystemProto.BatteryLevelStep.DS_DOZE;
+ break;
+ case Display.STATE_DOZE_SUSPEND:
+ ds = SystemProto.BatteryLevelStep.DS_DOZE_SUSPEND;
+ break;
+ default:
+ ds = SystemProto.BatteryLevelStep.DS_ERROR;
+ break;
+ }
+ }
+ proto.write(SystemProto.BatteryLevelStep.DISPLAY_STATE, ds);
+
+ int psm = SystemProto.BatteryLevelStep.PSM_MIXED;
+ if ((modMode & STEP_LEVEL_MODE_POWER_SAVE) == 0) {
+ psm = (initMode & STEP_LEVEL_MODE_POWER_SAVE) != 0
+ ? SystemProto.BatteryLevelStep.PSM_ON : SystemProto.BatteryLevelStep.PSM_OFF;
+ }
+ proto.write(SystemProto.BatteryLevelStep.POWER_SAVE_MODE, psm);
+
+ int im = SystemProto.BatteryLevelStep.IM_MIXED;
+ if ((modMode & STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
+ im = (initMode & STEP_LEVEL_MODE_DEVICE_IDLE) != 0
+ ? SystemProto.BatteryLevelStep.IM_ON : SystemProto.BatteryLevelStep.IM_OFF;
+ }
+ proto.write(SystemProto.BatteryLevelStep.IDLE_MODE, im);
+
+ proto.end(token);
+ }
+ }
+
public static final int DUMP_CHARGED_ONLY = 1<<1;
public static final int DUMP_DAILY_ONLY = 1<<2;
public static final int DUMP_HISTORY_ONLY = 1<<3;
@@ -6463,7 +6569,7 @@
}
}
- /** Dump batterystats data to a proto. @hide */
+ /** Dump #STATS_SINCE_CHARGED batterystats data to a proto. @hide */
public void dumpProtoLocked(Context context, FileDescriptor fd, List<ApplicationInfo> apps,
int flags, long historyStart) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
@@ -6485,10 +6591,376 @@
if ((flags & (DUMP_HISTORY_ONLY | DUMP_DAILY_ONLY)) == 0) {
// TODO: implement dumpProtoAppsLocked(proto, apps);
- // TODO: implement dumpProtoSystemLocked(proto);
+ dumpProtoSystemLocked(context, proto, (flags & DUMP_DEVICE_WIFI_ONLY) != 0);
}
proto.end(bToken);
proto.flush();
}
+
+ private void dumpProtoSystemLocked(Context context, ProtoOutputStream proto, boolean wifiOnly) {
+ final long sToken = proto.start(BatteryStatsProto.SYSTEM);
+ final long rawUptimeUs = SystemClock.uptimeMillis() * 1000;
+ final long rawRealtimeMs = SystemClock.elapsedRealtime();
+ final long rawRealtimeUs = rawRealtimeMs * 1000;
+ final int which = STATS_SINCE_CHARGED;
+
+ // Battery data (BATTERY_DATA)
+ long token = proto.start(SystemProto.BATTERY);
+ proto.write(SystemProto.Battery.START_CLOCK_TIME_MS, getStartClockTime());
+ proto.write(SystemProto.Battery.START_COUNT, getStartCount());
+ proto.write(SystemProto.Battery.TOTAL_REALTIME_MS,
+ computeRealtime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.TOTAL_UPTIME_MS,
+ computeUptime(rawUptimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.BATTERY_REALTIME_MS,
+ computeBatteryRealtime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.BATTERY_UPTIME_MS,
+ computeBatteryUptime(rawUptimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.SCREEN_OFF_REALTIME_MS,
+ computeBatteryScreenOffRealtime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.SCREEN_OFF_UPTIME_MS,
+ computeBatteryScreenOffUptime(rawUptimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.SCREEN_DOZE_DURATION_MS,
+ getScreenDozeTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.ESTIMATED_BATTERY_CAPACITY_MAH,
+ getEstimatedBatteryCapacity());
+ proto.write(SystemProto.Battery.MIN_LEARNED_BATTERY_CAPACITY_UAH,
+ getMinLearnedBatteryCapacity());
+ proto.write(SystemProto.Battery.MAX_LEARNED_BATTERY_CAPACITY_UAH,
+ getMaxLearnedBatteryCapacity());
+ proto.end(token);
+
+ // Battery discharge (BATTERY_DISCHARGE_DATA)
+ token = proto.start(SystemProto.BATTERY_DISCHARGE);
+ proto.write(SystemProto.BatteryDischarge.LOWER_BOUND_SINCE_CHARGE,
+ getLowDischargeAmountSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.UPPER_BOUND_SINCE_CHARGE,
+ getHighDischargeAmountSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.SCREEN_ON_SINCE_CHARGE,
+ getDischargeAmountScreenOnSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.SCREEN_OFF_SINCE_CHARGE,
+ getDischargeAmountScreenOffSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.SCREEN_DOZE_SINCE_CHARGE,
+ getDischargeAmountScreenDozeSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.TOTAL_MAH,
+ getUahDischarge(which) / 1000);
+ proto.write(SystemProto.BatteryDischarge.TOTAL_MAH_SCREEN_OFF,
+ getUahDischargeScreenOff(which) / 1000);
+ proto.write(SystemProto.BatteryDischarge.TOTAL_MAH_SCREEN_DOZE,
+ getUahDischargeScreenDoze(which) / 1000);
+ proto.end(token);
+
+ // Time remaining
+ long timeRemainingUs = computeChargeTimeRemaining(rawRealtimeUs);
+ if (timeRemainingUs >= 0) {
+ // Charge time remaining (CHARGE_TIME_REMAIN_DATA)
+ proto.write(SystemProto.CHARGE_TIME_REMAINING_MS, timeRemainingUs / 1000);
+ } else {
+ timeRemainingUs = computeBatteryTimeRemaining(rawRealtimeUs);
+ // Discharge time remaining (DISCHARGE_TIME_REMAIN_DATA)
+ if (timeRemainingUs >= 0) {
+ proto.write(SystemProto.DISCHARGE_TIME_REMAINING_MS, timeRemainingUs / 1000);
+ } else {
+ proto.write(SystemProto.DISCHARGE_TIME_REMAINING_MS, -1);
+ }
+ }
+
+ // Charge step (CHARGE_STEP_DATA)
+ dumpDurationSteps(proto, SystemProto.CHARGE_STEP, getChargeLevelStepTracker());
+
+ // Phone data connection (DATA_CONNECTION_TIME_DATA and DATA_CONNECTION_COUNT_DATA)
+ for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; ++i) {
+ token = proto.start(SystemProto.DATA_CONNECTION);
+ proto.write(SystemProto.DataConnection.NAME, i);
+ dumpTimer(proto, SystemProto.DataConnection.TOTAL, getPhoneDataConnectionTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Discharge step (DISCHARGE_STEP_DATA)
+ dumpDurationSteps(proto, SystemProto.DISCHARGE_STEP, getDischargeLevelStepTracker());
+
+ // CPU frequencies (GLOBAL_CPU_FREQ_DATA)
+ final long[] cpuFreqs = getCpuFreqs();
+ if (cpuFreqs != null) {
+ for (long i : cpuFreqs) {
+ proto.write(SystemProto.CPU_FREQUENCY, i);
+ }
+ }
+
+ // Bluetooth controller (GLOBAL_BLUETOOTH_CONTROLLER_DATA)
+ dumpControllerActivityProto(proto, SystemProto.GLOBAL_BLUETOOTH_CONTROLLER,
+ getBluetoothControllerActivity(), which);
+
+ // Modem controller (GLOBAL_MODEM_CONTROLLER_DATA)
+ dumpControllerActivityProto(proto, SystemProto.GLOBAL_MODEM_CONTROLLER,
+ getModemControllerActivity(), which);
+
+ // Global network data (GLOBAL_NETWORK_DATA)
+ token = proto.start(SystemProto.GLOBAL_NETWORK);
+ proto.write(SystemProto.GlobalNetwork.MOBILE_BYTES_RX,
+ getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.MOBILE_BYTES_TX,
+ getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.MOBILE_PACKETS_RX,
+ getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.MOBILE_PACKETS_TX,
+ getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.WIFI_BYTES_RX,
+ getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.WIFI_BYTES_TX,
+ getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.WIFI_PACKETS_RX,
+ getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.WIFI_PACKETS_TX,
+ getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.BT_BYTES_RX,
+ getNetworkActivityBytes(NETWORK_BT_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.BT_BYTES_TX,
+ getNetworkActivityBytes(NETWORK_BT_TX_DATA, which));
+ proto.end(token);
+
+ // Wifi controller (GLOBAL_WIFI_CONTROLLER_DATA)
+ dumpControllerActivityProto(proto, SystemProto.GLOBAL_WIFI_CONTROLLER,
+ getWifiControllerActivity(), which);
+
+
+ // Global wifi (GLOBAL_WIFI_DATA)
+ token = proto.start(SystemProto.GLOBAL_WIFI);
+ proto.write(SystemProto.GlobalWifi.ON_DURATION_MS,
+ getWifiOnTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.GlobalWifi.RUNNING_DURATION_MS,
+ getGlobalWifiRunningTime(rawRealtimeUs, which) / 1000);
+ proto.end(token);
+
+ // Kernel wakelock (KERNEL_WAKELOCK_DATA)
+ final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
+ for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
+ token = proto.start(SystemProto.KERNEL_WAKELOCK);
+ proto.write(SystemProto.KernelWakelock.NAME, ent.getKey());
+ dumpTimer(proto, SystemProto.KernelWakelock.TOTAL, ent.getValue(),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Misc (MISC_DATA)
+ // Calculate wakelock times across all uids.
+ long fullWakeLockTimeTotalUs = 0;
+ long partialWakeLockTimeTotalUs = 0;
+
+ final SparseArray<? extends Uid> uidStats = getUidStats();
+ for (int iu = 0; iu < uidStats.size(); iu++) {
+ final Uid u = uidStats.valueAt(iu);
+
+ final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks =
+ u.getWakelockStats();
+ for (int iw = wakelocks.size() - 1; iw >= 0; --iw) {
+ final Uid.Wakelock wl = wakelocks.valueAt(iw);
+
+ final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
+ if (fullWakeTimer != null) {
+ fullWakeLockTimeTotalUs += fullWakeTimer.getTotalTimeLocked(rawRealtimeUs,
+ which);
+ }
+
+ final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+ if (partialWakeTimer != null) {
+ partialWakeLockTimeTotalUs += partialWakeTimer.getTotalTimeLocked(
+ rawRealtimeUs, which);
+ }
+ }
+ }
+ token = proto.start(SystemProto.MISC);
+ proto.write(SystemProto.Misc.SCREEN_ON_DURATION_MS,
+ getScreenOnTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.PHONE_ON_DURATION_MS,
+ getPhoneOnTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.FULL_WAKELOCK_TOTAL_DURATION_MS,
+ fullWakeLockTimeTotalUs / 1000);
+ proto.write(SystemProto.Misc.PARTIAL_WAKELOCK_TOTAL_DURATION_MS,
+ partialWakeLockTimeTotalUs / 1000);
+ proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_DURATION_MS,
+ getMobileRadioActiveTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_ADJUSTED_TIME_MS,
+ getMobileRadioActiveAdjustedTime(which) / 1000);
+ proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_COUNT,
+ getMobileRadioActiveCount(which));
+ proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_UNKNOWN_DURATION_MS,
+ getMobileRadioActiveUnknownTime(which) / 1000);
+ proto.write(SystemProto.Misc.INTERACTIVE_DURATION_MS,
+ getInteractiveTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.BATTERY_SAVER_MODE_ENABLED_DURATION_MS,
+ getPowerSaveModeEnabledTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.NUM_CONNECTIVITY_CHANGES,
+ getNumConnectivityChange(which));
+ proto.write(SystemProto.Misc.DEEP_DOZE_ENABLED_DURATION_MS,
+ getDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP, rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.DEEP_DOZE_COUNT,
+ getDeviceIdleModeCount(DEVICE_IDLE_MODE_DEEP, which));
+ proto.write(SystemProto.Misc.DEEP_DOZE_IDLING_DURATION_MS,
+ getDeviceIdlingTime(DEVICE_IDLE_MODE_DEEP, rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.DEEP_DOZE_IDLING_COUNT,
+ getDeviceIdlingCount(DEVICE_IDLE_MODE_DEEP, which));
+ proto.write(SystemProto.Misc.LONGEST_DEEP_DOZE_DURATION_MS,
+ getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP));
+ proto.write(SystemProto.Misc.LIGHT_DOZE_ENABLED_DURATION_MS,
+ getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT, rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.LIGHT_DOZE_COUNT,
+ getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which));
+ proto.write(SystemProto.Misc.LIGHT_DOZE_IDLING_DURATION_MS,
+ getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT, rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.LIGHT_DOZE_IDLING_COUNT,
+ getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which));
+ proto.write(SystemProto.Misc.LONGEST_LIGHT_DOZE_DURATION_MS,
+ getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT));
+ proto.end(token);
+
+ final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
+ helper.create(this);
+ helper.refreshStats(which, UserHandle.USER_ALL);
+
+ // Power use item (POWER_USE_ITEM_DATA)
+ final List<BatterySipper> sippers = helper.getUsageList();
+ if (sippers != null) {
+ for (int i = 0; i < sippers.size(); ++i) {
+ final BatterySipper bs = sippers.get(i);
+ int n = SystemProto.PowerUseItem.UNKNOWN_SIPPER;
+ int uid = 0;
+ switch (bs.drainType) {
+ case IDLE:
+ n = SystemProto.PowerUseItem.IDLE;
+ break;
+ case CELL:
+ n = SystemProto.PowerUseItem.CELL;
+ break;
+ case PHONE:
+ n = SystemProto.PowerUseItem.PHONE;
+ break;
+ case WIFI:
+ n = SystemProto.PowerUseItem.WIFI;
+ break;
+ case BLUETOOTH:
+ n = SystemProto.PowerUseItem.BLUETOOTH;
+ break;
+ case SCREEN:
+ n = SystemProto.PowerUseItem.SCREEN;
+ break;
+ case FLASHLIGHT:
+ n = SystemProto.PowerUseItem.FLASHLIGHT;
+ break;
+ case APP:
+ // dumpProtoAppLocked will handle this.
+ continue;
+ case USER:
+ n = SystemProto.PowerUseItem.USER;
+ uid = UserHandle.getUid(bs.userId, 0);
+ break;
+ case UNACCOUNTED:
+ n = SystemProto.PowerUseItem.UNACCOUNTED;
+ break;
+ case OVERCOUNTED:
+ n = SystemProto.PowerUseItem.OVERCOUNTED;
+ break;
+ case CAMERA:
+ n = SystemProto.PowerUseItem.CAMERA;
+ break;
+ case MEMORY:
+ n = SystemProto.PowerUseItem.MEMORY;
+ break;
+ }
+ token = proto.start(SystemProto.POWER_USE_ITEM);
+ proto.write(SystemProto.PowerUseItem.NAME, n);
+ proto.write(SystemProto.PowerUseItem.UID, uid);
+ proto.write(SystemProto.PowerUseItem.COMPUTED_POWER_MAH, bs.totalPowerMah);
+ proto.write(SystemProto.PowerUseItem.SHOULD_HIDE, bs.shouldHide);
+ proto.write(SystemProto.PowerUseItem.SCREEN_POWER_MAH, bs.screenPowerMah);
+ proto.write(SystemProto.PowerUseItem.PROPORTIONAL_SMEAR_MAH,
+ bs.proportionalSmearMah);
+ proto.end(token);
+ }
+ }
+
+ // Power use summary (POWER_USE_SUMMARY_DATA)
+ token = proto.start(SystemProto.POWER_USE_SUMMARY);
+ proto.write(SystemProto.PowerUseSummary.BATTERY_CAPACITY_MAH,
+ helper.getPowerProfile().getBatteryCapacity());
+ proto.write(SystemProto.PowerUseSummary.COMPUTED_POWER_MAH, helper.getComputedPower());
+ proto.write(SystemProto.PowerUseSummary.MIN_DRAINED_POWER_MAH, helper.getMinDrainedPower());
+ proto.write(SystemProto.PowerUseSummary.MAX_DRAINED_POWER_MAH, helper.getMaxDrainedPower());
+ proto.end(token);
+
+ // RPM stats (RESOURCE_POWER_MANAGER_DATA)
+ final Map<String, ? extends Timer> rpmStats = getRpmStats();
+ final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats();
+ for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) {
+ token = proto.start(SystemProto.RESOURCE_POWER_MANAGER);
+ proto.write(SystemProto.ResourcePowerManager.NAME, ent.getKey());
+ dumpTimer(proto, SystemProto.ResourcePowerManager.TOTAL,
+ ent.getValue(), rawRealtimeUs, which);
+ dumpTimer(proto, SystemProto.ResourcePowerManager.SCREEN_OFF,
+ screenOffRpmStats.get(ent.getKey()), rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Screen brightness (SCREEN_BRIGHTNESS_DATA)
+ for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; ++i) {
+ token = proto.start(SystemProto.SCREEN_BRIGHTNESS);
+ proto.write(SystemProto.ScreenBrightness.NAME, i);
+ dumpTimer(proto, SystemProto.ScreenBrightness.TOTAL, getScreenBrightnessTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Signal scanning time (SIGNAL_SCANNING_TIME_DATA)
+ dumpTimer(proto, SystemProto.SIGNAL_SCANNING, getPhoneSignalScanningTimer(), rawRealtimeUs,
+ which);
+
+ // Phone signal strength (SIGNAL_STRENGTH_TIME_DATA and SIGNAL_STRENGTH_COUNT_DATA)
+ for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; ++i) {
+ token = proto.start(SystemProto.PHONE_SIGNAL_STRENGTH);
+ proto.write(SystemProto.PhoneSignalStrength.NAME, i);
+ dumpTimer(proto, SystemProto.PhoneSignalStrength.TOTAL, getPhoneSignalStrengthTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Wakeup reasons (WAKEUP_REASON_DATA)
+ final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
+ for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
+ token = proto.start(SystemProto.WAKEUP_REASON);
+ proto.write(SystemProto.WakeupReason.NAME, ent.getKey());
+ dumpTimer(proto, SystemProto.WakeupReason.TOTAL, ent.getValue(), rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Wifi signal strength (WIFI_SIGNAL_STRENGTH_TIME_DATA and WIFI_SIGNAL_STRENGTH_COUNT_DATA)
+ for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; ++i) {
+ token = proto.start(SystemProto.WIFI_SIGNAL_STRENGTH);
+ proto.write(SystemProto.WifiSignalStrength.NAME, i);
+ dumpTimer(proto, SystemProto.WifiSignalStrength.TOTAL, getWifiSignalStrengthTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Wifi state (WIFI_STATE_TIME_DATA and WIFI_STATE_COUNT_DATA)
+ for (int i = 0; i < NUM_WIFI_STATES; ++i) {
+ token = proto.start(SystemProto.WIFI_STATE);
+ proto.write(SystemProto.WifiState.NAME, i);
+ dumpTimer(proto, SystemProto.WifiState.TOTAL, getWifiStateTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Wifi supplicant state (WIFI_SUPPL_STATE_TIME_DATA and WIFI_SUPPL_STATE_COUNT_DATA)
+ for (int i = 0; i < NUM_WIFI_SUPPL_STATES; ++i) {
+ token = proto.start(SystemProto.WIFI_SUPPLICANT_STATE);
+ proto.write(SystemProto.WifiSupplicantState.NAME, i);
+ dumpTimer(proto, SystemProto.WifiSupplicantState.TOTAL, getWifiSupplStateTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ proto.end(sToken);
+ }
}
diff --git a/core/java/android/os/PatternMatcher.java b/core/java/android/os/PatternMatcher.java
index 1f3a1e6..76b2142 100644
--- a/core/java/android/os/PatternMatcher.java
+++ b/core/java/android/os/PatternMatcher.java
@@ -16,7 +16,7 @@
package android.os;
-import android.util.Log;
+import android.util.proto.ProtoOutputStream;
import java.util.Arrays;
@@ -131,7 +131,17 @@
}
return "PatternMatcher{" + type + mPattern + "}";
}
-
+
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ proto.write(PatternMatcherProto.PATTERN, mPattern);
+ proto.write(PatternMatcherProto.TYPE, mType);
+ // PatternMatcherProto.PARSED_PATTERN is too much to dump, but the field is reserved to
+ // match the current data structure.
+ proto.end(token);
+ }
+
public int describeContents() {
return 0;
}
@@ -141,7 +151,7 @@
dest.writeInt(mType);
dest.writeIntArray(mParsedPattern);
}
-
+
public PatternMatcher(Parcel src) {
mPattern = src.readString();
mType = src.readInt();
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index ee8eed1..3d2e1d1 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -206,8 +206,7 @@
try {
mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
.getAudioAttributes())
- .setFlags(AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
- AudioAttributes.FLAG_BYPASS_MUTE)
+ .setFlags(AudioAttributes.FLAG_BYPASS_MUTE)
.build());
mRingtone.play();
} catch (Throwable e) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a062db4..53e8881 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6792,14 +6792,6 @@
"lock_screen_show_notifications";
/**
- * This preference stores the last stack active task time for each user, which affects what
- * tasks will be visible in Overview.
- * @hide
- */
- public static final String OVERVIEW_LAST_STACK_ACTIVE_TIME =
- "overview_last_stack_active_time";
-
- /**
* List of TV inputs that are currently hidden. This is a string
* containing the IDs of all hidden TV inputs. Each ID is encoded by
* {@link android.net.Uri#encode(String)} and separated by ':'.
@@ -9575,6 +9567,22 @@
public static final String DEVICE_POLICY_CONSTANTS = "device_policy_constants";
/**
+ * TextClassifier specific settings.
+ * This is encoded as a key=value list, separated by commas. Ex:
+ *
+ * <pre>
+ * smart_selection_dark_launch (boolean)
+ * smart_selection_enabled_for_edit_text (boolean)
+ * </pre>
+ *
+ * <p>
+ * Type: string
+ * @hide
+ * see also android.view.textclassifier.TextClassifierConstants
+ */
+ public static final String TEXT_CLASSIFIER_CONSTANTS = "text_classifier_constants";
+
+ /**
* Get the key that retrieves a bluetooth headset's priority.
* @hide
*/
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 2e59f6c..953501c 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -65,7 +65,7 @@
* <li>The service replies through {@link FillCallback#onSuccess(FillResponse)}.
* <li>The Android System calls {@link #onDisconnected()} and unbinds from the
* {@code AutofillService}.
- * <li>The Android System displays an UI affordance with the options sent by the service.
+ * <li>The Android System displays an autofill UI with the options sent by the service.
* <li>The user picks an option.
* <li>The proper views are autofilled.
* </ol>
@@ -365,6 +365,81 @@
* <p><b>Note:</b> The autofill service could also whitelist well-known browser apps and skip the
* verifications above, as long as the service can verify the authenticity of the browser app by
* checking its signing certificate.
+ *
+ * <a name="MultipleStepsSave"></a>
+ * <h3>Saving when data is split in multiple screens</h3>
+ *
+ * Apps often split the user data in multiple screens in the same activity, specially in
+ * activities used to create a new user account. For example, the first screen asks for a username,
+ * and if the username is available, it moves to a second screen, which asks for a password.
+ *
+ * <p>It's tricky to handle save for autofill in these situations, because the autofill service must
+ * wait until the user enters both fields before the autofill save UI can be shown. But it can be
+ * done by following the steps below:
+ *
+ * <ol>
+ * <li>In the first
+ * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback) fill request}, the service
+ * adds a {@link FillResponse.Builder#setClientState(android.os.Bundle) client state bundle} in
+ * the response, containing the autofill ids of the partial fields present in the screen.
+ * <li>In the second
+ * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback) fill request}, the service
+ * retrieves the {@link FillRequest#getClientState() client state bundle}, gets the autofill ids
+ * set in the previous request from the client state, and adds these ids and the
+ * {@link SaveInfo#FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} to the {@link SaveInfo} used in the second
+ * response.
+ * <li>In the {@link #onSaveRequest(SaveRequest, SaveCallback) save request}, the service uses the
+ * proper {@link FillContext fill contexts} to get the value of each field (there is one fill
+ * context per fill request).
+ * </ol>
+ *
+ * <p>For example, in an app that uses 2 steps for the username and password fields, the workflow
+ * would be:
+ * <pre class="prettyprint">
+ * // On first fill request
+ * AutofillId usernameId = // parse from AssistStructure;
+ * Bundle clientState = new Bundle();
+ * clientState.putParcelable("usernameId", usernameId);
+ * fillCallback.onSuccess(
+ * new FillResponse.Builder()
+ * .setClientState(clientState)
+ * .setSaveInfo(new SaveInfo
+ * .Builder(SaveInfo.SAVE_DATA_TYPE_USERNAME, new AutofillId[] {usernameId})
+ * .build())
+ * .build());
+ *
+ * // On second fill request
+ * Bundle clientState = fillRequest.getClientState();
+ * AutofillId usernameId = clientState.getParcelable("usernameId");
+ * AutofillId passwordId = // parse from AssistStructure
+ * clientState.putParcelable("passwordId", passwordId);
+ * fillCallback.onSuccess(
+ * new FillResponse.Builder()
+ * .setClientState(clientState)
+ * .setSaveInfo(new SaveInfo
+ * .Builder(SaveInfo.SAVE_DATA_TYPE_USERNAME | SaveInfo.SAVE_DATA_TYPE_PASSWORD,
+ * new AutofillId[] {usernameId, passwordId})
+ * .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
+ * .build())
+ * .build());
+ *
+ * // On save request
+ * Bundle clientState = saveRequest.getClientState();
+ * AutofillId usernameId = clientState.getParcelable("usernameId");
+ * AutofillId passwordId = clientState.getParcelable("passwordId");
+ * List<FillContext> fillContexts = saveRequest.getFillContexts();
+ *
+ * FillContext usernameContext = fillContexts.get(0);
+ * ViewNode usernameNode = findNodeByAutofillId(usernameContext.getStructure(), usernameId);
+ * AutofillValue username = usernameNode.getAutofillValue().getTextValue().toString();
+ *
+ * FillContext passwordContext = fillContexts.get(1);
+ * ViewNode passwordNode = findNodeByAutofillId(passwordContext.getStructure(), passwordId);
+ * AutofillValue password = passwordNode.getAutofillValue().getTextValue().toString();
+ *
+ * save(username, password);
+ *
+ * </pre>
*/
public abstract class AutofillService extends Service {
private static final String TAG = "AutofillService";
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 1b9240c..fde2416 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -68,7 +68,7 @@
* .build();
* </pre>
*
- * <p>The save type flags are used to display the appropriate strings in the save UI affordance.
+ * <p>The save type flags are used to display the appropriate strings in the autofill save UI.
* You can pass multiple values, but try to keep it short if possible. In the above example, just
* {@code SaveInfo.SAVE_DATA_TYPE_PASSWORD} would be enough.
*
@@ -103,13 +103,17 @@
* .build();
* </pre>
*
+ * <a name="TriggeringSaveRequest"></a>
+ * <h3>Triggering a save request</h3>
+ *
* <p>The {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} can be triggered after
* any of the following events:
* <ul>
* <li>The {@link Activity} finishes.
- * <li>The app explicitly called {@link AutofillManager#commit()}.
- * <li>All required views became invisible (if the {@link SaveInfo} was created with the
+ * <li>The app explicitly calls {@link AutofillManager#commit()}.
+ * <li>All required views become invisible (if the {@link SaveInfo} was created with the
* {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} flag).
+ * <li>The user clicks a specific view (defined by {@link Builder#setTriggerId(AutofillId)}.
* </ul>
*
* <p>But it is only triggered when all conditions below are met:
@@ -123,10 +127,13 @@
* <li>There is no {@link Dataset} in the last {@link FillResponse} that completely matches the
* screen state (i.e., all required and optional fields in the dataset have the same value as
* the fields in the screen).
- * <li>The user explicitly tapped the UI affordance asking to save data for autofill.
+ * <li>The user explicitly tapped the autofill save UI asking to save data for autofill.
* </ul>
*
- * <p>The service can also customize some aspects of the save UI affordance:
+ * <a name="CustomizingSaveUI"></a>
+ * <h3>Customizing the autofill save UI</h3>
+ *
+ * <p>The service can also customize some aspects of the autofill save UI:
* <ul>
* <li>Add a simple subtitle by calling {@link Builder#setDescription(CharSequence)}.
* <li>Add a customized subtitle by calling
@@ -212,16 +219,25 @@
@interface SaveDataType{}
/**
- * Usually {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
- * is called once the {@link Activity} finishes. If this flag is set it is called once all
- * saved views become invisible.
+ * Usually, a save request is only automatically <a href="#TriggeringSaveRequest">triggered</a>
+ * once the {@link Activity} finishes. If this flag is set, it is triggered once all saved views
+ * become invisible.
*/
public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 0x1;
+ /**
+ * By default, a save request is automatically <a href="#TriggeringSaveRequest">triggered</a>
+ * once the {@link Activity} finishes. If this flag is set, finishing the activity doesn't
+ * trigger a save request.
+ *
+ * <p>This flag is typically used in conjunction with {@link Builder#setTriggerId(AutofillId)}.
+ */
+ public static final int FLAG_DONT_SAVE_ON_FINISH = 0x2;
+
/** @hide */
@IntDef(
flag = true,
- value = {FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE})
+ value = {FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE, FLAG_DONT_SAVE_ON_FINISH})
@Retention(RetentionPolicy.SOURCE)
@interface SaveInfoFlags{}
@@ -236,6 +252,7 @@
private final InternalValidator mValidator;
private final InternalSanitizer[] mSanitizerKeys;
private final AutofillId[][] mSanitizerValues;
+ private final AutofillId mTriggerId;
private SaveInfo(Builder builder) {
mType = builder.mType;
@@ -259,6 +276,7 @@
mSanitizerValues[i] = builder.mSanitizers.valueAt(i);
}
}
+ mTriggerId = builder.mTriggerId;
}
/** @hide */
@@ -320,6 +338,12 @@
return mSanitizerValues;
}
+ /** @hide */
+ @Nullable
+ public AutofillId getTriggerId() {
+ return mTriggerId;
+ }
+
/**
* A builder for {@link SaveInfo} objects.
*/
@@ -338,6 +362,7 @@
private ArrayMap<InternalSanitizer, AutofillId[]> mSanitizers;
// Set used to validate against duplicate ids.
private ArraySet<AutofillId> mSanitizerIds;
+ private AutofillId mTriggerId;
/**
* Creates a new builder.
@@ -394,13 +419,15 @@
/**
* Sets flags changing the save behavior.
*
- * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} or {@code 0}.
+ * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE},
+ * {@link #FLAG_DONT_SAVE_ON_FINISH}, or {@code 0}.
* @return This builder.
*/
public @NonNull Builder setFlags(@SaveInfoFlags int flags) {
throwIfDestroyed();
- mFlags = Preconditions.checkFlagsArgument(flags, FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE);
+ mFlags = Preconditions.checkFlagsArgument(flags,
+ FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE | FLAG_DONT_SAVE_ON_FINISH);
return this;
}
@@ -493,8 +520,8 @@
}
/**
- * Sets an object used to validate the user input - if the input is not valid, the Save UI
- * affordance is not shown.
+ * Sets an object used to validate the user input - if the input is not valid, the
+ * autofill save UI is not shown.
*
* <p>Typically used to validate credit card numbers. Examples:
*
@@ -520,7 +547,7 @@
* );
* </pre>
*
- * <p><b>NOTE: </b>the example above is just for illustrative purposes; the same validator
+ * <p><b>Note:</b> the example above is just for illustrative purposes; the same validator
* could be created using a single regex for the {@code OR} part:
*
* <pre class="prettyprint">
@@ -615,6 +642,27 @@
return this;
}
+ /**
+ * Explicitly defines the view that should commit the autofill context when clicked.
+ *
+ * <p>Usually, the save request is only automatically
+ * <a href="#TriggeringSaveRequest">triggered</a> after the activity is
+ * finished or all relevant views become invisible, but there are scenarios where the
+ * autofill context is automatically commited too late
+ * —for example, when the activity manually clears the autofillable views when a
+ * button is tapped. This method can be used to trigger the autofill save UI earlier in
+ * these scenarios.
+ *
+ * <p><b>Note:</b> This method should only be used in scenarios where the automatic workflow
+ * is not enough, otherwise it could trigger the autofill save UI when it should not—
+ * for example, when the user entered invalid credentials for the autofillable views.
+ */
+ public @NonNull Builder setTriggerId(@NonNull AutofillId id) {
+ throwIfDestroyed();
+ mTriggerId = Preconditions.checkNotNull(id);
+ return this;
+ }
+
/**
* Builds a new {@link SaveInfo} instance.
*
@@ -652,13 +700,14 @@
.append(", description=").append(mDescription)
.append(DebugUtils.flagsToString(SaveInfo.class, "NEGATIVE_BUTTON_STYLE_",
mNegativeButtonStyle))
- .append(", mFlags=").append(mFlags)
- .append(", mCustomDescription=").append(mCustomDescription)
- .append(", validation=").append(mValidator)
+ .append(", flags=").append(mFlags)
+ .append(", customDescription=").append(mCustomDescription)
+ .append(", validator=").append(mValidator)
.append(", sanitizerKeys=")
.append(mSanitizerKeys == null ? "N/A:" : mSanitizerKeys.length)
.append(", sanitizerValues=")
.append(mSanitizerValues == null ? "N/A:" : mSanitizerValues.length)
+ .append(", triggerId=").append(mTriggerId)
.append("]").toString();
}
@@ -687,6 +736,7 @@
parcel.writeParcelableArray(mSanitizerValues[i], flags);
}
}
+ parcel.writeParcelable(mTriggerId, flags);
parcel.writeInt(mFlags);
}
@@ -727,6 +777,10 @@
builder.addSanitizer(sanitizers[i], autofillIds);
}
}
+ final AutofillId triggerId = parcel.readParcelable(null);
+ if (triggerId != null) {
+ builder.setTriggerId(triggerId);
+ }
builder.setFlags(parcel.readInt());
return builder.build();
}
diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java
index 65fdb5c..f53967b 100644
--- a/core/java/android/service/autofill/SaveRequest.java
+++ b/core/java/android/service/autofill/SaveRequest.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
-import android.os.CancellationSignal;
import android.os.Parcel;
import android.os.Parcelable;
@@ -60,9 +59,14 @@
}
/**
- * Gets the extra client state returned from the last {@link
- * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)}
- * fill request}.
+ * Gets the latest client state extra returned from the service.
+ *
+ * <p><b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, only client state
+ * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} where considered. On
+ * Android {@link android.os.Build.VERSION_CODES#P} and higher, bundles set in the result of
+ * an authenticated request through the
+ * {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE} extra are
+ * also considered (and take precedence when set).
*
* @return The client state.
*/
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 7bec898..c5615ae 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -76,10 +76,13 @@
private static final int DAY_MINUTES = 24 * 60;
private static final int ZERO_VALUE_MS = 10 * SECONDS_MS;
- private static final boolean DEFAULT_ALLOW_CALLS = true;
+ // Default allow categories set in readXml() from default_zen_mode_config.xml, fallback values:
+ private static final boolean DEFAULT_ALLOW_ALARMS = true;
+ private static final boolean DEFAULT_ALLOW_MEDIA_SYSTEM_OTHER = true;
+ private static final boolean DEFAULT_ALLOW_CALLS = false;
private static final boolean DEFAULT_ALLOW_MESSAGES = false;
- private static final boolean DEFAULT_ALLOW_REMINDERS = true;
- private static final boolean DEFAULT_ALLOW_EVENTS = true;
+ private static final boolean DEFAULT_ALLOW_REMINDERS = false;
+ private static final boolean DEFAULT_ALLOW_EVENTS = false;
private static final boolean DEFAULT_ALLOW_REPEAT_CALLERS = false;
private static final boolean DEFAULT_ALLOW_SCREEN_OFF = true;
private static final boolean DEFAULT_ALLOW_SCREEN_ON = true;
@@ -89,6 +92,8 @@
private static final String ZEN_ATT_VERSION = "version";
private static final String ZEN_ATT_USER = "user";
private static final String ALLOW_TAG = "allow";
+ private static final String ALLOW_ATT_ALARMS = "alarms";
+ private static final String ALLOW_ATT_MEDIA = "media_system_other";
private static final String ALLOW_ATT_CALLS = "calls";
private static final String ALLOW_ATT_REPEAT_CALLERS = "repeatCallers";
private static final String ALLOW_ATT_MESSAGES = "messages";
@@ -100,8 +105,6 @@
private static final String ALLOW_ATT_SCREEN_OFF = "visualScreenOff";
private static final String ALLOW_ATT_SCREEN_ON = "visualScreenOn";
- private static final String CONDITION_TAG = "condition";
- private static final String CONDITION_ATT_COMPONENT = "component";
private static final String CONDITION_ATT_ID = "id";
private static final String CONDITION_ATT_SUMMARY = "summary";
private static final String CONDITION_ATT_LINE1 = "line1";
@@ -123,6 +126,8 @@
private static final String RULE_ATT_CREATION_TIME = "creationTime";
private static final String RULE_ATT_ENABLER = "enabler";
+ public boolean allowAlarms = DEFAULT_ALLOW_ALARMS;
+ public boolean allowMediaSystemOther = DEFAULT_ALLOW_MEDIA_SYSTEM_OTHER;
public boolean allowCalls = DEFAULT_ALLOW_CALLS;
public boolean allowRepeatCallers = DEFAULT_ALLOW_REPEAT_CALLERS;
public boolean allowMessages = DEFAULT_ALLOW_MESSAGES;
@@ -161,6 +166,8 @@
}
allowWhenScreenOff = source.readInt() == 1;
allowWhenScreenOn = source.readInt() == 1;
+ allowAlarms = source.readInt() == 1;
+ allowMediaSystemOther = source.readInt() == 1;
}
@Override
@@ -190,19 +197,23 @@
}
dest.writeInt(allowWhenScreenOff ? 1 : 0);
dest.writeInt(allowWhenScreenOn ? 1 : 0);
+ dest.writeInt(allowAlarms ? 1 : 0);
+ dest.writeInt(allowMediaSystemOther ? 1 : 0);
}
@Override
public String toString() {
return new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[')
.append("user=").append(user)
+ .append(",allowAlarms=").append(allowAlarms)
+ .append(",allowMediaSystemOther=").append(allowMediaSystemOther)
+ .append(",allowReminders=").append(allowReminders)
+ .append(",allowEvents=").append(allowEvents)
.append(",allowCalls=").append(allowCalls)
.append(",allowRepeatCallers=").append(allowRepeatCallers)
.append(",allowMessages=").append(allowMessages)
.append(",allowCallsFrom=").append(sourceToString(allowCallsFrom))
.append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom))
- .append(",allowReminders=").append(allowReminders)
- .append(",allowEvents=").append(allowEvents)
.append(",allowWhenScreenOff=").append(allowWhenScreenOff)
.append(",allowWhenScreenOn=").append(allowWhenScreenOn)
.append(",automaticRules=").append(automaticRules)
@@ -218,9 +229,21 @@
if (user != to.user) {
d.addLine("user", user, to.user);
}
+ if (allowAlarms != to.allowAlarms) {
+ d.addLine("allowAlarms", allowAlarms, to.allowAlarms);
+ }
+ if (allowMediaSystemOther != to.allowMediaSystemOther) {
+ d.addLine("allowMediaSystemOther", allowMediaSystemOther, to.allowMediaSystemOther);
+ }
if (allowCalls != to.allowCalls) {
d.addLine("allowCalls", allowCalls, to.allowCalls);
}
+ if (allowReminders != to.allowReminders) {
+ d.addLine("allowReminders", allowReminders, to.allowReminders);
+ }
+ if (allowEvents != to.allowEvents) {
+ d.addLine("allowEvents", allowEvents, to.allowEvents);
+ }
if (allowRepeatCallers != to.allowRepeatCallers) {
d.addLine("allowRepeatCallers", allowRepeatCallers, to.allowRepeatCallers);
}
@@ -233,12 +256,6 @@
if (allowMessagesFrom != to.allowMessagesFrom) {
d.addLine("allowMessagesFrom", allowMessagesFrom, to.allowMessagesFrom);
}
- if (allowReminders != to.allowReminders) {
- d.addLine("allowReminders", allowReminders, to.allowReminders);
- }
- if (allowEvents != to.allowEvents) {
- d.addLine("allowEvents", allowEvents, to.allowEvents);
- }
if (allowWhenScreenOff != to.allowWhenScreenOff) {
d.addLine("allowWhenScreenOff", allowWhenScreenOff, to.allowWhenScreenOff);
}
@@ -335,7 +352,9 @@
if (!(o instanceof ZenModeConfig)) return false;
if (o == this) return true;
final ZenModeConfig other = (ZenModeConfig) o;
- return other.allowCalls == allowCalls
+ return other.allowAlarms == allowAlarms
+ && other.allowMediaSystemOther == allowMediaSystemOther
+ && other.allowCalls == allowCalls
&& other.allowRepeatCallers == allowRepeatCallers
&& other.allowMessages == allowMessages
&& other.allowCallsFrom == allowCallsFrom
@@ -351,10 +370,10 @@
@Override
public int hashCode() {
- return Objects.hash(allowCalls, allowRepeatCallers, allowMessages, allowCallsFrom,
- allowMessagesFrom, allowReminders, allowEvents, allowWhenScreenOff,
- allowWhenScreenOn,
- user, automaticRules, manualRule);
+ return Objects.hash(allowAlarms, allowMediaSystemOther, allowCalls,
+ allowRepeatCallers, allowMessages,
+ allowCallsFrom, allowMessagesFrom, allowReminders, allowEvents,
+ allowWhenScreenOff, allowWhenScreenOn, user, automaticRules, manualRule);
}
private static String toDayList(int[] days) {
@@ -413,10 +432,12 @@
}
if (type == XmlPullParser.START_TAG) {
if (ALLOW_TAG.equals(tag)) {
- rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false);
+ rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS,
+ DEFAULT_ALLOW_CALLS);
rt.allowRepeatCallers = safeBoolean(parser, ALLOW_ATT_REPEAT_CALLERS,
DEFAULT_ALLOW_REPEAT_CALLERS);
- rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES, false);
+ rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES,
+ DEFAULT_ALLOW_MESSAGES);
rt.allowReminders = safeBoolean(parser, ALLOW_ATT_REMINDERS,
DEFAULT_ALLOW_REMINDERS);
rt.allowEvents = safeBoolean(parser, ALLOW_ATT_EVENTS, DEFAULT_ALLOW_EVENTS);
@@ -438,6 +459,9 @@
safeBoolean(parser, ALLOW_ATT_SCREEN_OFF, DEFAULT_ALLOW_SCREEN_OFF);
rt.allowWhenScreenOn =
safeBoolean(parser, ALLOW_ATT_SCREEN_ON, DEFAULT_ALLOW_SCREEN_ON);
+ rt.allowAlarms = safeBoolean(parser, ALLOW_ATT_ALARMS, DEFAULT_ALLOW_ALARMS);
+ rt.allowMediaSystemOther = safeBoolean(parser, ALLOW_ATT_MEDIA,
+ DEFAULT_ALLOW_MEDIA_SYSTEM_OTHER);
} else if (MANUAL_TAG.equals(tag)) {
rt.manualRule = readRuleXml(parser);
} else if (AUTOMATIC_TAG.equals(tag)) {
@@ -468,6 +492,8 @@
out.attribute(null, ALLOW_ATT_MESSAGES_FROM, Integer.toString(allowMessagesFrom));
out.attribute(null, ALLOW_ATT_SCREEN_OFF, Boolean.toString(allowWhenScreenOff));
out.attribute(null, ALLOW_ATT_SCREEN_ON, Boolean.toString(allowWhenScreenOn));
+ out.attribute(null, ALLOW_ATT_ALARMS, Boolean.toString(allowAlarms));
+ out.attribute(null, ALLOW_ATT_ALARMS, Boolean.toString(allowMediaSystemOther));
out.endTag(null, ALLOW_TAG);
if (manualRule != null) {
@@ -654,6 +680,12 @@
if (!allowWhenScreenOn) {
suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_SCREEN_ON;
}
+ if (allowAlarms) {
+ priorityCategories |= Policy.PRIORITY_CATEGORY_ALARMS;
+ }
+ if (allowMediaSystemOther) {
+ priorityCategories |= Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER;
+ }
priorityCallSenders = sourceToPrioritySenders(allowCallsFrom, priorityCallSenders);
priorityMessageSenders = sourceToPrioritySenders(allowMessagesFrom, priorityMessageSenders);
return new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders,
@@ -680,10 +712,13 @@
public void applyNotificationPolicy(Policy policy) {
if (policy == null) return;
- allowCalls = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_CALLS) != 0;
- allowMessages = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_MESSAGES) != 0;
+ allowAlarms = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_ALARMS) != 0;
+ allowMediaSystemOther = (policy.priorityCategories
+ & Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0;
allowEvents = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_EVENTS) != 0;
allowReminders = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_REMINDERS) != 0;
+ allowCalls = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_CALLS) != 0;
+ allowMessages = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_MESSAGES) != 0;
allowRepeatCallers = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_REPEAT_CALLERS)
!= 0;
allowCallsFrom = prioritySendersToSource(policy.priorityCallSenders, allowCallsFrom);
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index ad26f23..ddfc00c 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -129,7 +129,6 @@
final String patternFilename = "hyph-" + languageTag.toLowerCase(Locale.US) + ".hyb";
final File patternFile = new File(SYSTEM_HYPHENATOR_LOCATION, patternFilename);
if (!patternFile.canRead()) {
- Log.e(TAG, "hyphenation patterns for " + patternFile + " not found or unreadable");
mDataAddress = 0;
} else {
long address;
@@ -230,6 +229,11 @@
loadData("tk", 2, 2); // Turkmen
loadData("und-Ethi", 1, 1); // Any language in Ethiopic script
+ // Following two hyphenators do not have pattern files but there is some special logic
+ // based on language.
+ loadData("ca", 2, 2); // Catalan
+ loadData("pl", 2, 2); // Polish
+
// English locales that fall back to en-US. The data is
// from CLDR. It's all English locales, minus the locales whose
// parent is en-001 (from supplementalData.xml, under <parentLocales>).
@@ -267,7 +271,7 @@
}
};
- private static native long nBuildHyphenator(/* non-zero */ long dataAddress,
+ private static native long nBuildHyphenator(long dataAddress,
@NonNull String langTag, @IntRange(from = 1) int minPrefix,
@IntRange(from = 1) int minSuffix);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 31daeff..5482589 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -21,15 +21,22 @@
import android.annotation.Size;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
+import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
+import android.os.Debug;
import android.os.IBinder;
import android.util.Log;
import android.view.Surface.OutOfResourcesException;
import dalvik.system.CloseGuard;
+import java.io.Closeable;
+
+import libcore.util.NativeAllocationRegistry;
+
/**
* SurfaceControl
* @hide
@@ -54,25 +61,34 @@
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
boolean allLayers, boolean useIdentityTransform);
- private static native void nativeOpenTransaction();
- private static native void nativeCloseTransaction(boolean sync);
- private static native void nativeSetAnimationTransaction();
+ private static native long nativeCreateTransaction();
+ private static native long nativeGetNativeTransactionFinalizer();
+ private static native void nativeApplyTransaction(long transactionObj, boolean sync);
+ private static native void nativeSetAnimationTransaction(long transactionObj);
- private static native void nativeSetLayer(long nativeObject, int zorder);
- private static native void nativeSetRelativeLayer(long nativeObject, IBinder relativeTo,
- int zorder);
- private static native void nativeSetPosition(long nativeObject, float x, float y);
- private static native void nativeSetGeometryAppliesWithResize(long nativeObject);
- private static native void nativeSetSize(long nativeObject, int w, int h);
- private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
- private static native void nativeSetAlpha(long nativeObject, float alpha);
- private static native void nativeSetColor(long nativeObject, float[] color);
- private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx,
+ private static native void nativeSetLayer(long transactionObj, long nativeObject, int zorder);
+ private static native void nativeSetRelativeLayer(long transactionObj, long nativeObject,
+ IBinder relativeTo, int zorder);
+ private static native void nativeSetPosition(long transactionObj, long nativeObject,
+ float x, float y);
+ private static native void nativeSetGeometryAppliesWithResize(long transactionObj,
+ long nativeObject);
+ private static native void nativeSetSize(long transactionObj, long nativeObject, int w, int h);
+ private static native void nativeSetTransparentRegionHint(long transactionObj,
+ long nativeObject, Region region);
+ private static native void nativeSetAlpha(long transactionObj, long nativeObject, float alpha);
+ private static native void nativeSetMatrix(long transactionObj, long nativeObject,
+ float dsdx, float dtdx,
float dtdy, float dsdy);
- private static native void nativeSetFlags(long nativeObject, int flags, int mask);
- private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
- private static native void nativeSetFinalCrop(long nativeObject, int l, int t, int r, int b);
- private static native void nativeSetLayerStack(long nativeObject, int layerStack);
+ private static native void nativeSetColor(long transactionObj, long nativeObject, float[] color);
+ private static native void nativeSetFlags(long transactionObj, long nativeObject,
+ int flags, int mask);
+ private static native void nativeSetWindowCrop(long transactionObj, long nativeObject,
+ int l, int t, int r, int b);
+ private static native void nativeSetFinalCrop(long transactionObj, long nativeObject,
+ int l, int t, int r, int b);
+ private static native void nativeSetLayerStack(long transactionObj, long nativeObject,
+ int layerStack);
private static native boolean nativeClearContentFrameStats(long nativeObject);
private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
@@ -82,15 +98,16 @@
private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
private static native IBinder nativeCreateDisplay(String name, boolean secure);
private static native void nativeDestroyDisplay(IBinder displayToken);
- private static native void nativeSetDisplaySurface(
+ private static native void nativeSetDisplaySurface(long transactionObj,
IBinder displayToken, long nativeSurfaceObject);
- private static native void nativeSetDisplayLayerStack(
+ private static native void nativeSetDisplayLayerStack(long transactionObj,
IBinder displayToken, int layerStack);
- private static native void nativeSetDisplayProjection(
+ private static native void nativeSetDisplayProjection(long transactionObj,
IBinder displayToken, int orientation,
int l, int t, int r, int b,
int L, int T, int R, int B);
- private static native void nativeSetDisplaySize(IBinder displayToken, int width, int height);
+ private static native void nativeSetDisplaySize(long transactionObj, IBinder displayToken,
+ int width, int height);
private static native SurfaceControl.PhysicalDisplayInfo[] nativeGetDisplayConfigs(
IBinder displayToken);
private static native int nativeGetActiveConfig(IBinder displayToken);
@@ -101,16 +118,17 @@
int colorMode);
private static native void nativeSetDisplayPowerMode(
IBinder displayToken, int mode);
- private static native void nativeDeferTransactionUntil(long nativeObject,
+ private static native void nativeDeferTransactionUntil(long transactionObj, long nativeObject,
IBinder handle, long frame);
- private static native void nativeDeferTransactionUntilSurface(long nativeObject,
+ private static native void nativeDeferTransactionUntilSurface(long transactionObj,
+ long nativeObject,
long surfaceObject, long frame);
- private static native void nativeReparentChildren(long nativeObject,
+ private static native void nativeReparentChildren(long transactionObj, long nativeObject,
IBinder handle);
- private static native void nativeReparent(long nativeObject,
+ private static native void nativeReparent(long transactionObj, long nativeObject,
IBinder parentHandle);
- private static native void nativeSeverChildren(long nativeObject);
- private static native void nativeSetOverrideScalingMode(long nativeObject,
+ private static native void nativeSeverChildren(long transactionObj, long nativeObject);
+ private static native void nativeSetOverrideScalingMode(long transactionObj, long nativeObject,
int scalingMode);
private static native IBinder nativeGetHandle(long nativeObject);
private static native boolean nativeGetTransformToDisplayInverse(long nativeObject);
@@ -122,6 +140,9 @@
private final String mName;
long mNativeObject; // package visibility only for Surface.java access
+ static Transaction sGlobalTransaction;
+ static long sTransactionNestCount = 0;
+
/* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
/**
@@ -377,11 +398,6 @@
}
}
- @Override
- public String toString() {
- return "Surface(name=" + mName + ")";
- }
-
/**
* Release the local reference to the server-side surface.
* Always call release() when you're done with a Surface.
@@ -429,102 +445,141 @@
/** start a transaction */
public static void openTransaction() {
- nativeOpenTransaction();
+ synchronized (SurfaceControl.class) {
+ if (sGlobalTransaction == null) {
+ sGlobalTransaction = new Transaction();
+ }
+ synchronized(SurfaceControl.class) {
+ sTransactionNestCount++;
+ }
+ }
+ }
+
+ private static void closeTransaction(boolean sync) {
+ synchronized(SurfaceControl.class) {
+ if (sTransactionNestCount == 0) {
+ Log.e(TAG, "Call to SurfaceControl.closeTransaction without matching openTransaction");
+ } else if (--sTransactionNestCount > 0) {
+ return;
+ }
+ sGlobalTransaction.apply(sync);
+ }
}
/** end a transaction */
public static void closeTransaction() {
- nativeCloseTransaction(false);
+ closeTransaction(false);
}
public static void closeTransactionSync() {
- nativeCloseTransaction(true);
+ closeTransaction(true);
}
public void deferTransactionUntil(IBinder handle, long frame) {
if (frame > 0) {
- nativeDeferTransactionUntil(mNativeObject, handle, frame);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.deferTransactionUntil(this, handle, frame);
+ }
}
}
public void deferTransactionUntil(Surface barrier, long frame) {
if (frame > 0) {
- nativeDeferTransactionUntilSurface(mNativeObject, barrier.mNativeObject, frame);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.deferTransactionUntilSurface(this, barrier, frame);
+ }
}
}
public void reparentChildren(IBinder newParentHandle) {
- nativeReparentChildren(mNativeObject, newParentHandle);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.reparentChildren(this, newParentHandle);
+ }
}
- /** Re-parents this layer to a new parent. */
public void reparent(IBinder newParentHandle) {
- nativeReparent(mNativeObject, newParentHandle);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.reparent(this, newParentHandle);
+ }
}
public void detachChildren() {
- nativeSeverChildren(mNativeObject);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.detachChildren(this);
+ }
}
public void setOverrideScalingMode(int scalingMode) {
checkNotReleased();
- nativeSetOverrideScalingMode(mNativeObject, scalingMode);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setOverrideScalingMode(this, scalingMode);
+ }
}
public IBinder getHandle() {
return nativeGetHandle(mNativeObject);
}
- /** flag the transaction as an animation */
public static void setAnimationTransaction() {
- nativeSetAnimationTransaction();
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setAnimationTransaction();
+ }
}
public void setLayer(int zorder) {
checkNotReleased();
- nativeSetLayer(mNativeObject, zorder);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setLayer(this, zorder);
+ }
}
public void setRelativeLayer(IBinder relativeTo, int zorder) {
checkNotReleased();
- nativeSetRelativeLayer(mNativeObject, relativeTo, zorder);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setRelativeLayer(this, relativeTo, zorder);
+ }
}
public void setPosition(float x, float y) {
checkNotReleased();
- nativeSetPosition(mNativeObject, x, y);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setPosition(this, x, y);
+ }
}
- /**
- * If the buffer size changes in this transaction, position and crop updates specified
- * in this transaction will not complete until a buffer of the new size
- * arrives. As transform matrix and size are already frozen in this fashion,
- * this enables totally freezing the surface until the resize has completed
- * (at which point the geometry influencing aspects of this transaction will then occur)
- */
public void setGeometryAppliesWithResize() {
checkNotReleased();
- nativeSetGeometryAppliesWithResize(mNativeObject);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setGeometryAppliesWithResize(this);
+ }
}
public void setSize(int w, int h) {
checkNotReleased();
- nativeSetSize(mNativeObject, w, h);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setSize(this, w, h);
+ }
}
public void hide() {
checkNotReleased();
- nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.hide(this);
+ }
}
public void show() {
checkNotReleased();
- nativeSetFlags(mNativeObject, 0, SURFACE_HIDDEN);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.show(this);
+ }
}
public void setTransparentRegionHint(Region region) {
checkNotReleased();
- nativeSetTransparentRegionHint(mNativeObject, region);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setTransparentRegionHint(this, region);
+ }
}
public boolean clearContentFrameStats() {
@@ -545,80 +600,70 @@
return nativeGetAnimationFrameStats(outStats);
}
- /**
- * Sets an alpha value for the entire Surface. This value is combined with the
- * per-pixel alpha. It may be used with opaque Surfaces.
- */
public void setAlpha(float alpha) {
checkNotReleased();
- nativeSetAlpha(mNativeObject, alpha);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setAlpha(this, alpha);
+ }
}
- /**
- * Sets a color for the Surface.
- * @param color A float array with three values to represent r, g, b in range [0..1]
- */
public void setColor(@Size(3) float[] color) {
checkNotReleased();
- nativeSetColor(mNativeObject, color);
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setColor(this, color);
+ }
}
public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
checkNotReleased();
- nativeSetMatrix(mNativeObject, dsdx, dtdx, dtdy, dsdy);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setMatrix(this, dsdx, dtdx, dtdy, dsdy);
+ }
}
public void setWindowCrop(Rect crop) {
checkNotReleased();
- if (crop != null) {
- nativeSetWindowCrop(mNativeObject,
- crop.left, crop.top, crop.right, crop.bottom);
- } else {
- nativeSetWindowCrop(mNativeObject, 0, 0, 0, 0);
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setWindowCrop(this, crop);
}
}
public void setFinalCrop(Rect crop) {
checkNotReleased();
- if (crop != null) {
- nativeSetFinalCrop(mNativeObject,
- crop.left, crop.top, crop.right, crop.bottom);
- } else {
- nativeSetFinalCrop(mNativeObject, 0, 0, 0, 0);
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setFinalCrop(this, crop);
}
}
public void setLayerStack(int layerStack) {
checkNotReleased();
- nativeSetLayerStack(mNativeObject, layerStack);
+ synchronized(SurfaceControl.class) {
+ sGlobalTransaction.setLayerStack(this, layerStack);
+ }
}
- /**
- * Sets the opacity of the surface. Setting the flag is equivalent to creating the
- * Surface with the {@link #OPAQUE} flag.
- */
public void setOpaque(boolean isOpaque) {
checkNotReleased();
- if (isOpaque) {
- nativeSetFlags(mNativeObject, SURFACE_OPAQUE, SURFACE_OPAQUE);
- } else {
- nativeSetFlags(mNativeObject, 0, SURFACE_OPAQUE);
+
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setOpaque(this, isOpaque);
}
}
- /**
- * Sets the security of the surface. Setting the flag is equivalent to creating the
- * Surface with the {@link #SECURE} flag.
- */
public void setSecure(boolean isSecure) {
checkNotReleased();
- if (isSecure) {
- nativeSetFlags(mNativeObject, SECURE, SECURE);
- } else {
- nativeSetFlags(mNativeObject, 0, SECURE);
+
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setSecure(this, isSecure);
}
}
+ @Override
+ public String toString() {
+ return "Surface(name=" + mName + ")/@0x" +
+ Integer.toHexString(System.identityHashCode(this));
+ }
+
/*
* set display parameters.
* needs to be inside open/closeTransaction block
@@ -741,50 +786,28 @@
public static void setDisplayProjection(IBinder displayToken,
int orientation, Rect layerStackRect, Rect displayRect) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setDisplayProjection(displayToken, orientation,
+ layerStackRect, displayRect);
}
- if (layerStackRect == null) {
- throw new IllegalArgumentException("layerStackRect must not be null");
- }
- if (displayRect == null) {
- throw new IllegalArgumentException("displayRect must not be null");
- }
- nativeSetDisplayProjection(displayToken, orientation,
- layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
- displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
}
public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setDisplayLayerStack(displayToken, layerStack);
}
- nativeSetDisplayLayerStack(displayToken, layerStack);
}
public static void setDisplaySurface(IBinder displayToken, Surface surface) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
-
- if (surface != null) {
- synchronized (surface.mLock) {
- nativeSetDisplaySurface(displayToken, surface.mNativeObject);
- }
- } else {
- nativeSetDisplaySurface(displayToken, 0);
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setDisplaySurface(displayToken, surface);
}
}
public static void setDisplaySize(IBinder displayToken, int width, int height) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setDisplaySize(displayToken, width, height);
}
- if (width <= 0 || height <= 0) {
- throw new IllegalArgumentException("width and height must be positive");
- }
-
- nativeSetDisplaySize(displayToken, width, height);
}
public static Display.HdrCapabilities getHdrCapabilities(IBinder displayToken) {
@@ -946,4 +969,261 @@
nativeScreenshot(display, consumer, sourceCrop, width, height,
minLayer, maxLayer, allLayers, useIdentityTransform);
}
+
+ public static class Transaction implements Closeable {
+ public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+ Transaction.class.getClassLoader(),
+ nativeGetNativeTransactionFinalizer(), 512);
+ private long mNativeObject;
+
+ Runnable mFreeNativeResources;
+
+ public Transaction() {
+ mNativeObject = nativeCreateTransaction();
+ mFreeNativeResources
+ = sRegistry.registerNativeAllocation(this, mNativeObject);
+ }
+
+ /**
+ * Apply the transaction, clearing it's state, and making it usable
+ * as a new transaction.
+ */
+ public void apply() {
+ apply(false);
+ }
+
+ /**
+ * Close the transaction, if the transaction was not already applied this will cancel the
+ * transaction.
+ */
+ @Override
+ public void close() {
+ mFreeNativeResources.run();
+ mNativeObject = 0;
+ }
+
+ /**
+ * Jankier version of apply. Avoid use (b/28068298).
+ */
+ public void apply(boolean sync) {
+ nativeApplyTransaction(mNativeObject, sync);
+ }
+
+ public Transaction show(SurfaceControl sc) {
+ nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SURFACE_HIDDEN);
+ return this;
+ }
+
+ public Transaction hide(SurfaceControl sc) {
+ nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
+ return this;
+ }
+
+ public Transaction setPosition(SurfaceControl sc, float x, float y) {
+ nativeSetPosition(mNativeObject, sc.mNativeObject, x, y);
+ return this;
+ }
+
+ public Transaction setSize(SurfaceControl sc, int w, int h) {
+ nativeSetSize(mNativeObject, sc.mNativeObject,
+ w, h);
+ return this;
+ }
+
+ public Transaction setLayer(SurfaceControl sc, int z) {
+ nativeSetLayer(mNativeObject, sc.mNativeObject, z);
+ return this;
+ }
+
+ public Transaction setRelativeLayer(SurfaceControl sc, IBinder relativeTo, int z) {
+ nativeSetRelativeLayer(mNativeObject, sc.mNativeObject,
+ relativeTo, z);
+ return this;
+ }
+
+ public Transaction setTransparentRegionHint(SurfaceControl sc, Region transparentRegion) {
+ nativeSetTransparentRegionHint(mNativeObject,
+ sc.mNativeObject, transparentRegion);
+ return this;
+ }
+
+ public Transaction setAlpha(SurfaceControl sc, float alpha) {
+ nativeSetAlpha(mNativeObject, sc.mNativeObject, alpha);
+ return this;
+ }
+
+ public Transaction setMatrix(SurfaceControl sc,
+ float dsdx, float dtdx, float dtdy, float dsdy) {
+ nativeSetMatrix(mNativeObject, sc.mNativeObject,
+ dsdx, dtdx, dtdy, dsdy);
+ return this;
+ }
+
+ public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
+ if (crop != null) {
+ nativeSetWindowCrop(mNativeObject, sc.mNativeObject,
+ crop.left, crop.top, crop.right, crop.bottom);
+ } else {
+ nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, 0, 0);
+ }
+
+ return this;
+ }
+
+ public Transaction setFinalCrop(SurfaceControl sc, Rect crop) {
+ if (crop != null) {
+ nativeSetFinalCrop(mNativeObject, sc.mNativeObject,
+ crop.left, crop.top, crop.right, crop.bottom);
+ } else {
+ nativeSetFinalCrop(mNativeObject, sc.mNativeObject, 0, 0, 0, 0);
+ }
+
+ return this;
+ }
+
+ public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
+ nativeSetLayerStack(mNativeObject, sc.mNativeObject, layerStack);
+ return this;
+ }
+
+ public Transaction deferTransactionUntil(SurfaceControl sc, IBinder handle, long frameNumber) {
+ nativeDeferTransactionUntil(mNativeObject, sc.mNativeObject, handle, frameNumber);
+ return this;
+ }
+
+ public Transaction deferTransactionUntilSurface(SurfaceControl sc, Surface barrierSurface,
+ long frameNumber) {
+ nativeDeferTransactionUntilSurface(mNativeObject, sc.mNativeObject,
+ barrierSurface.mNativeObject, frameNumber);
+ return this;
+ }
+
+ public Transaction reparentChildren(SurfaceControl sc, IBinder newParentHandle) {
+ nativeReparentChildren(mNativeObject, sc.mNativeObject, newParentHandle);
+ return this;
+ }
+
+ /** Re-parents a specific child layer to a new parent */
+ public Transaction reparent(SurfaceControl sc, IBinder newParentHandle) {
+ nativeReparent(mNativeObject, sc.mNativeObject,
+ newParentHandle);
+ return this;
+ }
+
+ public Transaction detachChildren(SurfaceControl sc) {
+ nativeSeverChildren(mNativeObject, sc.mNativeObject);
+ return this;
+ }
+
+ public Transaction setOverrideScalingMode(SurfaceControl sc, int overrideScalingMode) {
+ nativeSetOverrideScalingMode(mNativeObject, sc.mNativeObject,
+ overrideScalingMode);
+ return this;
+ }
+
+ /**
+ * Sets a color for the Surface.
+ * @param color A float array with three values to represent r, g, b in range [0..1]
+ */
+ public Transaction setColor(SurfaceControl sc, @Size(3) float[] color) {
+ nativeSetColor(mNativeObject, sc.mNativeObject, color);
+ return this;
+ }
+
+ /**
+ * If the buffer size changes in this transaction, position and crop updates specified
+ * in this transaction will not complete until a buffer of the new size
+ * arrives. As transform matrix and size are already frozen in this fashion,
+ * this enables totally freezing the surface until the resize has completed
+ * (at which point the geometry influencing aspects of this transaction will then occur)
+ */
+ public Transaction setGeometryAppliesWithResize(SurfaceControl sc) {
+ nativeSetGeometryAppliesWithResize(mNativeObject, sc.mNativeObject);
+ return this;
+ }
+
+ /**
+ * Sets the security of the surface. Setting the flag is equivalent to creating the
+ * Surface with the {@link #SECURE} flag.
+ */
+ Transaction setSecure(SurfaceControl sc, boolean isSecure) {
+ if (isSecure) {
+ nativeSetFlags(mNativeObject, sc.mNativeObject, SECURE, SECURE);
+ } else {
+ nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SECURE);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the opacity of the surface. Setting the flag is equivalent to creating the
+ * Surface with the {@link #OPAQUE} flag.
+ */
+ public Transaction setOpaque(SurfaceControl sc, boolean isOpaque) {
+ if (isOpaque) {
+ nativeSetFlags(mNativeObject, sc.mNativeObject, OPAQUE, OPAQUE);
+ } else {
+ nativeSetFlags(mNativeObject, sc.mNativeObject, 0, OPAQUE);
+ }
+ return this;
+ }
+
+ public Transaction setDisplaySurface(IBinder displayToken, Surface surface) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ if (surface != null) {
+ synchronized (surface.mLock) {
+ nativeSetDisplaySurface(mNativeObject, displayToken, surface.mNativeObject);
+ }
+ } else {
+ nativeSetDisplaySurface(mNativeObject, displayToken, 0);
+ }
+ return this;
+ }
+
+ public Transaction setDisplayLayerStack(IBinder displayToken, int layerStack) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+ nativeSetDisplayLayerStack(mNativeObject, displayToken, layerStack);
+ return this;
+ }
+
+ public Transaction setDisplayProjection(IBinder displayToken,
+ int orientation, Rect layerStackRect, Rect displayRect) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+ if (layerStackRect == null) {
+ throw new IllegalArgumentException("layerStackRect must not be null");
+ }
+ if (displayRect == null) {
+ throw new IllegalArgumentException("displayRect must not be null");
+ }
+ nativeSetDisplayProjection(mNativeObject, displayToken, orientation,
+ layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
+ displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
+ return this;
+ }
+
+ public Transaction setDisplaySize(IBinder displayToken, int width, int height) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+ if (width <= 0 || height <= 0) {
+ throw new IllegalArgumentException("width and height must be positive");
+ }
+
+ nativeSetDisplaySize(mNativeObject, displayToken, width, height);
+ return this;
+ }
+
+ /** flag the transaction as an animation */
+ public Transaction setAnimationTransaction() {
+ nativeSetAnimationTransaction(mNativeObject);
+ return this;
+ }
+ }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b6be296..2ee83bc 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1448,17 +1448,59 @@
/**
* <p>Enables low quality mode for the drawing cache.</p>
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
/**
* <p>Enables high quality mode for the drawing cache.</p>
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
/**
* <p>Enables automatic quality mode for the drawing cache.</p>
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
@@ -6356,6 +6398,60 @@
}
/**
+ * Set by {@link AutofillManager} if it needs to be notified when this view is clicked.
+ */
+ private boolean mNotifyAutofillManagerOnClick;
+
+ /**
+ * Temporary variable used to make sure the autofill manager is not called twice on
+ * {@link #performClickInternal()}.
+ */
+ private boolean mAlreadyNotifiedAutofillManagerOnClick;
+
+ /** @hide */
+ public void setNotifyAutofillManagerOnClick(boolean notify) {
+ mNotifyAutofillManagerOnClick = notify;
+ }
+
+ private void notifyAutofillManagerOnClick() {
+ if (!mNotifyAutofillManagerOnClick || mAlreadyNotifiedAutofillManagerOnClick) {
+ return;
+ }
+ // Must notify manager first to avoid scenarios where app has a listener
+ // that changes the state of views the autofill service might be interested on.
+ try {
+ getAutofillManager().notifyViewClicked(this);
+ } finally {
+ // Set it to already called so it's not called twice when
+ mAlreadyNotifiedAutofillManagerOnClick = true;
+ }
+ }
+
+ /**
+ * Entry point for {@link #performClick()} - other methods on View should call it instead of
+ * {@code performClick()} directly to make sure the autofill manager is notified when
+ * necessary (as subclasses could extend {@code performClick()} without calling the parent's
+ * method).
+ */
+ private boolean performClickInternal() {
+ mAlreadyNotifiedAutofillManagerOnClick = false;
+
+ // Must notify autofill manager before performing the click actions to avoid scenarios where
+ // the app has a click listener that changes the state of views the autofill service might
+ // be interested on.
+ notifyAutofillManagerOnClick();
+
+ boolean performed;
+ try {
+ performed = performClick();
+ } finally {
+ // Reset it for next call.
+ mAlreadyNotifiedAutofillManagerOnClick = false;
+ }
+ return performed;
+ }
+
+ /**
* Call this view's OnClickListener, if it is defined. Performs all normal
* actions associated with clicking: reporting accessibility event, playing
* a sound, etc.
@@ -6363,7 +6459,19 @@
* @return True there was an assigned OnClickListener that was called, false
* otherwise is returned.
*/
+ // NOTE: other methods on View should not call this method directly, but performClickInternal()
+ // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
+ // could extend this method without calling super.performClick()).
public boolean performClick() {
+ try {
+ // We still need to call this method to handle the cases where performClick() was called
+ // externally, instead of through performClickInternal()
+ notifyAutofillManagerOnClick();
+ } finally {
+ // Reset it for next call.
+ mAlreadyNotifiedAutofillManagerOnClick = false;
+ }
+
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
@@ -8907,7 +9015,21 @@
* @see #isDrawingCacheEnabled()
*
* @attr ref android.R.styleable#View_drawingCacheQuality
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
@DrawingCacheQuality
public int getDrawingCacheQuality() {
return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
@@ -8925,7 +9047,21 @@
* @see #isDrawingCacheEnabled()
*
* @attr ref android.R.styleable#View_drawingCacheQuality
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
}
@@ -11433,7 +11569,7 @@
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK: {
if (isClickable()) {
- performClick();
+ performClickInternal();
return true;
}
} break;
@@ -12545,7 +12681,7 @@
// This is a tap, so remove the longpress check
removeLongPressCallback();
if (!event.isCanceled()) {
- return performClick();
+ return performClickInternal();
}
}
}
@@ -13117,7 +13253,7 @@
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
- performClick();
+ performClickInternal();
}
}
}
@@ -18103,7 +18239,21 @@
* @see #getDrawingCache()
* @see #buildDrawingCache()
* @see #setLayerType(int, android.graphics.Paint)
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void setDrawingCacheEnabled(boolean enabled) {
mCachingFailed = false;
setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
@@ -18116,7 +18266,21 @@
*
* @see #setDrawingCacheEnabled(boolean)
* @see #getDrawingCache()
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
@ViewDebug.ExportedProperty(category = "drawing")
public boolean isDrawingCacheEnabled() {
return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
@@ -18130,10 +18294,11 @@
*/
@SuppressWarnings({"UnusedDeclaration"})
public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
- Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
- ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
- (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
- ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
+ Log.d(VIEW_LOG_TAG, indent + this + " DIRTY("
+ + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
+ + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
+ + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
+ + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
if (clear) {
mPrivateFlags &= clearMask;
}
@@ -18257,7 +18422,21 @@
* @return A non-scaled bitmap representing this view or null if cache is disabled.
*
* @see #getDrawingCache(boolean)
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public Bitmap getDrawingCache() {
return getDrawingCache(false);
}
@@ -18288,7 +18467,21 @@
* @see #isDrawingCacheEnabled()
* @see #buildDrawingCache(boolean)
* @see #destroyDrawingCache()
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public Bitmap getDrawingCache(boolean autoScale) {
if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
return null;
@@ -18308,7 +18501,21 @@
* @see #setDrawingCacheEnabled(boolean)
* @see #buildDrawingCache()
* @see #getDrawingCache()
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void destroyDrawingCache() {
if (mDrawingCache != null) {
mDrawingCache.recycle();
@@ -18330,7 +18537,21 @@
* @see #setDrawingCacheEnabled(boolean)
* @see #buildDrawingCache()
* @see #getDrawingCache()
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void setDrawingCacheBackgroundColor(@ColorInt int color) {
if (color != mDrawingCacheBackgroundColor) {
mDrawingCacheBackgroundColor = color;
@@ -18342,7 +18563,21 @@
* @see #setDrawingCacheBackgroundColor(int)
*
* @return The background color to used for the drawing cache's bitmap
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
@ColorInt
public int getDrawingCacheBackgroundColor() {
return mDrawingCacheBackgroundColor;
@@ -18352,7 +18587,21 @@
* <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
*
* @see #buildDrawingCache(boolean)
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void buildDrawingCache() {
buildDrawingCache(false);
}
@@ -18379,7 +18628,21 @@
*
* @see #getDrawingCache()
* @see #destroyDrawingCache()
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void buildDrawingCache(boolean autoScale) {
if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
mDrawingCache == null : mUnscaledDrawingCache == null)) {
@@ -19812,7 +20075,7 @@
boolean changed = false;
if (DBG) {
- Log.d("View", this + " View.setFrame(" + left + "," + top + ","
+ Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
+ right + "," + bottom + ")");
}
@@ -24858,7 +25121,7 @@
private final class PerformClick implements Runnable {
@Override
public void run() {
- performClick();
+ performClickInternal();
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b2e5a16..929beae 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -421,22 +421,78 @@
/**
* Used to indicate that no drawing cache should be kept in memory.
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public static final int PERSISTENT_NO_CACHE = 0x0;
/**
* Used to indicate that the animation drawing cache should be kept in memory.
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public static final int PERSISTENT_ANIMATION_CACHE = 0x1;
/**
* Used to indicate that the scrolling drawing cache should be kept in memory.
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public static final int PERSISTENT_SCROLLING_CACHE = 0x2;
/**
* Used to indicate that all drawing caches should be kept in memory.
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public static final int PERSISTENT_ALL_CACHES = 0x3;
// Layout Modes
@@ -3769,7 +3825,21 @@
* Enables or disables the drawing cache for each child of this view group.
*
* @param enabled true to enable the cache, false to dispose of it
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
protected void setChildrenDrawingCacheEnabled(boolean enabled) {
if (enabled || (mPersistentDrawingCache & PERSISTENT_ALL_CACHES) != PERSISTENT_ALL_CACHES) {
final View[] children = mChildren;
@@ -6331,7 +6401,21 @@
* @return one or a combination of {@link #PERSISTENT_NO_CACHE},
* {@link #PERSISTENT_ANIMATION_CACHE}, {@link #PERSISTENT_SCROLLING_CACHE}
* and {@link #PERSISTENT_ALL_CACHES}
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
@ViewDebug.ExportedProperty(category = "drawing", mapping = {
@ViewDebug.IntToString(from = PERSISTENT_NO_CACHE, to = "NONE"),
@ViewDebug.IntToString(from = PERSISTENT_ANIMATION_CACHE, to = "ANIMATION"),
@@ -6352,7 +6436,21 @@
* @param drawingCacheToKeep one or a combination of {@link #PERSISTENT_NO_CACHE},
* {@link #PERSISTENT_ANIMATION_CACHE}, {@link #PERSISTENT_SCROLLING_CACHE}
* and {@link #PERSISTENT_ALL_CACHES}
+ *
+ * @deprecated The view drawing cache was largely made obsolete with the introduction of
+ * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
+ * layers are largely unnecessary and can easily result in a net loss in performance due to the
+ * cost of creating and updating the layer. In the rare cases where caching layers are useful,
+ * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
+ * rendering. For software-rendered snapshots of a small part of the View hierarchy or
+ * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
+ * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
+ * software-rendered usages are discouraged and have compatibility issues with hardware-only
+ * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
+ * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
+ * reports or unit testing the {@link PixelCopy} API is recommended.
*/
+ @Deprecated
public void setPersistentDrawingCache(int drawingCacheToKeep) {
mPersistentDrawingCache = drawingCacheToKeep & PERSISTENT_ALL_CACHES;
}
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 98f8dc8..69cc100 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -335,8 +335,8 @@
public abstract void setOnHardKeyboardStatusChangeListener(
OnHardKeyboardStatusChangeListener listener);
- /** Returns true if the stack with the input Id is currently visible. */
- public abstract boolean isStackVisible(int stackId);
+ /** Returns true if a stack in the windowing mode is currently visible. */
+ public abstract boolean isStackVisible(int windowingMode);
/**
* @return True if and only if the docked divider is currently in resize mode.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index da72535..137e551 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -467,11 +467,8 @@
*/
public boolean isDimming();
- /**
- * @return the stack id this windows belongs to, or {@link StackId#INVALID_STACK_ID} if
- * not attached to any stack.
- */
- int getStackId();
+ /** @return the current windowing mode of this window. */
+ int getWindowingMode();
/**
* Returns true if the window is current in multi-windowing mode. i.e. it shares the
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 0f21c5c..d785117 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -329,8 +329,6 @@
final long oldParentId = oldInfo.getParentNodeId();
if (info.getParentNodeId() != oldParentId) {
clearSubTreeLocked(windowId, oldParentId);
- } else {
- oldInfo.recycle();
}
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 4fb2a99..44f304d 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -91,10 +91,10 @@
* </ul>
*
* <p>When the service returns datasets, the Android System displays an autofill dataset picker
- * UI affordance associated with the view, when the view is focused on and is part of a dataset.
- * The application can be notified when the affordance is shown by registering an
+ * UI associated with the view, when the view is focused on and is part of a dataset.
+ * The application can be notified when the UI is shown by registering an
* {@link AutofillCallback} through {@link #registerCallback(AutofillCallback)}. When the user
- * selects a dataset from the affordance, all views present in the dataset are autofilled, through
+ * selects a dataset from the UI, all views present in the dataset are autofilled, through
* calls to {@link View#autofill(AutofillValue)} or {@link View#autofill(SparseArray)}.
*
* <p>When the service returns ids of savable views, the Android System keeps track of changes
@@ -108,7 +108,7 @@
* </ul>
*
* <p>Finally, after the autofill context is commited (i.e., not cancelled), the Android System
- * shows a save UI affordance if the value of savable views have changed. If the user selects the
+ * shows an autofill save UI if the value of savable views have changed. If the user selects the
* option to Save, the current value of the views is then sent to the autofill service.
*
* <p>It is safe to call into its methods from any thread.
@@ -150,6 +150,12 @@
* service authentication will contain the Bundle set by
* {@link android.service.autofill.FillResponse.Builder#setClientState(Bundle)} on this extra.
*
+ * <p>On Android {@link android.os.Build.VERSION_CODES#P} and higher, the autofill service
+ * can also add this bundle to the {@link Intent} set as the
+ * {@link android.app.Activity#setResult(int, Intent) result} for an authentication request,
+ * so the bundle can be recovered later on
+ * {@link android.service.autofill.SaveRequest#getClientState()}.
+ *
* <p>
* Type: {@link android.os.Bundle}
*/
@@ -311,6 +317,14 @@
@GuardedBy("mLock")
@Nullable private ArraySet<AutofillId> mFillableIds;
+ /** If set, session is commited when the field is clicked. */
+ @GuardedBy("mLock")
+ @Nullable private AutofillId mSaveTriggerId;
+
+ /** If set, session is commited when the activity is finished; otherwise session is canceled. */
+ @GuardedBy("mLock")
+ private boolean mSaveOnFinish;
+
/** @hide */
public interface AutofillClient {
/**
@@ -834,6 +848,46 @@
}
}
+
+ /**
+ * Called when a {@link View} is clicked. Currently only used by views that should trigger save.
+ *
+ * @hide
+ */
+ public void notifyViewClicked(View view) {
+ final AutofillId id = view.getAutofillId();
+
+ if (sVerbose) Log.v(TAG, "notifyViewClicked(): id=" + id + ", trigger=" + mSaveTriggerId);
+
+ synchronized (mLock) {
+ if (mSaveTriggerId != null && mSaveTriggerId.equals(id)) {
+ if (sDebug) Log.d(TAG, "triggering commit by click of " + id);
+ commitLocked();
+ mMetricsLogger.action(MetricsEvent.AUTOFILL_SAVE_EXPLICITLY_TRIGGERED,
+ mContext.getPackageName());
+ }
+ }
+ }
+
+ /**
+ * Called by {@link android.app.Activity} to commit or cancel the session on finish.
+ *
+ * @hide
+ */
+ public void onActivityFinished() {
+ if (!hasAutofillFeature()) {
+ return;
+ }
+ synchronized (mLock) {
+ if (mSaveOnFinish) {
+ commitLocked();
+ } else {
+ if (sDebug) Log.d(TAG, "Cancelling session on finish() as requested by service");
+ cancelLocked();
+ }
+ }
+ }
+
/**
* Called to indicate the current autofill context should be commited.
*
@@ -850,14 +904,17 @@
return;
}
synchronized (mLock) {
- if (!mEnabled && !isActiveLocked()) {
- return;
- }
-
- finishSessionLocked();
+ commitLocked();
}
}
+ private void commitLocked() {
+ if (!mEnabled && !isActiveLocked()) {
+ return;
+ }
+ finishSessionLocked();
+ }
+
/**
* Called to indicate the current autofill context should be cancelled.
*
@@ -874,14 +931,17 @@
return;
}
synchronized (mLock) {
- if (!mEnabled && !isActiveLocked()) {
- return;
- }
-
- cancelSessionLocked();
+ cancelLocked();
}
}
+ private void cancelLocked() {
+ if (!mEnabled && !isActiveLocked()) {
+ return;
+ }
+ cancelSessionLocked();
+ }
+
/** @hide */
public void disableOwnedAutofillServices() {
disableAutofillServices();
@@ -959,6 +1019,10 @@
final Parcelable result = data.getParcelableExtra(EXTRA_AUTHENTICATION_RESULT);
final Bundle responseData = new Bundle();
responseData.putParcelable(EXTRA_AUTHENTICATION_RESULT, result);
+ final Bundle newClientState = data.getBundleExtra(EXTRA_CLIENT_STATE);
+ if (newClientState != null) {
+ responseData.putBundle(EXTRA_CLIENT_STATE, newClientState);
+ }
try {
mService.setAuthenticationResult(responseData, mSessionId, authenticationId,
mContext.getUserId());
@@ -1038,6 +1102,7 @@
mState = STATE_UNKNOWN;
mTrackedViews = null;
mFillableIds = null;
+ mSaveTriggerId = null;
}
private void updateSessionLocked(AutofillId id, Rect bounds, AutofillValue value, int action,
@@ -1289,12 +1354,15 @@
/**
* Set the tracked views.
*
- * @param trackedIds The views to be tracked
+ * @param trackedIds The views to be tracked.
* @param saveOnAllViewsInvisible Finish the session once all tracked views are invisible.
+ * @param saveOnFinish Finish the session once the activity is finished.
* @param fillableIds Views that might anchor FillUI.
+ * @param saveTriggerId View that when clicked triggers commit().
*/
private void setTrackedViews(int sessionId, @Nullable AutofillId[] trackedIds,
- boolean saveOnAllViewsInvisible, @Nullable AutofillId[] fillableIds) {
+ boolean saveOnAllViewsInvisible, boolean saveOnFinish,
+ @Nullable AutofillId[] fillableIds, @Nullable AutofillId saveTriggerId) {
synchronized (mLock) {
if (mEnabled && mSessionId == sessionId) {
if (saveOnAllViewsInvisible) {
@@ -1302,6 +1370,7 @@
} else {
mTrackedViews = null;
}
+ mSaveOnFinish = saveOnFinish;
if (fillableIds != null) {
if (mFillableIds == null) {
mFillableIds = new ArraySet<>(fillableIds.length);
@@ -1314,10 +1383,30 @@
+ ", mFillableIds" + mFillableIds);
}
}
+
+ if (mSaveTriggerId != null && !mSaveTriggerId.equals(saveTriggerId)) {
+ // Turn off trigger on previous view id.
+ setNotifyOnClickLocked(mSaveTriggerId, false);
+ }
+
+ if (saveTriggerId != null && !saveTriggerId.equals(mSaveTriggerId)) {
+ // Turn on trigger on new view id.
+ mSaveTriggerId = saveTriggerId;
+ setNotifyOnClickLocked(mSaveTriggerId, true);
+ }
}
}
}
+ private void setNotifyOnClickLocked(@NonNull AutofillId id, boolean notify) {
+ final View view = findView(id);
+ if (view == null) {
+ Log.w(TAG, "setNotifyOnClick(): invalid id: " + id);
+ return;
+ }
+ view.setNotifyAutofillManagerOnClick(notify);
+ }
+
private void setSaveUiState(int sessionId, boolean shown) {
if (sDebug) Log.d(TAG, "setSaveUiState(" + sessionId + "): " + shown);
synchronized (mLock) {
@@ -1504,6 +1593,8 @@
pw.print(pfx2); pw.print("invisible:"); pw.println(mTrackedViews.mInvisibleTrackedIds);
}
pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds);
+ pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId);
+ pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish);
}
private String getStateAsStringLocked() {
@@ -1752,7 +1843,7 @@
* Callback for autofill related events.
*
* <p>Typically used for applications that display their own "auto-complete" views, so they can
- * enable / disable such views when the autofill UI affordance is shown / hidden.
+ * enable / disable such views when the autofill UI is shown / hidden.
*/
public abstract static class AutofillCallback {
@@ -1762,26 +1853,26 @@
public @interface AutofillEventType {}
/**
- * The autofill input UI affordance associated with the view was shown.
+ * The autofill input UI associated with the view was shown.
*
- * <p>If the view provides its own auto-complete UI affordance and its currently shown, it
+ * <p>If the view provides its own auto-complete UI and its currently shown, it
* should be hidden upon receiving this event.
*/
public static final int EVENT_INPUT_SHOWN = 1;
/**
- * The autofill input UI affordance associated with the view was hidden.
+ * The autofill input UI associated with the view was hidden.
*
- * <p>If the view provides its own auto-complete UI affordance that was hidden upon a
+ * <p>If the view provides its own auto-complete UI that was hidden upon a
* {@link #EVENT_INPUT_SHOWN} event, it could be shown again now.
*/
public static final int EVENT_INPUT_HIDDEN = 2;
/**
- * The autofill input UI affordance associated with the view isn't shown because
+ * The autofill input UI associated with the view isn't shown because
* autofill is not available.
*
- * <p>If the view provides its own auto-complete UI affordance but was not displaying it
+ * <p>If the view provides its own auto-complete UI but was not displaying it
* to avoid flickering, it could shown it upon receiving this event.
*/
public static final int EVENT_INPUT_UNAVAILABLE = 3;
@@ -1883,12 +1974,12 @@
@Override
public void setTrackedViews(int sessionId, AutofillId[] ids,
- boolean saveOnAllViewsInvisible, AutofillId[] fillableIds) {
+ boolean saveOnAllViewsInvisible, boolean saveOnFinish, AutofillId[] fillableIds,
+ AutofillId saveTriggerId) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
- afm.post(() ->
- afm.setTrackedViews(sessionId, ids, saveOnAllViewsInvisible, fillableIds)
- );
+ afm.post(() -> afm.setTrackedViews(sessionId, ids, saveOnAllViewsInvisible,
+ saveOnFinish, fillableIds, saveTriggerId));
}
}
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 3dabcec..56a22c22 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -53,7 +53,8 @@
* the session is finished automatically.
*/
void setTrackedViews(int sessionId, in @nullable AutofillId[] savableIds,
- boolean saveOnAllViewsInvisible, in @nullable AutofillId[] fillableIds);
+ boolean saveOnAllViewsInvisible, boolean saveOnFinish,
+ in @nullable AutofillId[] fillableIds, in AutofillId saveTriggerId);
/**
* Requests showing the fill UI.
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index bb1e693..c3601d9 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -152,4 +152,12 @@
*/
@WorkerThread
default void logEvent(String source, String event) {}
+
+ /**
+ * Returns this TextClassifier's settings.
+ * @hide
+ */
+ default TextClassifierConstants getSettings() {
+ return TextClassifierConstants.DEFAULT;
+ }
}
diff --git a/core/java/android/view/textclassifier/TextClassifierConstants.java b/core/java/android/view/textclassifier/TextClassifierConstants.java
new file mode 100644
index 0000000..51e6168
--- /dev/null
+++ b/core/java/android/view/textclassifier/TextClassifierConstants.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.textclassifier;
+
+import android.annotation.Nullable;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+
+/**
+ * TextClassifier specific settings.
+ * This is encoded as a key=value list, separated by commas. Ex:
+ *
+ * <pre>
+ * smart_selection_dark_launch (boolean)
+ * smart_selection_enabled_for_edit_text (boolean)
+ * </pre>
+ *
+ * <p>
+ * Type: string
+ * see also android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS
+ *
+ * Example of setting the values for testing.
+ * adb shell settings put global text_classifier_constants smart_selection_dark_launch=true,smart_selection_enabled_for_edit_text=true
+ * @hide
+ */
+public final class TextClassifierConstants {
+
+ private static final String LOG_TAG = "TextClassifierConstants";
+
+ private static final String SMART_SELECTION_DARK_LAUNCH =
+ "smart_selection_dark_launch";
+ private static final String SMART_SELECTION_ENABLED_FOR_EDIT_TEXT =
+ "smart_selection_enabled_for_edit_text";
+
+ private static final boolean SMART_SELECTION_DARK_LAUNCH_DEFAULT = false;
+ private static final boolean SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT = true;
+
+ /** Default settings. */
+ static final TextClassifierConstants DEFAULT = new TextClassifierConstants();
+
+ private final boolean mDarkLaunch;
+ private final boolean mSuggestSelectionEnabledForEditableText;
+
+ private TextClassifierConstants() {
+ mDarkLaunch = SMART_SELECTION_DARK_LAUNCH_DEFAULT;
+ mSuggestSelectionEnabledForEditableText = SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT;
+ }
+
+ private TextClassifierConstants(@Nullable String settings) {
+ final KeyValueListParser parser = new KeyValueListParser(',');
+ try {
+ parser.setString(settings);
+ } catch (IllegalArgumentException e) {
+ // Failed to parse the settings string, log this and move on with defaults.
+ Slog.e(LOG_TAG, "Bad TextClassifier settings: " + settings);
+ }
+ mDarkLaunch = parser.getBoolean(
+ SMART_SELECTION_DARK_LAUNCH,
+ SMART_SELECTION_DARK_LAUNCH_DEFAULT);
+ mSuggestSelectionEnabledForEditableText = parser.getBoolean(
+ SMART_SELECTION_ENABLED_FOR_EDIT_TEXT,
+ SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT);
+ }
+
+ static TextClassifierConstants loadFromString(String settings) {
+ return new TextClassifierConstants(settings);
+ }
+
+ public boolean isDarkLaunch() {
+ return mDarkLaunch;
+ }
+
+ public boolean isSuggestSelectionEnabledForEditableText() {
+ return mSuggestSelectionEnabledForEditableText;
+ }
+}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 2aa81a2..ef08747 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -24,12 +24,12 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
-import android.icu.text.BreakIterator;
import android.net.Uri;
import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
import android.provider.Browser;
import android.provider.ContactsContract;
+import android.provider.Settings;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.method.WordIterator;
@@ -47,6 +47,7 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -91,6 +92,8 @@
@GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
private SmartSelection mSmartSelection;
+ private TextClassifierConstants mSettings;
+
TextClassifierImpl(Context context) {
mContext = Preconditions.checkNotNull(context);
}
@@ -189,6 +192,15 @@
}
}
+ @Override
+ public TextClassifierConstants getSettings() {
+ if (mSettings == null) {
+ mSettings = TextClassifierConstants.loadFromString(Settings.Global.getString(
+ mContext.getContentResolver(), Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
+ }
+ return mSettings;
+ }
+
private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException {
synchronized (mSmartSelectionLock) {
localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 1b26f8e..199b596 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2653,7 +2653,11 @@
/**
* Equivalent to calling
* {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
- * to launch the provided {@link PendingIntent}.
+ * to launch the provided {@link PendingIntent}. The source bounds
+ * ({@link Intent#getSourceBounds()}) of the intent will be set to the bounds of the clicked
+ * view in screen space.
+ * Note that any activity options associated with the pendingIntent may get overridden
+ * before starting the intent.
*
* When setting the on-click action of items within collections (eg. {@link ListView},
* {@link StackView} etc.), this method will not work. Instead, use {@link
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 3be42a5..5e22650 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -95,11 +95,15 @@
}
public void startActionModeAsync(boolean adjustSelection) {
+ // Check if the smart selection should run for editable text.
+ adjustSelection &= !mTextView.isTextEditable()
+ || mTextView.getTextClassifier().getSettings()
+ .isSuggestSelectionEnabledForEditableText();
+
mSelectionTracker.onOriginalSelection(
getText(mTextView),
mTextView.getSelectionStart(),
- mTextView.getSelectionEnd(),
- mTextView.isTextEditable());
+ mTextView.getSelectionEnd());
cancelAsyncTask();
if (skipTextClassification()) {
startActionMode(null);
@@ -196,7 +200,10 @@
private void startActionMode(@Nullable SelectionResult result) {
final CharSequence text = getText(mTextView);
if (result != null && text instanceof Spannable) {
- Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
+ // Do not change the selection if TextClassifier should be dark launched.
+ if (!mTextView.getTextClassifier().getSettings().isDarkLaunch()) {
+ Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
+ }
mTextClassification = result.mClassification;
} else {
mTextClassification = null;
@@ -377,7 +384,7 @@
}
private void resetTextClassificationHelper() {
- mTextClassificationHelper.reset(
+ mTextClassificationHelper.init(
mTextView.getTextClassifier(),
getText(mTextView),
mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
@@ -415,8 +422,7 @@
/**
* Called when the original selection happens, before smart selection is triggered.
*/
- public void onOriginalSelection(
- CharSequence text, int selectionStart, int selectionEnd, boolean editableText) {
+ public void onOriginalSelection(CharSequence text, int selectionStart, int selectionEnd) {
// If we abandoned a selection and created a new one very shortly after, we may still
// have a pending request to log ABANDON, which we flush here.
mDelayedLogAbandon.flush();
@@ -812,11 +818,11 @@
TextClassificationHelper(TextClassifier textClassifier,
CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
- reset(textClassifier, text, selectionStart, selectionEnd, locales);
+ init(textClassifier, text, selectionStart, selectionEnd, locales);
}
@UiThread
- public void reset(TextClassifier textClassifier,
+ public void init(TextClassifier textClassifier,
CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
mTextClassifier = Preconditions.checkNotNull(textClassifier);
mText = Preconditions.checkNotNull(text).toString();
@@ -839,8 +845,12 @@
trimText();
final TextSelection selection = mTextClassifier.suggestSelection(
mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
- mSelectionStart = Math.max(0, selection.getSelectionStartIndex() + mTrimStart);
- mSelectionEnd = Math.min(mText.length(), selection.getSelectionEndIndex() + mTrimStart);
+ // Do not classify new selection boundaries if TextClassifier should be dark launched.
+ if (!mTextClassifier.getSettings().isDarkLaunch()) {
+ mSelectionStart = Math.max(0, selection.getSelectionStartIndex() + mTrimStart);
+ mSelectionEnd = Math.min(
+ mText.length(), selection.getSelectionEndIndex() + mTrimStart);
+ }
return performClassification(selection);
}
diff --git a/core/java/com/android/internal/alsa/AlsaCardsParser.java b/core/java/com/android/internal/alsa/AlsaCardsParser.java
index 5b92a17..bb75bf6 100644
--- a/core/java/com/android/internal/alsa/AlsaCardsParser.java
+++ b/core/java/com/android/internal/alsa/AlsaCardsParser.java
@@ -37,6 +37,12 @@
private ArrayList<AlsaCardRecord> mCardRecords = new ArrayList<AlsaCardRecord>();
+ public static final int SCANSTATUS_NOTSCANNED = -1;
+ public static final int SCANSTATUS_SUCCESS = 0;
+ public static final int SCANSTATUS_FAIL = 1;
+ public static final int SCANSTATUS_EMPTY = 2;
+ private int mScanStatus = SCANSTATUS_NOTSCANNED;
+
public class AlsaCardRecord {
private static final String TAG = "AlsaCardRecord";
private static final String kUsbCardKeyStr = "at usb-";
@@ -104,10 +110,11 @@
public AlsaCardsParser() {}
- public void scan() {
+ public int scan() {
if (DEBUG) {
- Slog.i(TAG, "AlsaCardsParser.scan()");
+ Slog.i(TAG, "AlsaCardsParser.scan()....");
}
+
mCardRecords = new ArrayList<AlsaCardRecord>();
File cardsFile = new File(kCardsFilePath);
@@ -134,11 +141,26 @@
mCardRecords.add(cardRecord);
}
reader.close();
+ if (mCardRecords.size() > 0) {
+ mScanStatus = SCANSTATUS_SUCCESS;
+ } else {
+ mScanStatus = SCANSTATUS_EMPTY;
+ }
} catch (FileNotFoundException e) {
e.printStackTrace();
+ mScanStatus = SCANSTATUS_FAIL;
} catch (IOException e) {
e.printStackTrace();
+ mScanStatus = SCANSTATUS_FAIL;
}
+ if (DEBUG) {
+ Slog.i(TAG, " status:" + mScanStatus);
+ }
+ return mScanStatus;
+ }
+
+ public int getScanStatus() {
+ return mScanStatus;
}
public ArrayList<AlsaCardRecord> getScanRecords() {
@@ -182,7 +204,11 @@
}
// get the new list of devices
- scan();
+ if (scan() != SCANSTATUS_SUCCESS) {
+ Slog.e(TAG, "Error scanning Alsa cards file.");
+ return -1;
+ }
+
if (DEBUG) {
LogDevices("Current Devices:", mCardRecords);
}
diff --git a/core/java/com/android/internal/alsa/AlsaDevicesParser.java b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
index 6e3d596..15261baf 100644
--- a/core/java/com/android/internal/alsa/AlsaDevicesParser.java
+++ b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
@@ -46,6 +46,12 @@
private boolean mHasPlaybackDevices = false;
private boolean mHasMIDIDevices = false;
+ public static final int SCANSTATUS_NOTSCANNED = -1;
+ public static final int SCANSTATUS_SUCCESS = 0;
+ public static final int SCANSTATUS_FAIL = 1;
+ public static final int SCANSTATUS_EMPTY = 2;
+ private int mScanStatus = SCANSTATUS_NOTSCANNED;
+
public class AlsaDeviceRecord {
public static final int kDeviceType_Unknown = -1;
public static final int kDeviceType_Audio = 0;
@@ -258,7 +264,11 @@
return line.charAt(kIndex_CardDeviceField) == '[';
}
- public boolean scan() {
+ public int scan() {
+ if (DEBUG) {
+ Slog.i(TAG, "AlsaDevicesParser.scan()....");
+ }
+
mDeviceRecords.clear();
File devicesFile = new File(kDevicesFilePath);
@@ -274,13 +284,27 @@
}
}
reader.close();
- return true;
+ // success if we add at least 1 record
+ if (mDeviceRecords.size() > 0) {
+ mScanStatus = SCANSTATUS_SUCCESS;
+ } else {
+ mScanStatus = SCANSTATUS_EMPTY;
+ }
} catch (FileNotFoundException e) {
e.printStackTrace();
+ mScanStatus = SCANSTATUS_FAIL;
} catch (IOException e) {
e.printStackTrace();
+ mScanStatus = SCANSTATUS_FAIL;
}
- return false;
+ if (DEBUG) {
+ Slog.i(TAG, " status:" + mScanStatus);
+ }
+ return mScanStatus;
+ }
+
+ public int getScanStatus() {
+ return mScanStatus;
}
//
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index d64c9a1..4a181b2 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -20,6 +20,7 @@
import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.ParceledListSlice;
+import android.media.AudioAttributes;
import android.os.RemoteException;
import android.provider.Settings;
@@ -47,6 +48,7 @@
public static String RETAIL_MODE = "RETAIL_MODE";
public static String USB = "USB";
public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
+ public static String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP";
public static void createAll(Context context) {
final NotificationManager nm = context.getSystemService(NotificationManager.class);
@@ -139,6 +141,17 @@
foregroundChannel.setBlockableSystem(true);
channelsList.add(foregroundChannel);
+ NotificationChannel heavyWeightChannel = new NotificationChannel(
+ HEAVY_WEIGHT_APP,
+ context.getString(R.string.notification_channel_heavy_weight_app),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ heavyWeightChannel.setShowBadge(false);
+ heavyWeightChannel.setSound(null, new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
+ .build());
+ channelsList.add(heavyWeightChannel);
+
nm.createNotificationChannels(channelsList);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 36fd991..dd07ddb 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -681,17 +681,17 @@
}
@Override
- public long getMahDischarge(int which) {
+ public long getUahDischarge(int which) {
return mDischargeCounter.getCountLocked(which);
}
@Override
- public long getMahDischargeScreenOff(int which) {
+ public long getUahDischargeScreenOff(int which) {
return mDischargeScreenOffCounter.getCountLocked(which);
}
@Override
- public long getMahDischargeScreenDoze(int which) {
+ public long getUahDischargeScreenDoze(int which) {
return mDischargeScreenDozeCounter.getCountLocked(which);
}
@@ -3588,7 +3588,7 @@
public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
long realtime) {
- final boolean screenOff = isScreenOff(screenState) || isScreenDoze(screenState);
+ final boolean screenOff = !isScreenOn(screenState);
final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
final boolean updateOnBatteryScreenOffTimeBase =
(unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
@@ -5427,6 +5427,10 @@
elapsedRealtimeUs, which);
}
+ @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
+ return mScreenBrightnessTimer[brightnessBin];
+ }
+
@Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
}
@@ -5520,10 +5524,18 @@
elapsedRealtimeUs, which);
}
+ @Override public Timer getPhoneSignalScanningTimer() {
+ return mPhoneSignalScanningTimer;
+ }
+
@Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
}
+ @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
+ return mPhoneSignalStrengthsTimer[strengthBin];
+ }
+
@Override public long getPhoneDataConnectionTime(int dataType,
long elapsedRealtimeUs, int which) {
return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
@@ -5534,6 +5546,10 @@
return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
}
+ @Override public Timer getPhoneDataConnectionTimer(int dataType) {
+ return mPhoneDataConnectionsTimer[dataType];
+ }
+
@Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
}
@@ -5572,6 +5588,10 @@
return mWifiStateTimer[wifiState].getCountLocked(which);
}
+ @Override public Timer getWifiStateTimer(int wifiState) {
+ return mWifiStateTimer[wifiState];
+ }
+
@Override public long getWifiSupplStateTime(int state,
long elapsedRealtimeUs, int which) {
return mWifiSupplStateTimer[state].getTotalTimeLocked(
@@ -5582,6 +5602,10 @@
return mWifiSupplStateTimer[state].getCountLocked(which);
}
+ @Override public Timer getWifiSupplStateTimer(int state) {
+ return mWifiSupplStateTimer[state];
+ }
+
@Override public long getWifiSignalStrengthTime(int strengthBin,
long elapsedRealtimeUs, int which) {
return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
@@ -5592,6 +5616,10 @@
return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
}
+ @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
+ return mWifiSignalStrengthsTimer[strengthBin];
+ }
+
@Override
public ControllerActivityCounter getBluetoothControllerActivity() {
return mBluetoothActivity;
@@ -9463,7 +9491,7 @@
}
public boolean isScreenOn(int state) {
- return state == Display.STATE_ON;
+ return state == Display.STATE_ON || state == Display.STATE_VR;
}
public boolean isScreenOff(int state) {
@@ -12791,7 +12819,7 @@
mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
mOnBatteryTimeBase, in);
- mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
+ mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
mOnBatteryTimeBase, in);
mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index f76c724..8f80bfe 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -319,13 +319,15 @@
public void setGroupDividerEnabled(boolean groupDividerEnabled) {
// If mHasListDivider is true, disabling the groupDivider.
// Otherwise, checking enbling it according to groupDividerEnabled flag.
- mGroupDivider.setVisibility(!mHasListDivider
- && groupDividerEnabled ? View.VISIBLE : View.GONE);
+ if (mGroupDivider != null) {
+ mGroupDivider.setVisibility(!mHasListDivider
+ && groupDividerEnabled ? View.VISIBLE : View.GONE);
+ }
}
@Override
public void adjustListItemSelectionBounds(Rect rect) {
- if (mGroupDivider.getVisibility() == View.VISIBLE) {
+ if (mGroupDivider != null && mGroupDivider.getVisibility() == View.VISIBLE) {
// groupDivider is a part of MenuItemListView.
// If ListMenuItem with divider enabled is hovered/clicked, divider also gets selected.
// Clipping the selector bounds from the top divider portion when divider is enabled,
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index deb4d5a..95cb616 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -19,6 +19,8 @@
#define LOG_NDEBUG 1
#include <android_runtime/AndroidRuntime.h>
+
+#include <android-base/properties.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -47,8 +49,8 @@
#include <string>
#include <vector>
-
using namespace android;
+using android::base::GetProperty;
extern int register_android_os_Binder(JNIEnv* env);
extern int register_android_os_Process(JNIEnv* env);
@@ -392,17 +394,6 @@
return false;
}
-// Convenience wrapper over the property API that returns an
-// std::string.
-std::string getProperty(const char* key, const char* defaultValue) {
- std::vector<char> temp(PROPERTY_VALUE_MAX);
- const int len = property_get(key, &temp[0], defaultValue);
- if (len < 0) {
- return "";
- }
- return std::string(&temp[0], len);
-}
-
/*
* Read the persistent locale. Inspects the following system properties
* (in order) and returns the first non-empty property in the list :
@@ -419,15 +410,15 @@
*/
const std::string readLocale()
{
- const std::string locale = getProperty("persist.sys.locale", "");
+ const std::string locale = GetProperty("persist.sys.locale", "");
if (!locale.empty()) {
return locale;
}
- const std::string language = getProperty("persist.sys.language", "");
+ const std::string language = GetProperty("persist.sys.language", "");
if (!language.empty()) {
- const std::string country = getProperty("persist.sys.country", "");
- const std::string variant = getProperty("persist.sys.localevar", "");
+ const std::string country = GetProperty("persist.sys.country", "");
+ const std::string variant = GetProperty("persist.sys.localevar", "");
std::string out = language;
if (!country.empty()) {
@@ -441,15 +432,15 @@
return out;
}
- const std::string productLocale = getProperty("ro.product.locale", "");
+ const std::string productLocale = GetProperty("ro.product.locale", "");
if (!productLocale.empty()) {
return productLocale;
}
// If persist.sys.locale and ro.product.locale are missing,
// construct a locale value from the individual locale components.
- const std::string productLanguage = getProperty("ro.product.locale.language", "en");
- const std::string productRegion = getProperty("ro.product.locale.region", "US");
+ const std::string productLanguage = GetProperty("ro.product.locale.language", "en");
+ const std::string productRegion = GetProperty("ro.product.locale.region", "US");
return productLanguage + "-" + productRegion;
}
@@ -649,7 +640,7 @@
char cpuAbiListBuf[sizeof("--cpu-abilist=") + PROPERTY_VALUE_MAX];
char methodTraceFileBuf[sizeof("-Xmethod-trace-file:") + PROPERTY_VALUE_MAX];
char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
- char fingerprintBuf[sizeof("-Xfingerprint:") + PROPERTY_VALUE_MAX];
+ std::string fingerprintBuf;
bool checkJni = false;
property_get("dalvik.vm.checkjni", propBuf, "");
@@ -964,8 +955,15 @@
/*
* Retrieve the build fingerprint and provide it to the runtime. That way, ANR dumps will
* contain the fingerprint and can be parsed.
+ * Fingerprints are potentially longer than PROPERTY_VALUE_MAX, so parseRuntimeOption() cannot
+ * be used here.
+ * Do not ever re-assign fingerprintBuf as its c_str() value is stored in mOptions.
*/
- parseRuntimeOption("ro.build.fingerprint", fingerprintBuf, "-Xfingerprint:");
+ std::string fingerprint = GetProperty("ro.build.fingerprint", "");
+ if (!fingerprint.empty()) {
+ fingerprintBuf = "-Xfingerprint:" + fingerprint;
+ addOption(fingerprintBuf.c_str());
+ }
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index c8eef7f..1628220 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -23,13 +23,13 @@
#include <vector>
#include <cmath>
+#include <android-base/properties.h>
#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
#include <utils/RefBase.h>
#include <utils/Vector.h>
#include <utils/String8.h>
-#include <cutils/properties.h>
#include <system/camera_metadata.h>
#include <camera/CameraMetadata.h>
#include <img_utils/DngUtils.h>
@@ -50,6 +50,7 @@
using namespace android;
using namespace img_utils;
+using android::base::GetProperty;
#define BAIL_IF_INVALID_RET_BOOL(expr, jnienv, tagId, writer) \
if ((expr) != OK) { \
@@ -1237,26 +1238,24 @@
{
// make
- char manufacturer[PROPERTY_VALUE_MAX];
-
// Use "" to represent unknown make as suggested in TIFF/EP spec.
- property_get("ro.product.manufacturer", manufacturer, "");
- uint32_t count = static_cast<uint32_t>(strlen(manufacturer)) + 1;
+ std::string manufacturer = GetProperty("ro.product.manufacturer", "");
+ uint32_t count = static_cast<uint32_t>(manufacturer.size()) + 1;
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_MAKE, count,
- reinterpret_cast<uint8_t*>(manufacturer), TIFF_IFD_0), env, TAG_MAKE, writer);
+ reinterpret_cast<const uint8_t*>(manufacturer.c_str()), TIFF_IFD_0), env, TAG_MAKE,
+ writer);
}
{
// model
- char model[PROPERTY_VALUE_MAX];
-
// Use "" to represent unknown model as suggested in TIFF/EP spec.
- property_get("ro.product.model", model, "");
- uint32_t count = static_cast<uint32_t>(strlen(model)) + 1;
+ std::string model = GetProperty("ro.product.model", "");
+ uint32_t count = static_cast<uint32_t>(model.size()) + 1;
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_MODEL, count,
- reinterpret_cast<uint8_t*>(model), TIFF_IFD_0), env, TAG_MODEL, writer);
+ reinterpret_cast<const uint8_t*>(model.c_str()), TIFF_IFD_0), env, TAG_MODEL,
+ writer);
}
{
@@ -1277,11 +1276,11 @@
{
// software
- char software[PROPERTY_VALUE_MAX];
- property_get("ro.build.fingerprint", software, "");
- uint32_t count = static_cast<uint32_t>(strlen(software)) + 1;
+ std::string software = GetProperty("ro.build.fingerprint", "");
+ uint32_t count = static_cast<uint32_t>(software.size()) + 1;
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_SOFTWARE, count,
- reinterpret_cast<uint8_t*>(software), TIFF_IFD_0), env, TAG_SOFTWARE, writer);
+ reinterpret_cast<const uint8_t*>(software.c_str()), TIFF_IFD_0), env, TAG_SOFTWARE,
+ writer);
}
if (nativeContext->hasCaptureTime()) {
@@ -1613,20 +1612,15 @@
{
// Setup unique camera model tag
- char model[PROPERTY_VALUE_MAX];
- property_get("ro.product.model", model, "");
+ std::string model = GetProperty("ro.product.model", "");
+ std::string manufacturer = GetProperty("ro.product.manufacturer", "");
+ std::string brand = GetProperty("ro.product.brand", "");
- char manufacturer[PROPERTY_VALUE_MAX];
- property_get("ro.product.manufacturer", manufacturer, "");
-
- char brand[PROPERTY_VALUE_MAX];
- property_get("ro.product.brand", brand, "");
-
- String8 cameraModel(model);
+ String8 cameraModel(model.c_str());
cameraModel += "-";
- cameraModel += manufacturer;
+ cameraModel += manufacturer.c_str();
cameraModel += "-";
- cameraModel += brand;
+ cameraModel += brand.c_str();
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_UNIQUECAMERAMODEL, cameraModel.size() + 1,
reinterpret_cast<const uint8_t*>(cameraModel.string()), TIFF_IFD_0), env,
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a9b849e..8ae9ada 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -98,6 +98,18 @@
// ----------------------------------------------------------------------------
+static jlong nativeCreateTransaction(JNIEnv* env, jclass clazz) {
+ return reinterpret_cast<jlong>(new SurfaceComposerClient::Transaction);
+}
+
+static void releaseTransaction(SurfaceComposerClient::Transaction* t) {
+ delete t;
+}
+
+static jlong nativeGetNativeTransactionFinalizer(JNIEnv* env, jclass clazz) {
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&releaseTransaction));
+}
+
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
jint windowType, jint ownerUid) {
@@ -278,69 +290,72 @@
}
}
-static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
- SurfaceComposerClient::openGlobalTransaction();
+static void nativeApplyTransaction(JNIEnv* env, jclass clazz, jlong transactionObj, jboolean sync) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->apply(sync);
}
-
-static void nativeCloseTransaction(JNIEnv* env, jclass clazz, jboolean sync) {
- SurfaceComposerClient::closeGlobalTransaction(sync);
+static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz, jlong transactionObj) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setAnimationTransaction();
}
-static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
- SurfaceComposerClient::setAnimationTransaction();
-}
+static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jint zorder) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
-static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong nativeObject, jint zorder) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setLayer(zorder);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setLayer(ctrl, zorder);
}
-static void nativeSetRelativeLayer(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeSetRelativeLayer(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jobject relativeTo, jint zorder) {
+
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
sp<IBinder> handle = ibinderForJavaObject(env, relativeTo);
- ctrl->setRelativeLayer(handle, zorder);
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setRelativeLayer(ctrl, handle, zorder);
+ }
}
-static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) {
+static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jfloat x, jfloat y) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setPosition(x, y);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setPosition(ctrl, x, y);
}
static void nativeSetGeometryAppliesWithResize(JNIEnv* env, jclass clazz,
+jlong transactionObj,
jlong nativeObject) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setGeometryAppliesWithResize();
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setGeometryAppliesWithResize(ctrl);
}
-static void nativeSetSize(JNIEnv* env, jclass clazz, jlong nativeObject, jint w, jint h) {
+static void nativeSetSize(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jint w, jint h) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setSize(w, h);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setSize(ctrl, w, h);
}
-static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong nativeObject, jint flags, jint mask) {
+static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jint flags, jint mask) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setFlags(flags, mask);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setFlags(ctrl, flags, mask);
}
-static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong nativeObject, jobject regionObj) {
+static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jobject regionObj) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
if (!region) {
@@ -359,65 +374,65 @@
}
}
- status_t err = ctrl->setTransparentRegionHint(reg);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setTransparentRegionHint(ctrl, reg);
}
}
-static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat alpha) {
+static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jfloat alpha) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setAlpha(alpha);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setAlpha(ctrl, alpha);
}
-static void nativeSetColor(JNIEnv* env, jclass clazz, jlong nativeObject, jfloatArray fColor) {
+static void nativeSetColor(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jfloatArray fColor) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+
float* floatColors = env->GetFloatArrayElements(fColor, 0);
half3 color(floatColors[0], floatColors[1], floatColors[2]);
- status_t err = ctrl->setColor(color);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setColor(ctrl, color);
}
-static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jfloat dsdx, jfloat dtdx, jfloat dtdy, jfloat dsdy) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setMatrix(dsdx, dtdx, dtdy, dsdy);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setMatrix(ctrl, dsdx, dtdx, dtdy, dsdy);
}
-static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jint l, jint t, jint r, jint b) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
Rect crop(l, t, r, b);
- status_t err = ctrl->setCrop(crop);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setCrop(ctrl, crop);
}
-static void nativeSetFinalCrop(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeSetFinalCrop(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jint l, jint t, jint r, jint b) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
Rect crop(l, t, r, b);
- status_t err = ctrl->setFinalCrop(crop);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setFinalCrop(ctrl, crop);
}
-static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong nativeObject, jint layerStack) {
+static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jint layerStack) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setLayerStack(layerStack);
- if (err < 0 && err != NO_INIT) {
- doThrowIAE(env);
- }
+ transaction->setLayerStack(ctrl, layerStack);
}
static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
@@ -440,6 +455,7 @@
}
static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
+ jlong transactionObj,
jobject tokenObj, jlong nativeSurfaceObject) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return;
@@ -448,8 +464,14 @@
if (sur != NULL) {
bufferProducer = sur->getIGraphicBufferProducer();
}
- status_t err = SurfaceComposerClient::setDisplaySurface(token,
- bufferProducer);
+
+
+ status_t err = NO_ERROR;
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ err = transaction->setDisplaySurface(token,
+ bufferProducer);
+ }
if (err != NO_ERROR) {
doThrowIAE(env, "Illegal Surface, could not enable async mode. Was this"
" Surface created with singleBufferMode?");
@@ -457,14 +479,20 @@
}
static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
+ jlong transactionObj,
jobject tokenObj, jint layerStack) {
+
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return;
- SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setDisplayLayerStack(token, layerStack);
+ }
}
static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
+ jlong transactionObj,
jobject tokenObj, jint orientation,
jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom,
jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) {
@@ -472,14 +500,23 @@
if (token == NULL) return;
Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom);
Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom);
- SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
+
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setDisplayProjection(token, orientation, layerStackRect, displayRect);
+ }
}
static void nativeSetDisplaySize(JNIEnv* env, jclass clazz,
+ jlong transactionObj,
jobject tokenObj, jint width, jint height) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return;
- SurfaceComposerClient::setDisplaySize(token, width, height);
+
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->setDisplaySize(token, width, height);
+ }
}
static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
@@ -722,52 +759,73 @@
return JNI_TRUE;
}
-static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jobject handleObject, jlong frameNumber) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
sp<IBinder> handle = ibinderForJavaObject(env, handleObject);
- ctrl->deferTransactionUntil(handle, frameNumber);
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->deferTransactionUntil(ctrl, handle, frameNumber);
+ }
}
-static void nativeDeferTransactionUntilSurface(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeDeferTransactionUntilSurface(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jlong surfaceObject, jlong frameNumber) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
sp<Surface> barrier = reinterpret_cast<Surface *>(surfaceObject);
- ctrl->deferTransactionUntil(barrier, frameNumber);
+ transaction->deferTransactionUntil(ctrl, barrier, frameNumber);
}
-static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jobject newParentObject) {
+
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
sp<IBinder> handle = ibinderForJavaObject(env, newParentObject);
- ctrl->reparentChildren(handle);
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->reparentChildren(ctrl, handle);
+ }
}
-static void nativeReparent(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeReparent(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jobject newParentObject) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
sp<IBinder> parentHandle = ibinderForJavaObject(env, newParentObject);
- ctrl->reparent(parentHandle);
+
+ {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->reparent(ctrl, parentHandle);
+ }
}
-static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong nativeObject) {
+static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- ctrl->detachChildren();
+ transaction->detachChildren(ctrl);
}
-static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong nativeObject,
+static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject,
jint scalingMode) {
- auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- ctrl->setOverrideScalingMode(scalingMode);
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ transaction->setOverrideScalingMode(ctrl, scalingMode);
}
static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
-
return javaObjectForIBinder(env, ctrl->getHandle());
}
@@ -802,37 +860,39 @@
(void*)nativeScreenshotBitmap },
{"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
(void*)nativeScreenshot },
- {"nativeOpenTransaction", "()V",
- (void*)nativeOpenTransaction },
- {"nativeCloseTransaction", "(Z)V",
- (void*)nativeCloseTransaction },
- {"nativeSetAnimationTransaction", "()V",
+ {"nativeCreateTransaction", "()J",
+ (void*)nativeCreateTransaction },
+ {"nativeApplyTransaction", "(JZ)V",
+ (void*)nativeApplyTransaction },
+ {"nativeGetNativeTransactionFinalizer", "()J",
+ (void*)nativeGetNativeTransactionFinalizer },
+ {"nativeSetAnimationTransaction", "(J)V",
(void*)nativeSetAnimationTransaction },
- {"nativeSetLayer", "(JI)V",
+ {"nativeSetLayer", "(JJI)V",
(void*)nativeSetLayer },
- {"nativeSetRelativeLayer", "(JLandroid/os/IBinder;I)V",
+ {"nativeSetRelativeLayer", "(JJLandroid/os/IBinder;I)V",
(void*)nativeSetRelativeLayer },
- {"nativeSetPosition", "(JFF)V",
+ {"nativeSetPosition", "(JJFF)V",
(void*)nativeSetPosition },
- {"nativeSetGeometryAppliesWithResize", "(J)V",
+ {"nativeSetGeometryAppliesWithResize", "(JJ)V",
(void*)nativeSetGeometryAppliesWithResize },
- {"nativeSetSize", "(JII)V",
+ {"nativeSetSize", "(JJII)V",
(void*)nativeSetSize },
- {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V",
+ {"nativeSetTransparentRegionHint", "(JJLandroid/graphics/Region;)V",
(void*)nativeSetTransparentRegionHint },
- {"nativeSetAlpha", "(JF)V",
+ {"nativeSetAlpha", "(JJF)V",
(void*)nativeSetAlpha },
- {"nativeSetColor", "(J[F)V",
+ {"nativeSetColor", "(JJ[F)V",
(void*)nativeSetColor },
- {"nativeSetMatrix", "(JFFFF)V",
+ {"nativeSetMatrix", "(JJFFFF)V",
(void*)nativeSetMatrix },
- {"nativeSetFlags", "(JII)V",
+ {"nativeSetFlags", "(JJII)V",
(void*)nativeSetFlags },
- {"nativeSetWindowCrop", "(JIIII)V",
+ {"nativeSetWindowCrop", "(JJIIII)V",
(void*)nativeSetWindowCrop },
- {"nativeSetFinalCrop", "(JIIII)V",
+ {"nativeSetFinalCrop", "(JJIIII)V",
(void*)nativeSetFinalCrop },
- {"nativeSetLayerStack", "(JI)V",
+ {"nativeSetLayerStack", "(JJI)V",
(void*)nativeSetLayerStack },
{"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
(void*)nativeGetBuiltInDisplay },
@@ -840,13 +900,13 @@
(void*)nativeCreateDisplay },
{"nativeDestroyDisplay", "(Landroid/os/IBinder;)V",
(void*)nativeDestroyDisplay },
- {"nativeSetDisplaySurface", "(Landroid/os/IBinder;J)V",
+ {"nativeSetDisplaySurface", "(JLandroid/os/IBinder;J)V",
(void*)nativeSetDisplaySurface },
- {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
+ {"nativeSetDisplayLayerStack", "(JLandroid/os/IBinder;I)V",
(void*)nativeSetDisplayLayerStack },
- {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
+ {"nativeSetDisplayProjection", "(JLandroid/os/IBinder;IIIIIIIII)V",
(void*)nativeSetDisplayProjection },
- {"nativeSetDisplaySize", "(Landroid/os/IBinder;II)V",
+ {"nativeSetDisplaySize", "(JLandroid/os/IBinder;II)V",
(void*)nativeSetDisplaySize },
{"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;",
(void*)nativeGetDisplayConfigs },
@@ -872,17 +932,17 @@
(void*)nativeGetAnimationFrameStats },
{"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V",
(void*)nativeSetDisplayPowerMode },
- {"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V",
+ {"nativeDeferTransactionUntil", "(JJLandroid/os/IBinder;J)V",
(void*)nativeDeferTransactionUntil },
- {"nativeDeferTransactionUntilSurface", "(JJJ)V",
+ {"nativeDeferTransactionUntilSurface", "(JJJJ)V",
(void*)nativeDeferTransactionUntilSurface },
- {"nativeReparentChildren", "(JLandroid/os/IBinder;)V",
+ {"nativeReparentChildren", "(JJLandroid/os/IBinder;)V",
(void*)nativeReparentChildren } ,
- {"nativeReparent", "(JLandroid/os/IBinder;)V",
+ {"nativeReparent", "(JJLandroid/os/IBinder;)V",
(void*)nativeReparent },
- {"nativeSeverChildren", "(J)V",
+ {"nativeSeverChildren", "(JJ)V",
(void*)nativeSeverChildren } ,
- {"nativeSetOverrideScalingMode", "(JI)V",
+ {"nativeSetOverrideScalingMode", "(JJI)V",
(void*)nativeSetOverrideScalingMode },
{"nativeGetHandle", "(J)Landroid/os/IBinder;",
(void*)nativeGetHandle },
diff --git a/core/proto/android/content/intent.proto b/core/proto/android/content/intent.proto
new file mode 100644
index 0000000..f2927a7
--- /dev/null
+++ b/core/proto/android/content/intent.proto
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+option java_package = "android.content";
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/os/patternmatcher.proto";
+
+package android.content;
+
+// Next Tag: 13
+message IntentProto {
+ string action = 1;
+ repeated string categories = 2;
+ string data = 3;
+ string type = 4;
+ string flag = 5;
+ string package = 6;
+ string component = 7;
+ string source_bounds = 8;
+ string clip_data = 9;
+ string extras = 10;
+ int32 content_user_hint = 11;
+ string selector = 12;
+}
+
+// Next Tag: 11
+message IntentFilterProto {
+ repeated string actions = 1;
+ repeated string categories = 2;
+ repeated string data_schemes = 3;
+ repeated android.os.PatternMatcherProto data_scheme_specs = 4;
+ repeated AuthorityEntryProto data_authorities = 5;
+ repeated android.os.PatternMatcherProto data_paths = 6;
+ repeated string data_types = 7;
+ int32 priority = 8;
+ bool has_partial_types = 9;
+ bool get_auto_verify = 10;
+}
+
+message AuthorityEntryProto {
+ string host = 1;
+ bool wild = 2;
+ int32 port = 3;
+}
diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto
index 86e31d0..8d85038 100644
--- a/core/proto/android/os/batterystats.proto
+++ b/core/proto/android/os/batterystats.proto
@@ -20,6 +20,8 @@
package android.os;
+import "frameworks/base/core/proto/android/telephony/signalstrength.proto";
+
message BatteryStatsProto {
int32 report_version = 1;
int64 parcel_version = 2;
@@ -55,6 +57,383 @@
}
message SystemProto {
+ message Battery {
+ // Wall clock time when the data collection started.
+ // In case of device time manually reset by users:
+ // start_clock_time_ms keeps the same value in the current collection
+ // period and changes for later collection periods.
+ int64 start_clock_time_ms = 1;
+ // #times the device has been started since start_clock_time_millis.
+ int64 start_count = 2;
+ // Total realtime duration (= SINCE_UNPLUGGED battery_realtime_millis.)
+ int64 total_realtime_ms = 3;
+ int64 total_uptime_ms = 4;
+ // Realtime duration on battery.
+ int64 battery_realtime_ms = 5;
+ // Uptime duration (i.e., not suspend).
+ // Uptime is anytime the CPUs were on. The radio and Wifi chip
+ // can be running while the CPUs are off.
+ int64 battery_uptime_ms = 6;
+ // Total realtime duration measured with screen off or dozing.
+ int64 screen_off_realtime_ms = 7;
+ // Total uptime duration measured with screen off or dozing.
+ int64 screen_off_uptime_ms = 8;
+ // Total time the screen was dozing while the device was running on battery.
+ // For historical reasons, screen_doze_duration_msec is a subset of
+ // screen_off_realtime_msec.
+ int64 screen_doze_duration_ms = 9;
+ // The estimated real battery capacity, which may be less than the declared
+ // battery capacity (for example, because of battery aging). This field is
+ // less reliable than min(max)_learned_battery_capacity_uah, use those two
+ // fields whenever possible.
+ int64 estimated_battery_capacity_mah = 10;
+ // The minimum learned battery capacity in uAh.
+ int64 min_learned_battery_capacity_uah = 11;
+ // The maximum learned battery capacity in uAh.
+ int64 max_learned_battery_capacity_uah = 12;
+ };
+ Battery battery = 1;
+
+ message BatteryDischarge {
+ // Discharged battery percentage points since the stats were last reset
+ // after charging (lower bound approximation).
+ int32 lower_bound_since_charge = 1;
+ // Upper bound approximation.
+ int32 upper_bound_since_charge = 2;
+ // Discharged points while screen is on.
+ int32 screen_on_since_charge = 3;
+ // Discharged points while screen is off.
+ int32 screen_off_since_charge = 4;
+ // Discharged points while screen was dozing. For historical reasons,
+ // screen_doze_since_charge is a subset of screen_off_since_charge.
+ int32 screen_doze_since_charge = 5;
+ // Total amount of battery discharged in mAh. This will only be non-zero for
+ // devices that report battery discharge via a coulomb counter.
+ int64 total_mah = 6;
+ // Total amount of battery discharged while the screen was off in mAh.
+ // This will only be non-zero for devices that report battery discharge
+ // via a coulomb counter.
+ int64 total_mah_screen_off = 7;
+ // Total amount of battery discharged while the screen was dozing in mAh.
+ // This will only be non-zero for devices that report battery discharge
+ // via a coulomb counter. For historical reasons, total_mah_screen_doze is
+ // a subset of total_mah_screen_off.
+ int64 total_mah_screen_doze = 8;
+ };
+ BatteryDischarge battery_discharge = 2;
+
+ oneof time_remaining {
+ // Approximation for how much time remains until the battery is fully
+ // charged. The device will print -1 if there wasn't enough data to
+ // calculate an estimate, or if the battery is currently discharging.
+ int64 charge_time_remaining_ms = 3;
+ // Approximation for how much time remains until the battery is fully
+ // discharged. The device will print -1 if there wasn't enough data to
+ // calculate an estimate, or if the battery is currently charging.
+ int64 discharge_time_remaining_ms = 4;
+ }
+
+ // BatteryLevelStep tracks data for which conditions were continuously held for
+ // the entire duration. Field for which the conditions were not consistent
+ // for the entire duration should be marked MIXED.
+ message BatteryLevelStep {
+ // How long the battery was at the current level.
+ int64 duration_ms = 1;
+ // Battery level
+ int32 level = 2;
+
+ // State of the display. A special enum is used rather than
+ // DisplayProto.State because a MIXED value needs to be in the enum, and
+ // batterystats doesn't care about all of the different display states.
+ enum DisplayState {
+ DS_MIXED = 0;
+ DS_ON = 1;
+ DS_OFF = 2;
+ DS_DOZE = 3;
+ DS_DOZE_SUSPEND = 4;
+ // Any display state error that comes through should be sent to hackbod@.
+ DS_ERROR = 5;
+ }
+ // The state of the display for the entire battery level step. MIXED is used
+ // if there were multiple states for this step.
+ DisplayState display_state = 3;
+
+ // Indicates status in power save mode.
+ enum PowerSaveMode {
+ PSM_MIXED = 0;
+ PSM_ON = 1;
+ PSM_OFF = 2;
+ }
+ // Battery Saver mode for the entire battery level step. MIXED is used
+ // if there were multiple states for this step.
+ PowerSaveMode power_save_mode = 4;
+
+ // Indicates status in idle mode.
+ enum IdleMode {
+ IM_MIXED = 0;
+ IM_ON = 2;
+ IM_OFF = 3;
+ }
+ // Doze mode for the entire battery level step. MIXED is used if there were
+ // multiple states for this step.
+ IdleMode idle_mode = 5;
+ };
+ // Battery level steps when the device was charging.
+ repeated BatteryLevelStep charge_step = 5;
+ // Battery level steps when the device was discharging.
+ repeated BatteryLevelStep discharge_step = 6;
+
+ // All CPU frequencies of the device.
+ repeated int64 cpu_frequency = 7;
+
+ message DataConnection {
+ enum Name {
+ NONE = 0;
+ GPRS = 1;
+ EDGE = 2;
+ UMTS = 3;
+ CDMA = 4;
+ EVDO_0 = 5;
+ EVDO_A = 6;
+ ONE_X_RTT = 7; // 1xRTT.
+ HSDPA = 8;
+ HSUPA = 9;
+ HSPA = 10;
+ IDEN = 11;
+ EVDO_B = 12;
+ LTE = 13;
+ EHRPD = 14;
+ HSPAP = 15;
+ OTHER = 16;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated DataConnection data_connection = 8;
+
+ ControllerActivityProto global_bluetooth_controller = 9;
+ ControllerActivityProto global_modem_controller = 10;
+ ControllerActivityProto global_wifi_controller = 11;
+
+ message GlobalNetwork {
+ // Total Bytes received on mobile connections.
+ int64 mobile_bytes_rx = 1;
+ // Total Bytes transmitted on mobile connections.
+ int64 mobile_bytes_tx = 2;
+ // Total Bytes received on wifi connections.
+ int64 wifi_bytes_rx = 3;
+ // Total Bytes transmitted on wifi connections.
+ int64 wifi_bytes_tx = 4;
+ // Total Packets received on mobile connections.
+ int64 mobile_packets_rx = 5;
+ // Total Packets transmitted on mobile connections.
+ int64 mobile_packets_tx = 6;
+ // Total Packets received on wifi connections.
+ int64 wifi_packets_rx = 7;
+ // Total Packets transmitted on wifi connections.
+ int64 wifi_packets_tx = 8;
+ // Total Bytes received on bluetooth connections.
+ int64 bt_bytes_rx = 9;
+ // Total Bytes transmitted on bluetooth connections.
+ int64 bt_bytes_tx = 10;
+ };
+ GlobalNetwork global_network = 12;
+
+ message GlobalWifi {
+ // The amount of time that wifi has been on while the device was running on
+ // battery.
+ int64 on_duration_ms = 1;
+ // The amount of time that wifi has been on and the driver has been in the
+ // running state while the device was running on battery.
+ int64 running_duration_ms = 2;
+ }
+ GlobalWifi global_wifi = 13;
+
+ // Kernel wakelock metrics are only recorded when the device is unplugged
+ // *and* the screen is off.
+ message KernelWakelock {
+ string name = 1;
+ // Kernel wakelock stats aren't apportioned across all kernel wakelocks (as
+ // app wakelocks stats are).
+ TimerProto total = 2;
+ // The kernel doesn't have the data to enable printing out current and max
+ // durations.
+ };
+ repeated KernelWakelock kernel_wakelock = 14;
+
+ message Misc {
+ int64 screen_on_duration_ms = 1;
+ int64 phone_on_duration_ms = 2;
+ int64 full_wakelock_total_duration_ms = 3;
+ // The total elapsed time that a partial wakelock was held. This duration
+ // does not double count wakelocks held at the same time.
+ int64 partial_wakelock_total_duration_ms = 4;
+ int64 mobile_radio_active_duration_ms = 5;
+ // The time that is the difference between the mobile radio time we saw
+ // based on the elapsed timestamp when going down vs. the given time stamp
+ // from the radio.
+ int64 mobile_radio_active_adjusted_time_ms = 6;
+ int32 mobile_radio_active_count = 7;
+ // The amount of time that the mobile network has been active (in a high
+ // power state) but not being able to blame on an app.
+ int32 mobile_radio_active_unknown_duration_ms = 8;
+ // Total amount of time the device was in the interactive state.
+ int64 interactive_duration_ms = 9;
+ int64 battery_saver_mode_enabled_duration_ms = 10;
+ int32 num_connectivity_changes = 11;
+ // Amount of time the device was in deep Doze.
+ int64 deep_doze_enabled_duration_ms = 12;
+ // How many times the device went into deep Doze mode.
+ int32 deep_doze_count = 13;
+ // Amount of time the device was idling in deep Doze. Idling time
+ // encompasses "doze" time and the maintenance windows that allow apps to
+ // operate.
+ int64 deep_doze_idling_duration_ms = 14;
+ // How many times the device idling for deep Doze mode.
+ int32 deep_doze_idling_count = 15;
+ int64 longest_deep_doze_duration_ms = 16;
+ // Amount of time the device was in Doze Light.
+ int64 light_doze_enabled_duration_ms = 17;
+ // How many times the device went into Doze Light mode.
+ int32 light_doze_count = 18;
+ // Amount of time the device was idling in Doze Light. Idling time
+ // encompasses "doze" time and the maintenance windows that allow apps to
+ // operate.
+ int64 light_doze_idling_duration_ms = 19;
+ // How many times the device idling for Doze Light mode.
+ int32 light_doze_idling_count = 20;
+ int64 longest_light_doze_duration_ms = 21;
+ }
+ Misc misc = 15;
+
+ message PhoneSignalStrength {
+ android.telephony.SignalStrengthProto.StrengthName name = 1;
+ TimerProto total = 2;
+ };
+ repeated PhoneSignalStrength phone_signal_strength = 16;
+
+ message PowerUseItem {
+ enum Sipper {
+ UNKNOWN_SIPPER = 0;
+ IDLE = 1;
+ CELL = 2;
+ PHONE = 3;
+ WIFI = 4;
+ BLUETOOTH = 5;
+ FLASHLIGHT = 6;
+ SCREEN = 7;
+ USER = 8;
+ UNACCOUNTED = 9;
+ OVERCOUNTED = 10;
+ CAMERA = 11;
+ MEMORY = 12;
+ };
+ Sipper name = 1;
+ // UID, only valid for the USER sipper.
+ int32 uid = 2;
+ // Estimated power use in mAh.
+ double computed_power_mah = 3;
+ // Starting in Oreo, Battery Settings has two modes to display the battery
+ // info. The first is "app usage list". In this mode, items with should_hide
+ // enabled are hidden.
+ bool should_hide = 4;
+ // Smeared power from screen usage. Screen usage power is split and smeared
+ // among apps, based on activity time.
+ double screen_power_mah = 5;
+ // Smeared power using proportional method. Power usage from hidden sippers
+ // is smeared to all apps proportionally (except for screen usage).
+ double proportional_smear_mah = 6;
+ };
+ repeated PowerUseItem power_use_item = 17;
+
+ message PowerUseSummary {
+ double battery_capacity_mah = 1;
+ double computed_power_mah = 2;
+ // Lower bound of actual power drained.
+ double min_drained_power_mah = 3;
+ // Upper bound of actual power drained.
+ double max_drained_power_mah = 4;
+ };
+ PowerUseSummary power_use_summary = 18;
+
+ message ResourcePowerManager {
+ string name = 1;
+ TimerProto total = 2;
+ TimerProto screen_off = 3;
+ }
+ ResourcePowerManager resource_power_manager = 19;
+
+ message ScreenBrightness {
+ enum Name {
+ DARK = 0; // Not screen-off.
+ DIM = 1;
+ MEDIUM = 2;
+ LIGHT = 3;
+ BRIGHT = 4;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated ScreenBrightness screen_brightness = 20;
+
+ // Duration and number of times trying to acquire a signal
+ TimerProto signal_scanning = 21;
+
+ message WakeupReason {
+ string name = 1;
+ TimerProto total = 2;
+ };
+ repeated WakeupReason wakeup_reason = 22;
+
+ message WifiSignalStrength {
+ enum Name {
+ NONE = 0;
+ POOR = 1;
+ MODERATE = 2;
+ GOOD = 3;
+ GREAT = 4;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated WifiSignalStrength wifi_signal_strength = 23;
+
+ message WifiState {
+ enum Name {
+ OFF = 0;
+ OFF_SCANNING = 1;
+ ON_NO_NETWORKS = 2;
+ ON_DISCONNECTED = 3;
+ ON_CONNECTED_STA = 4;
+ ON_CONNECTED_P2P = 5;
+ ON_CONNECTED_STA_P2P = 6;
+ SOFT_AP = 7;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated WifiState wifi_state = 24;
+
+ message WifiSupplicantState {
+ enum Name {
+ INVALID = 0;
+ DISCONNECTED = 1;
+ INTERFACE_DISABLED = 2;
+ INACTIVE = 3;
+ SCANNING = 4;
+ AUTHENTICATING = 5;
+ ASSOCIATING = 6;
+ ASSOCIATED = 7;
+ FOUR_WAY_HANDSHAKE = 8;
+ GROUP_HANDSHAKE = 9;
+ COMPLETED = 10;
+ DORMANT = 11;
+ UNINITIALIZED = 12;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated WifiSupplicantState wifi_supplicant_state = 25;
}
message TimerProto {
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index b3a606f..884d740 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -32,6 +32,7 @@
import "frameworks/base/core/proto/android/service/power.proto";
import "frameworks/base/core/proto/android/service/print.proto";
import "frameworks/base/core/proto/android/service/procstats.proto";
+import "frameworks/base/core/proto/android/server/activitymanagerservice.proto";
import "frameworks/base/core/proto/android/providers/settings.proto";
import "frameworks/base/core/proto/android/os/incidentheader.proto";
import "frameworks/base/core/proto/android/os/kernelwake.proto";
@@ -108,4 +109,17 @@
(section).type = SECTION_DUMPSYS,
(section).args = "procstats --proto"
];
+
+ com.android.server.am.proto.ActivityStackSupervisorProto activities = 3012 [
+ (section).type = SECTION_DUMPSYS,
+ (section).args = "activity --proto activities"
+ ];
+
+ com.android.server.am.proto.BroadcastProto broadcasts = 3013 [
+ (section).type = SECTION_DUMPSYS,
+ (section).args = "activity --proto broadcasts"
+ ];
+
+ com.android.server.am.proto.ServiceProto amservices = 3014;
+ com.android.server.am.proto.ProcessProto amprocesses = 3015;
}
diff --git a/core/proto/android/os/patternmatcher.proto b/core/proto/android/os/patternmatcher.proto
new file mode 100644
index 0000000..cd68245
--- /dev/null
+++ b/core/proto/android/os/patternmatcher.proto
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+option java_multiple_files = true;
+
+package android.os;
+
+message PatternMatcherProto {
+ string pattern = 1;
+
+ enum Type {
+ TYPE_LITERAL = 0;
+ TYPE_PREFIX = 1;
+ TYPE_SIMPLE_GLOB = 2;
+ TYPE_ADVANCED_GLOB = 3;
+ }
+ Type type = 2;
+
+ // This data is too much for dump
+ // repeated int32 parsed_pattern = 3;
+}
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index d5ecacc..fe5e3f1 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -16,8 +16,11 @@
syntax = "proto3";
+import "frameworks/base/core/proto/android/content/intent.proto";
+import "frameworks/base/core/proto/android/server/intentresolver.proto";
import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
import "frameworks/base/core/proto/android/graphics/rect.proto";
+import "frameworks/base/core/proto/android/os/looper.proto";
package com.android.server.am.proto;
@@ -25,6 +28,12 @@
message ActivityManagerServiceProto {
ActivityStackSupervisorProto activities = 1;
+
+ BroadcastProto broadcasts = 2;
+
+ ServiceProto services = 3;
+
+ ProcessProto processes = 4;
}
message ActivityStackSupervisorProto {
@@ -81,4 +90,86 @@
message KeyguardControllerProto {
bool keyguard_showing = 1;
bool keyguard_occluded = 2;
-}
\ No newline at end of file
+}
+
+message BroadcastProto {
+ repeated ReceiverListProto receiver_list = 1;
+
+ .com.android.server.IntentResolverProto receiver_resolver = 2;
+
+ repeated BroadcastQueueProto broadcast_queue = 3;
+
+ repeated StickyBroadcastProto sticky_broadcasts = 4;
+
+ message MainHandler {
+ string handler = 1;
+ .android.os.LooperProto looper = 2;
+ }
+ MainHandler handler = 5;
+}
+
+message ReceiverListProto {
+ ProcessRecordProto app = 1;
+ int32 pid = 2;
+ int32 uid = 3;
+ int32 user = 4;
+ BroadcastRecordProto current = 5;
+ bool linked_to_death = 6;
+ repeated BroadcastFilterProto filters = 7;
+ string hex_hash = 8; // this hash is used to find the object in IntentResolver
+}
+
+message ProcessRecordProto {
+ int32 pid = 1;
+ string process_name = 2;
+ int32 uid = 3;
+ int32 user_id = 4;
+ int32 app_id = 5;
+ int32 isolated_app_id = 6;
+}
+
+message BroadcastRecordProto {
+ int32 user_id = 1;
+ string intent_action = 2;
+}
+
+message BroadcastFilterProto {
+ .android.content.IntentFilterProto intent_filter = 1;
+ string required_permission = 2;
+ string hex_hash = 3; // used to find the object in IntentResolver
+ int32 owning_user_id = 4;
+}
+
+message BroadcastQueueProto {
+ string queue_name = 1;
+ repeated BroadcastRecordProto parallel_broadcasts = 2;
+ repeated BroadcastRecordProto ordered_broadcasts = 3;
+ BroadcastRecordProto pending_broadcast = 4;
+ repeated BroadcastRecordProto historical_broadcasts = 5;
+
+ message BroadcastSummary {
+ .android.content.IntentProto intent = 1;
+ int64 enqueue_clock_time_ms = 2;
+ int64 dispatch_clock_time_ms = 3;
+ int64 finish_clock_time_ms = 4;
+ }
+ repeated BroadcastSummary historical_broadcasts_summary = 6;
+}
+
+message StickyBroadcastProto {
+ int32 user = 1;
+
+ message StickyAction {
+ string name = 1;
+ repeated .android.content.IntentProto intents = 2;
+ }
+ repeated StickyAction actions = 2;
+}
+
+message ServiceProto {
+ // TODO: "dumpsys activity --proto services"
+}
+
+message ProcessProto {
+ // TODO: "dumpsys activity --proto processes"
+}
diff --git a/core/proto/android/server/intentresolver.proto b/core/proto/android/server/intentresolver.proto
new file mode 100644
index 0000000..62ec2ea
--- /dev/null
+++ b/core/proto/android/server/intentresolver.proto
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+option java_multiple_files = true;
+
+package com.android.server;
+
+message IntentResolverProto {
+
+ message ArrayMapEntry {
+ string key = 1;
+ repeated string values = 2;
+ }
+
+ repeated ArrayMapEntry full_mime_types = 1;
+ repeated ArrayMapEntry base_mime_types = 2;
+ repeated ArrayMapEntry wild_mime_types = 3;
+ repeated ArrayMapEntry schemes = 4;
+ repeated ArrayMapEntry non_data_actions = 5;
+ repeated ArrayMapEntry mime_typed_actions = 6;
+}
+
diff --git a/core/proto/android/telephony/signalstrength.proto b/core/proto/android/telephony/signalstrength.proto
new file mode 100644
index 0000000..ff230cb
--- /dev/null
+++ b/core/proto/android/telephony/signalstrength.proto
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+option java_package = "android.telephony";
+option java_multiple_files = true;
+
+package android.telephony;
+
+/**
+ * An android.telephony.SignalStrength object.
+ */
+message SignalStrengthProto {
+ enum StrengthName {
+ SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+ SIGNAL_STRENGTH_POOR = 1;
+ SIGNAL_STRENGTH_MODERATE = 2;
+ SIGNAL_STRENGTH_GOOD = 3;
+ SIGNAL_STRENGTH_GREAT = 4;
+ }
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ff579a6..3d5ae3d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -551,6 +551,9 @@
<protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
<protected-broadcast android:name="com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
+ <!-- Made protected in P (was introduced in JB-MR2) -->
+ <protected-broadcast android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 5d6f04f..8bc50b5 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Werkprofiel is weens ontbrekende administrasieprogram uitgevee"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Die werkprofiel se administrasieprogram ontbreek of is korrup. Gevolglik is jou werkprofiel en verwante data uitgevee. Kontak jou administrateur vir bystand."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Jou werkprofiel is nie meer op hierdie toestel beskikbaar nie"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Te veel wagwoordpogings"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Toestel word bestuur"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Jou organisasie bestuur hierdie toestel en kan netwerkverkeer monitor. Tik vir besonderhede."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Jou toestel sal uitgevee word"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM word nie toegelaat nie"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Foon word nie toegelaat nie"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Opspringvenster"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ffae89c..77a0ed7 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"ሲም አይፈቀድም"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ስልክ አይፈቀድም"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ብቅ-ባይ መስኮት"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 4b20e74..7b516c5 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -180,8 +180,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"تم حذف الملف الشخصي للعمل نتيجة فقد تطبيق المشرف"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"تطبيق المشرف للملف الشخصي للعمل مفقود أو تالف لذا تم حذف الملف الشخصي للعمل والبيانات ذات الصلة. اتصل بالمشرف للحصول على المساعدة."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"لم يعد ملفك الشخصي للعمل متاحًا على هذا الجهاز"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"تم إجراء محاولات كثيرة جدًا لإدخال كلمة المرور"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"تتم إدارة الجهاز"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"تدير مؤسستك هذا الجهاز ويمكنها مراقبة حركة بيانات الشبكة. يمكنك النقر للحصول على تفاصيل."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"سيتم محو بيانات جهازك."</string>
@@ -1930,4 +1929,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"غير مسموح باستخدام SIM"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"غير مسموح باستخدام الهاتف"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"نافذة منبثقة"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 7ff8d04..8ff588b 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-ə icazə verilmir"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefona icazə verilmir"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Popap Pəncərəsi"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index bc1e5ab..b1e1117 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -174,8 +174,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Profil za Work je izbrisan jer nedostaje aplikacija za administratore"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Aplikacija za administratore na profilu za Work nedostaje ili je oštećena. Zbog toga su profil za Work i povezani podaci izbrisani. Obratite se administratoru za pomoć."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Profil za Work više nije dostupan na ovom uređaju"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Previše pokušaja unosa lozinke"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Uređajem se upravlja"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organizacija upravlja ovim uređajem i može da nadgleda mrežni saobraćaj. Dodirnite za detalje."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Uređaj će biti obrisan"</string>
@@ -1825,4 +1824,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM kartica nije dozvoljena"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon nije dozvoljen"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Iskačući prozor"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index b643078..42937df 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -176,8 +176,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Працоўны профіль выдалены з-за адсутнасці праграмы адміністратара"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Праграма адміністратара для працоўнага профілю адсутнічае або пашкоджана. У выніку гэтага ваш працоўны профіль і звязаныя з ім даныя былі выдалены. Звярніцеся па дапамогу да адміністратара."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Ваш працоўны профіль больш не даступны на гэтай прыладзе"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Занадта шмат спроб уводу пароля"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Прылада знаходзіцца пад кіраваннем"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Ваша арганізацыя кіруе гэтай прыладай і можа сачыць за сеткавым трафікам. Дакраніцеся для атрымання дадатковай інфармацыі."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Даныя вашай прылады будуць сцерты"</string>
@@ -1860,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-карта не дапускаецца"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Тэлефон не дапускаецца"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Выплыўное акно"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 44df773..5643b7d 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM картата не е разрешена"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Телефонът не е разрешен"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Изскачащ прозорец"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 76a6b0e..48b8e64 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"প্রশাসক অ্যাপ না থাকায় কর্মস্থলের প্রোফাইল মুছে ফেলা হয়েছে"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"কর্মস্থলের প্রোফাইলের প্রশাসক অ্যাপটি হয় নেই, অথবা সেটি ক্ষতিগ্রস্ত হয়েছে৷ এর ফলে আপনার কর্মস্থলের প্রোফাইল এবং সম্পর্কিত ডেটা মুছে ফেলা হয়েছে৷ সহায়তার জন্য আপনার প্রশাসকের সাথে যোগাযোগ করুন৷"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"আপনার কর্মস্থলের প্রোফাইলটি আর এই ডিভাইসে নেই"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"বহুবার ভুল পাসওয়ার্ড দিয়েছেন"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"ডিভাইসটি পরিচালনা করা হচ্ছে"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"আপনার প্রতিষ্ঠান এই ডিভাইসটি পরিচালনা করে এবং এটির নেটওয়ার্ক ট্রাফিকের উপরে নজর রাখতে পারে। বিশদ বিবরণের জন্য ট্যাপ করুন।,"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"আপনার ডিভাইসটি মুছে ফেলা হবে"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"সিম অনুমোদিত নয়"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ফোন অনুমোদিত নয়"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"পপ-আপ উইন্ডো"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 0778b0d..c4a6d69 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -174,8 +174,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Radni profil je izbrisan jer nedostaje aplikacija administratora"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Nedostaje aplikacija administratora za radni profil ili je neispravna. Zbog toga su vaš radni profil i povezani podaci izbrisani. Obratite administratoru za pomoć."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Radni profil više nije dostupan na ovom uređaju"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Previše puta ste pokušali otključati uređaj"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Uređajem se upravlja."</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Vaša organizacija upravlja ovim uređajem i može pratiti mrežni saobraćaj. Dodirnite za detalje."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Uređaj će biti izbrisan"</string>
@@ -1827,4 +1826,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM kartica nije dozvoljena"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon nije dozvoljen"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Iskočni prozor"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index d910bf73..af48cf7 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"S\'ha suprimit el perfil professional perquè falta l\'aplicació d\'administració"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Falta l\'aplicació d\'administració del perfil professional o està malmesa. Com a conseqüència, s\'han suprimit el teu perfil professional i les dades relacionades. Contacta amb l\'administrador per obtenir ajuda."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"El teu perfil professional ja no està disponible en aquest dispositiu"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Has intentat introduir la contrasenya massa vegades"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"El dispositiu està gestionat"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"La teva organització gestiona aquest dispositiu i és possible que supervisi el trànsit de xarxa. Toca per obtenir més informació."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"El contingut del dispositiu s\'esborrarà"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM no compatible"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telèfon no no compatible"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Finestra emergent"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index c0760b1..d1029e6 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -176,8 +176,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Pracovní profil byl smazán, protože není k dispozici aplikace pro správu"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Aplikace pro správu pracovního profilu chybí nebo je poškozena. Váš pracovní profil a související data proto byla smazána. Požádejte o pomoc administrátora."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Váš pracovní profil v tomto zařízení již není k dispozici"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Příliš mnoho pokusů o zadání hesla"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Zařízení je spravováno"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Toto zařízení je spravováno vaší organizací, která může sledovat síťový provoz. Podrobnosti zobrazíte klepnutím."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Zařízení bude vymazáno"</string>
@@ -1860,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM karta není povolena"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon není povolen"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Vyskakovací okno"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 7b941b3..66af879 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Arbejdsprofilen blev slettet, fordi der mangler en administrationsapp"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Administrationsappen til arbejdsprofilen mangler eller er beskadiget. Derfor er din arbejdsprofil og dine relaterede data blevet slettet. Kontakt din administrator for at få hjælp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Din arbejdsprofil er ikke længere tilgængelig på denne enhed"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"For mange mislykkede adgangskodeforsøg"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Dette er en administreret enhed"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Din organisation administrerer denne enhed og kan overvåge netværkstrafik. Tryk for at se oplysninger."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Enheden slettes"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-kortet har ikke adgangstilladelse"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefonen har ikke adgangstilladelse"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pop op-vindue"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 68b0355..f76408a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Arbeitsprofil aufgrund fehlender Admin-App gelöscht"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Die Admin-App für das Arbeitsprofil fehlt oder ist beschädigt. Daher wurden dein Arbeitsprofil und alle zugehörigen Daten gelöscht. Bitte wende dich für weitere Hilfe an deinen Administrator."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Dein Arbeitsprofil ist auf diesem Gerät nicht mehr verfügbar"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Zu viele falsche Passworteingaben"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Dies ist ein verwaltetes Gerät"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Deine Organisation verwaltet dieses Gerät und überprüft unter Umständen den Netzwerkverkehr. Tippe hier, um weitere Informationen zu erhalten."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Die Daten auf deinem Gerät werden gelöscht."</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-Karte nicht zulässig"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Smartphone nicht zulässig"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pop-up-Fenster"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 9ca0a86..d2cc930 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Το προφίλ εργασίας διαγράφηκε λόγω απουσίας της εφαρμογής διαχείρισης"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Η εφαρμογή διαχείρισης προφίλ εργασίας είτε λείπει είτε είναι κατεστραμμένη. Ως αποτέλεσμα, διαγράφηκε το προφίλ εργασίας και τα σχετικά δεδομένα. Επικοινωνήστε με τον διαχειριστή σας για βοήθεια."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Το προφίλ εργασίας σας δεν είναι πια διαθέσιμο σε αυτήν τη συσκευή"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Πάρα πολλές προσπάθειες εισαγωγής κωδικού πρόσβασης"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Η συσκευή είναι διαχειριζόμενη"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Ο οργανισμός σας διαχειρίζεται αυτήν τη συσκευή και ενδέχεται να παρακολουθεί την επισκεψιμότητα δικτύου. Πατήστε για λεπτομέρειες."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Η συσκευή σας θα διαγραφεί"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Η κάρτα SIM δεν επιτρέπεται"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Το τηλέφωνο δεν επιτρέπεται"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Αναδυόμενο παράθυρο"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 73e55da..ad03374 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM not allowed"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Phone not allowed"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pop-Up Window"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 73e55da..ad03374 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM not allowed"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Phone not allowed"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pop-Up Window"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 73e55da..ad03374 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM not allowed"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Phone not allowed"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pop-Up Window"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 73e55da..ad03374 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM not allowed"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Phone not allowed"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pop-Up Window"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index db7ab4f..d6da98d 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM not allowed"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Phone not allowed"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Popup Window"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 16a43ba..ea8b54e 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM no permitida"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Teléfono no permitido"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Ventana emergente"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 5827a97..6164bac 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM no compatible"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Teléfono no compatible"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Ventana emergente"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 1d40f4a..b48afe0 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-kaart pole lubatud"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon pole lubatud"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Hüpikaken"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index a864f94..98b5f5a 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Ez da onartzen SIM txartela"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Ez da onartzen telefonoa"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Leiho gainerakorra"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 77336ff..9385f58 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"به دلیل نداشتن برنامه سرپرست، نمایه کاری حذف شد"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"برنامه سرپرست نمایه کاری یا وجود ندارد یا خراب است. در نتیجه، نمایه کاری شما و دادههای مرتبط با آن حذف شده است. برای دریافت راهنمایی با سرپرست سیستم تماس بگیرید."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"نمایه کاری شما دیگر در این دستگاه دردسترس نیست"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"تلاشهای بسیار زیادی برای وارد کردن گذرواژه انجام شده است"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"دستگاه مدیریت میشود"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"سازمانتان این دستگاه را مدیریت میکند و ممکن است ترافیک شبکه را پایش کند. برای اطلاع از جزئیات، ضربه بزنید."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"دستگاهتان پاک خواهد شد"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"سیمکارت مجاز نیست"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"تلفن مجاز نیست"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"پنجره بازشو"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 0c4e883..c523452 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-kortti estetty"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Puhelin estetty"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Ponnahdusikkuna"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index a8ab142..4f6b3aa 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Profil professionnel supprimé en raison de l\'application d\'administration manquante"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Le profil professionnel de l\'application d\'administration est manquant ou corrompu. Votre profil professionnel et ses données connexes ont donc été supprimés. Communiquez avec votre administrateur pour obtenir de l\'assistance."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Votre profil professionnel n\'est plus accessible sur cet appareil"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Trop de tentatives d\'entrée du mot de passe"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"L\'appareil est géré"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Votre organisation gère cet appareil et peut surveiller le trafic réseau. Touchez ici pour obtenir plus d\'information."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Le contenu de votre appareil sera effacé"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Carte SIM non autorisée"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Téléphone non autorisé"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Fenêtre contextuelle"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4c2bcca..92838e4 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Carte SIM non autorisée"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Téléphone non autorisé"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Fenêtre pop-up"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 12cbbb3..6d56700 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Eliminouse o perfil de traballo porque falta a aplicación de administración"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Falta a aplicación de administración do perfil de traballo ou ben está danada. Como resultado, eliminouse o teu perfil de traballo e os datos relacionados. Para obter asistencia, contacta co administrador."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"O teu perfil de traballo xa non está dispoñible neste dispositivo"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Demasiados intentos de introdución do contrasinal"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"O dispositivo está xestionado"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"A túa organización xestiona este dispositivo e pode controlar o tráfico de rede. Toca para obter máis detalles."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Borrarase o teu dispositivo"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Non se admite a tarxeta SIM"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Non se admite o teléfono"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Ventá emerxente"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 4cb735d..afc082b 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"ખૂટતી વ્યવસ્થાપક ઍપ્લિકેશનને કારણે કાર્યાલયની પ્રોફાઇલ કાઢી નાખી"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"કાર્ય પ્રોફાઇલ વ્યવસ્થાપક ઍપ્લિકેશન ખૂટે છે અથવા તો દૂષિત છે. પરિણામે, તમારી કાર્યાલયની પ્રોફાઇલ અને તે સંબંધિત ડેટા કાઢી નાખવામાં આવ્યો છે. સહાયતા માટે તમારા વ્યવસ્થાપકનો સંપર્ક કરો."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"આ ઉપકરણ પર તમારી કાર્યાલયની પ્રોફાઇલ હવે ઉપલબ્ધ નથી"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"પાસવર્ડના ઘણા વધુ પ્રયત્નો"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"ઉપકરણ સંચાલિત છે"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"તમારી સંસ્થા આ ઉપકરણનું સંચાલન કરે છે અને નેટવર્ક ટ્રાફિફનું નિયમન કરી શકે છે. વિગતો માટે ટૅપ કરો."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"તમારું ઉપકરણ કાઢી નાખવામાં આવશે"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"સિમ મંજૂર નથી"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ફોન મંજૂર નથી"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"પૉપઅપ વિંડો"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 3e37771..925565a 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"अनुपलब्ध व्यवस्थापक ऐप्लिकेशन के कारण कार्य प्रोफ़ाइल हटा दी गई"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"कार्य प्रोफ़ाइल व्यवस्थापक ऐप्लिकेशन या तो मौजूद नहीं है या वह खराब हो गया है. परिणामस्वरूप, आपकी कार्य प्रोफ़ाइल और उससे जुड़े डेटा को हटा दिया गया है. सहायता के लिए अपने व्यवस्थापक से संपर्क करें."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"आपकी कार्य प्रोफ़ाइल अब इस डिवाइस पर उपलब्ध नहीं है"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"कई बार गलत पासवर्ड डाला गया"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"डिवाइस प्रबंधित है"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"आपका संगठन इस डिवाइस का प्रबंधन करता है और वह नेटवर्क ट्रैफ़िक की निगरानी भी कर सकता है. विवरण के लिए टैप करें."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"आपके डिवाइस को मिटा दिया जाएगा"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM की अनुमति नहीं है"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"फ़ोन की अनुमति नहीं है"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"पॉपअप विंडो"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 3c295c8..a7fa3ce 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -174,8 +174,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Radni je profil izbrisan jer nedostaje administratorska aplikacija"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Administratorska aplikacija radnog profila nedostaje ili je oštećena. Zbog toga su radni profil i povezani podaci izbrisani. Za pomoć se obratite svom administratoru."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Vaš radni profil više nije dostupan na ovom uređaju"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Previše pokušaja unosa zaporke"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Uređaj je upravljan"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Vaša organizacija upravlja ovim uređajem i može nadzirati mrežni promet. Dodirnite za pojedinosti."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Uređaj će se izbrisati"</string>
@@ -1825,4 +1824,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM nije dopušten"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon nije dopušten"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Skočni prozor"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4e8d03c..b1ef463 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"A munkaprofilt a rendszer hiányzó rendszergazdai alkalmazás miatt törölte"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"A munkaprofil rendszergazdai alkalmazása hiányzik vagy sérült. A rendszer ezért törölte a munkaprofilt, és az ahhoz kapcsolódó adatokat. Ha segítségre van szüksége, vegye fel a kapcsolatot rendszergazdájával."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Munkaprofilja már nem hozzáférhető ezen az eszközön."</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Túl sok jelszómegadási kísérlet"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Felügyelt eszköz"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Ezt az eszközt szervezete kezeli, és lehetséges, hogy a hálózati forgalmat is figyelik. További részletekért koppintson."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"A rendszer törölni fogja eszközét"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"A SIM-kártya nem engedélyezett"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"A telefon nem engedélyezett"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Előugró ablak"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index a5fbe34f..b367c67 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM քարտի օգտագործումն արգելված է"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Հեռախոսի օգտագործումն արգելված է"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Հայտնվող պատուհան"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 173ad40..a9d4316 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM tidak diizinkan"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Ponsel tidak diizinkan"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Jendela Pop-up"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index c61c26e..3cdee4c 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Vinnusniði eytt vegna þess að stjórnunarforrit vantar"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Stjórnunarforrit vinnusniðsins vantar eða er skemmt. Vinnusniðinu og gögnum því tengdu hefur því verið eytt. Hafðu samband við kerfisstjórann til að fá frekari aðstoð."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Vinnusniðið þitt er ekki lengur í boði á þessu tæki"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Of margar tilraunir til að slá inn aðgangsorð"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Tækinu er stjórnað"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Fyrirtækið þitt stjórnar þessu tæki og kann að fylgjast með netnotkun. Ýttu hér til að fá upplýsingar."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Tækið verður hreinsað"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-kort er ekki leyft"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Sími er ekki leyfður"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Sprettigluggi"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 7e54a9c7..f08ed1b 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Scheda SIM non consentita"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefono non consentito"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Finestra popup"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 23b8e38..98b17dc 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -176,8 +176,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"פרופיל העבודה נמחק מפני שחסרה אפליקציית ניהול"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"אפליקציית הניהול של פרופיל העבודה חסרה או פגומה. כתוצאה מכך, פרופיל העבודה שלך נמחק, כולל כל הנתונים הקשורים אליו. לקבלת עזרה, פנה למנהל המערכת."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"פרופיל העבודה שלך אינו זמין עוד במכשיר הזה"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"בוצעו ניסיונות רבים מדי להזנת סיסמה"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"המכשיר מנוהל"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"הארגון שלך מנהל מכשיר זה ועשוי לנטר את התנועה ברשת. הקש לקבלת פרטים."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"תתבצע מחיקה של המכשיר"</string>
@@ -1860,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"כרטיס ה-SIM לא מורשה"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"הטלפון לא מורשה"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"חלון קופץ"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 2100470..66ce56c 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"管理アプリがないため仕事用プロファイルが削除されました"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"仕事用プロファイルの管理アプリがないか、破損しています。そのため仕事用プロファイルと関連データが削除されました。管理者にサポートをご依頼ください。"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"お使いの仕事用プロファイルはこの端末で使用できなくなりました"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"パスワード入力回数が上限を超えました"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"管理対象の端末"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"この端末は組織によって管理され、ネットワーク トラフィックが監視される場合があります。詳しくはタップしてください。"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"端末のデータが消去されます"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM は許可されていません"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"電話は許可されていません"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ポップアップ ウィンドウ"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index ee8daad..879270b 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM ბარათი დაუშვებელია"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ტელეფონი დაუშვებელია"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ამომხტარი ფანჯარა"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index bbf1b4a9..36dc3a6 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Әкімші қолданбасы болмағандықтан жұмыс профилі жойылды"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Жұмыс профилінің әкімші қолданбасы жоқ немесе бүлінген. Нәтижесінде жұмыс профиліңіз және қатысты деректер жойылды. Көмек алу үшін әкімшіге хабарласыңыз."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Жұмыс профиліңіз осы құрылғыда енді қолжетімді емес"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Тым көп құпия сөз енгізу әрекеті жасалды"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Құрылғы басқарылады"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Ұйымыңыз осы құрылғыны басқарады және желі трафигін бақылауы мүмкін. Мәліметтер алу үшін түртіңіз."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Құрылғыңыздағы деректер өшіріледі"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM картасына рұқсат етілмеген"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Телефонға рұқсат етілмеген"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Қалқымалы терезе"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 128c3f3..b8f9f8b 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"កម្រងព័ត៌មានការងារត្រូវបានលុបដោយសារបាត់កម្មវិធីអ្នកគ្រប់គ្រង"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"កម្មវិធីអ្នកគ្រប់គ្រងកម្រងព័ត៌មានការងារនេះអាចបាត់ ឬមានបញ្ហា។ ដូច្នេះហើយទើបកម្រងព័ត៌មានការងាររបស់អ្នក និងទិន្នន័យដែលពាក់ព័ន្ធត្រូវបានលុប។ សូមទាក់ទងទៅអ្នកគ្រប់គ្រងរបស់អ្នក ដើម្បីទទួលបានជំនួយ។"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"កម្រងព័ត៌មានការងាររបស់អ្នកលែងមាននៅលើឧបករណ៍នេះទៀតហើយ"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"ការព្យាយាមបញ្ចូលពាក្យសម្ងាត់ច្រើនដងពេកហើយ"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"ឧបករណ៍ស្ថិតក្រោមការគ្រប់គ្រង"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"ស្ថាប័នរបស់អ្នកគ្រប់គ្រងឧបករណ៍នេះ ហើយអាចនឹងតាមដានចរាចរណ៍បណ្តាញ។ ចុចដើម្បីទទួលបានព័ត៌មានលម្អិត។"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"ឧបករណ៍របស់អ្នកនឹងត្រូវបានលុប"</string>
@@ -1792,4 +1791,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"មិនអនុញ្ញាតចំពោះសីុមទេ"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"មិនអនុញ្ញាតចំពោះទូរសព្ទទេ"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"វិនដូលេចឡើង"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index eaeb25b..c362ce1 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"ನಿರ್ವಾಹಕ ಅಪ್ಲಿಕೇಶನ್ ತಪ್ಪಿಹೋಗಿರುವುದರಿಂದ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ಅಳಿಸಲಾಗಿದೆ"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ನಿರ್ವಾಹಕ ಅಪ್ಲಿಕೇಶನ್ ಕಳೆದು ಹೋಗಿದೆ ಅಥವಾ ಹಾಳಾಗಿದೆ. ಇದರ ಪರಿಣಾಮವಾಗಿ ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಅದಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗಿದೆ. ಸಹಾಯಕ್ಕಾಗಿ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಈ ಸಾಧನದಲ್ಲಿ ಈಗ ಲಭ್ಯವಿಲ್ಲ"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"ಹಲವಾರು ಪಾಸ್ವರ್ಡ್ ಪ್ರಯತ್ನಗಳು"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"ಸಾಧನವನ್ನು ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಸಾಧನವನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ ಮತ್ತು ಅದು ನೆಟ್ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಮೇಲೆ ಗಮನವಿರಿಸಬಹುದು. ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"ಸಿಮ್ಗೆ ಅನುಮತಿಯಿಲ್ಲ"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ಫೋನ್ಗೆ ಅನುಮತಿಯಿಲ್ಲ"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ಪಾಪ್ಅಪ್ ವಿಂಡೋ"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 59fa0bf..991a9833 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"관리 앱이 없어서 직장 프로필이 삭제되었습니다."</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"직장 프로필 관리 앱이 없거나 손상되어 직장 프로필 및 관련 데이터가 삭제되었습니다. 도움이 필요한 경우 관리자에게 문의하세요."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"직장 프로필을 이 기기에서 더 이상 사용할 수 없습니다."</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"비밀번호 입력을 너무 많이 시도함"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"관리되는 기기"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"조직에서 이 기기를 관리하며 네트워크 트래픽을 모니터링할 수도 있습니다. 자세한 내용을 보려면 탭하세요."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"기기가 삭제됩니다."</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM이 허용되지 않음"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"전화가 허용되지 않음"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"팝업 창"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index fb7b4f6..06bbabe 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Башкаруучу колдонмосу болбогондуктан, жумуш профили жок кылынды"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Жумуш профилинин башкаруучу колдонмосу жок же бузулгандыктан, жумуш профилиңиз жана ага байланыштуу дайындар жок кылынды. Жардам алуу үчүн администраторуңузга кайрылыңыз."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Жумуш профилиңиз бул түзмөктөн жок кылынды"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Өтө көп жолу сырсөздү киргизүү аракети жасалды"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Түзмөктү ишкана башкарат"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Ишканаңыз бул түзмөктү башкарат жана тармак трафигин көзөмөлдөшү мүмкүн. Чоо-жайын көрүү үчүн таптап коюңуз."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Түзмөгүңүз тазаланат"</string>
@@ -1791,4 +1790,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM картаны колдонууга тыюу салынган"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Телефонду колдонууга тыюу салынган"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Калкып чыкма терезе"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 477fbdc06..374188f 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"ບໍ່ອະນຸຍາດໃຫ້ໃຊ້ SIM"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ບໍ່ອະນຸຍາດໃຫ້ໃຊ້ໂທລະສັບ"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ໜ້າຈໍປັອບອັບ"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2e44ed2..ab60a62 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -176,8 +176,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Darbo profilis ištrintas dėl trūkstamos administratoriaus programos"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Trūksta darbo profilio administratoriaus programos arba ji sugadinta. Todėl darbo profilis ir susiję duomenys buvo ištrinti. Jei reikia pagalbos, susisiekite su administratoriumi."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Darbo profilis nebepasiekiamas šiame įrenginyje"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Per daug slaptažodžio bandymų"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Įrenginys yra tvarkomas"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Šį įrenginį tvarko organizacija ir gali stebėti tinklo srautą. Palieskite, kad gautumėte daugiau informacijos."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Įrenginys bus ištrintas"</string>
@@ -1860,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM kortelė neleidžiama"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefonas neleidžiamas"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Iššokantysis langas"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 659c9a7..f64fe62 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -174,8 +174,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Darba profils tika dzēsts, jo trūkst administratora lietotnes."</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Trūkst darba profila administratora lietotnes, vai šī lietotne ir bojāta. Šī iemesla dēļ jūsu darba profils un saistītie dati tika dzēsti. Lai saņemtu palīdzību, sazinieties ar administratoru."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Jūsu darba profils šai ierīcē vairs nav pieejams."</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Veikts pārāk daudz paroles ievadīšanas mēģinājumu."</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Ierīce tiek pārvaldīta"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Jūsu organizācija pārvalda šo ierīci un var uzraudzīt tīkla datplūsmu. Pieskarieties, lai saņemtu detalizētu informāciju."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Jūsu ierīces dati tiks dzēsti"</string>
@@ -1825,4 +1824,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM karti nav atļauts izmantot"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Tālruni nav atļauts izmantot"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Uznirstošais logs"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mcc001-mnc01/strings.xml b/core/res/res/values-mcc001-mnc01/strings.xml
new file mode 100644
index 0000000..96af975
--- /dev/null
+++ b/core/res/res/values-mcc001-mnc01/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc030/strings.xml b/core/res/res/values-mcc310-mnc030/strings.xml
index a3fea29..6a404d5 100644
--- a/core/res/res/values-mcc310-mnc030/strings.xml
+++ b/core/res/res/values-mcc310-mnc030/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc150/strings.xml b/core/res/res/values-mcc310-mnc150/strings.xml
new file mode 100644
index 0000000..96af975
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc150/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc170/strings.xml b/core/res/res/values-mcc310-mnc170/strings.xml
index a3fea29..6a404d5 100644
--- a/core/res/res/values-mcc310-mnc170/strings.xml
+++ b/core/res/res/values-mcc310-mnc170/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc280/strings.xml b/core/res/res/values-mcc310-mnc280/strings.xml
index a3fea29..6a404d5 100644
--- a/core/res/res/values-mcc310-mnc280/strings.xml
+++ b/core/res/res/values-mcc310-mnc280/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc410/strings.xml b/core/res/res/values-mcc310-mnc410/strings.xml
index a3fea29..6a404d5 100644
--- a/core/res/res/values-mcc310-mnc410/strings.xml
+++ b/core/res/res/values-mcc310-mnc410/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc560/strings.xml b/core/res/res/values-mcc310-mnc560/strings.xml
index a3fea29..6a404d5 100644
--- a/core/res/res/values-mcc310-mnc560/strings.xml
+++ b/core/res/res/values-mcc310-mnc560/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc950/strings.xml b/core/res/res/values-mcc310-mnc950/strings.xml
index a3fea29..6a404d5 100644
--- a/core/res/res/values-mcc310-mnc950/strings.xml
+++ b/core/res/res/values-mcc310-mnc950/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc311-mnc180/strings.xml b/core/res/res/values-mcc311-mnc180/strings.xml
index a3fea29..6a404d5 100644
--- a/core/res/res/values-mcc311-mnc180/strings.xml
+++ b/core/res/res/values-mcc311-mnc180/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc312-mnc670/strings.xml b/core/res/res/values-mcc312-mnc670/strings.xml
new file mode 100644
index 0000000..96af975
--- /dev/null
+++ b/core/res/res/values-mcc312-mnc670/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
+</resources>
diff --git a/core/res/res/values-mcc313-mnc100/strings.xml b/core/res/res/values-mcc313-mnc100/strings.xml
new file mode 100644
index 0000000..96af975
--- /dev/null
+++ b/core/res/res/values-mcc313-mnc100/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
+</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index a98e2f0..aef21c3 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1791,4 +1791,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Не е дозволена SIM-картичка"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Не е дозволен телефон"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Појавен прозорец"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 65b7041..89333cc 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"അഡ്മിൻ ആപ്പ് വിട്ടുപോയിരിക്കുന്നതിനാൽ ഔദ്യോഗിക പ്രൊഫൈൽ ഇല്ലാതാക്കി"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"ഔദ്യോഗിക പ്രൊഫൈൽ അഡ്മിൻ ആപ്പ് വിട്ടുപോയിരിക്കുന്നു അല്ലെങ്കിൽ കേടായിരിക്കുന്നു. ഫലമായി, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും ബന്ധപ്പെട്ട വിവരങ്ങളും ഇല്ലാതാക്കിയിരിക്കുന്നു. സഹായത്തിന് അഡ്മിനെ ബന്ധപ്പെടുക."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"ഈ ഉപകരണത്തിൽ തുടർന്നങ്ങോട്ട് നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈൽ ലഭ്യമല്ല"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"വളരെയധികം പാസ്വേഡ് ശ്രമങ്ങൾ"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"ഉപകരണം മാനേജുചെയ്യുന്നുണ്ട്"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"നിങ്ങളുടെ സ്ഥാപനമാണ് ഈ ഉപകരണം മാനേജുചെയ്യുന്നത്, നെറ്റ്വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിക്കുകയും ചെയ്തേക്കാം, വിശദാംശങ്ങൾ അറിയാൻ ടാപ്പുചെയ്യുക."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"നിങ്ങളുടെ ഉപകരണം മായ്ക്കും"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM അനുവദനീയമല്ല"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ഫോൺ അനുവദനീയമല്ല"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"പോപ്പ് അപ്പ് വിൻഡോ"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index b088180..9173f2c 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Админ апп байхгүй байгаа тул ажлын профайлыг устгасан байна"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Ажлын профайлын админ апп байхгүй эсвэл эвдэрсэн байна. Үүний улмаас таны ажлын профайл болон холбогдох мэдээллийг устгасан болно. Тусламж хэрэгтэй бол админтай холбогдоно уу."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Таны ажлын профайл энэ төхөөрөмжид боломжгүй байна"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Нууц үгийг хэт олон удаа буруу оруулсан байна"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Төхөөрөмжийг удирдсан"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Таны байгууллага энэ төхөөрөмжийг удирдаж, сүлжээний ачааллыг хянадаг. Дэлгэрэнгүй мэдээлэл авах бол товшино уу."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Таны төхөөрөмж устах болно."</string>
@@ -1788,4 +1787,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM боломжгүй"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Утас боломжгүй"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"гэнэт гарч ирэх цонх"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 9c74b30..eac23b9 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"प्रशासक अॅप गहाळ असल्यामुळे कार्य प्रोफाइल हटवले गेले"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"कार्य प्रोफाइल प्रशासक अॅप गहाळ आहे किंवा करप्ट आहे. परिणामी, आपले कार्य प्रोफाइल आणि संबंधित डेटा हटवले गेले आहेत. सहाय्यासाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"आपले कार्य प्रोफाइल आता या डिव्हाइसवर उपलब्ध नाही"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"बर्याचदा पासवर्ड टाकण्याचा प्रयत्न केला"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"डिव्हाइस व्यवस्थापित केले आहे"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"आपली संस्था हे डिव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे निरीक्षण करू शकते. तपशीलांसाठी टॅप करा."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"तुमचे डिव्हाइस मिटविले जाईल"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"सिमला अनुमती नाही"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"फोनला अनुमती नाही"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"पॉपअप विंडो"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index a81b76f..a627a05 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Profil kerja dipadamkan kerana ketiadaan apl pentadbir"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Apl pentadbir profil kerja tiada atau rosak. Akibatnya, profil kerja anda dan data yang berkaitan telah dipadamkan. Hubungi pentadbir anda untuk mendapatkan bantuan."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Profil kerja anda tidak lagi tersedia pada peranti ini"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Terlalu banyak percubaan kata laluan"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Peranti ini diurus"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organisasi anda mengurus peranti ini dan mungkin memantau trafik rangkaian. Ketik untuk mendapatkan butiran."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Peranti anda akan dipadam"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM tidak dibenarkan"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon tidak dibenarkan"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Tetingkap Timbul"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 34e783b..01f7b76 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"စီမံခန့်ခွဲရန် အက်ပ်မရှိသောကြောင့် အလုပ်ပရိုဖိုင်ကို ဖျက်လိုက်ခြင်းဖြစ်သည်"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"အလုပ်ပရိုဖိုင် စီမံခန့်ခွဲရန်အက်ပ် မရှိပါ သို့မဟုတ် ပျက်စီးနေပါသည်။ ထို့ကြောင့် သင်၏ အလုပ်ပရိုဖိုင်နှင့် ဆက်စပ်နေသော ဒေတာများကို ဖျက်လိုက်ပါပြီ။ အကူအညီရယူရန် သင်၏စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"ဤစက်ပစ္စည်းတွင် သင်၏ အလုပ်ပရိုဖိုင်မရှိတော့ပါ"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"စကားဝှက်ထည့်သွင်းရန် ကြိုးစားသည့် အကြိမ်အရေအတွက် အလွန်များသွား၍ ဖြစ်ပါသည်"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"စက်ပစ္စည်းကို စီမံခန့်ခွဲထားပါသည်"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"ဤစက်ပစ္စည်းကို သင်၏ အဖွဲ့အစည်းက စီမံပြီး ကွန်ရက်အသွားအလာကို စောင့်ကြည့်နိုင်ပါသည်။ ထပ်မံလေ့လာရန် တို့ပါ။"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"သင့်ကိရိယာအား ပယ်ဖျက်လိမ့်မည်"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"ဆင်းမ်ကို ခွင့်မပြုပါ"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ဖုန်းကို ခွင့်မပြုပါ"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ပေါ့ပ်အပ် ဝင်းဒိုး"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 52436ea..8e7b683 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Jobbprofilen er slettet på grunn av manglende administratorapp"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Administratorappen for jobbprofilen mangler eller er skadet. Dette har ført til at jobbprofilen og alle data knyttet til den, har blitt slettet. Ta kontakt med administratoren for å få hjelp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Jobbprofilen din er ikke lenger tilgjengelig på denne enheten"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"For mange passordforsøk"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Enheten administreres"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organisasjonen din kontrollerer denne enheten og kan overvåke nettverkstrafikk. Trykk for å få mer informasjon."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Enheten blir slettet"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-kortet er ikke tillatt"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefonen er ikke tillatt"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Forgrunnsvindu"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index bb84eae..41bb71b 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"प्रशासकीय अनुप्रयोग नभएकाले कार्य प्रोफाइल मेटाइयो"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"उक्त कार्य प्रोफाइलको प्रशासकीय अनुप्रयोग छैन वा बिग्रेको छ। त्यसले गर्दा, तपाईंको कार्य प्रोफाइल र सम्बन्धित डेटालाई मेटिएको छ। सहायताका लागि आफ्ना प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"तपाईंको कार्य प्रोफाइल अब उप्रान्त यस यन्त्रमा उपलब्ध छैन"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"पासवर्ड प्रविष्ट गर्ने अत्यधिक गलत प्रयासहरू भए"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"यन्त्र व्यवस्थित गरिएको छ"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"तपाईंको संगठनले यस यन्त्रको व्यवस्थापन गर्दछ र नेटवर्क ट्राफिकको अनुगमन गर्न सक्छ। विवरणहरूका लागि ट्याप गर्नुहोस्।"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"तपाईंको यन्त्र मेटिनेछ"</string>
@@ -1796,4 +1795,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM लाई अनुमति छैन"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"फोनलाई अनुमति छैन"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"पपअप विन्डो"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 3f8ed59..1355ed3 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Simkaart niet toegestaan"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefoon niet toegestaan"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pop-upvenster"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 2c0ba4b..d6ecf91 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"ਗੁੰਮਸ਼ੁਦਾ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਦੇ ਕਾਰਨ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਮਿਟਾਇਆ ਗਿਆ"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਜਾਂ ਤਾਂ ਗੁੰਮਸ਼ੁਦਾ ਹੈ ਜਾਂ ਖਰਾਬ ਹੈ। ਨਤੀਜੇ ਵਜੋਂ, ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਸਬੰਧਿਤ ਡਾਟਾ ਮਿਟਾਇਆ ਗਿਆ ਹੈ। ਸਹਾਇਤਾ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹੁਣ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"ਕਈ ਵਾਰ ਗਲਤ ਪਾਸਵਰਡ ਦਾਖਲ ਕੀਤਾ ਗਿਆ"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਨ ਅਧੀਨ ਹੈ"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"ਤੁਹਾਡਾ ਸੰਗਠਨ ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਦਾ ਹੈ ਅਤੇ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮਿਟਾਇਆ ਜਾਏਗਾ"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ਫ਼ੋਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"ਪੌਪਅੱਪ ਵਿੰਡੋ"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 685ad53..5904abd 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -176,8 +176,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Profil do pracy został usunięty z powodu braku aplikacji administratora"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Brakuje aplikacji administratora profilu do pracy lub jest ona uszkodzona. Dlatego Twój profil do pracy i związane z nim dane zostały usunięte. Skontaktuj się ze swoim administratorem, by uzyskać pomoc."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Twój profil do pracy nie jest już dostępny na tym urządzeniu"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Zbyt wiele prób podania hasła"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Urządzenie jest zarządzane"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Twoja organizacja zarządza tym urządzeniem i może monitorować ruch w sieci. Kliknij, by dowiedzieć się więcej."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Twoje urządzenie zostanie wyczyszczone"</string>
@@ -1860,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Niedozwolona karta SIM"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Niedozwolony telefon"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Wyskakujące okienko"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 1a9eefb..23b0eef 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM não permitido"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Smartphone não permitido"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Janela pop-up"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 0f4635b..141c8f090 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM não permitido"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telemóvel não permitido"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Janela pop-up"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 1a9eefb..23b0eef 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM não permitido"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Smartphone não permitido"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Janela pop-up"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 298434c..7cf8b1a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1824,4 +1824,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Cardul SIM nu este permis"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefonul nu este permis"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Fereastră pop-up"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 643978e..b8267c3 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -176,8 +176,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Рабочий профиль удален, поскольку отсутствует приложение для администрирования"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Приложение для администрирования рабочего профиля отсутствует или повреждено. Из-за этого рабочий профиль и связанные с ним данные были удалены. Если у вас возникли вопросы, обратитесь к администратору."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Ваш рабочий профиль больше не доступен на этом устройстве"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Слишком много попыток ввести пароль."</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Это управляемое устройство"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Ваша организация управляет этим устройством и может отслеживать сетевой трафик. Подробнее…"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Все данные с устройства будут удалены"</string>
@@ -1860,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Использование SIM-карты запрещено"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Звонки запрещены"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Всплывающее окно"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index e8b963c..bb9e6ec 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1791,4 +1791,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM එක සඳහා ඉඩ නොදේ"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"දුරකථනය සඳහා ඉඩ නොදේ"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"උත්පතන කවුළුව"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 36ad8b9..8646e95 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -176,8 +176,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Pracovný profil bol odstránený z dôvodu chýbajúcej aplikácie na správu"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Aplikácia na správu pracovného profilu buď chýba, alebo je poškodená. Z toho dôvodu bol odstránený pracovný profil aj k nemu priradené dáta. Ak potrebujete pomoc, kontaktujte svojho správcu."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Váš pracovný profil už v tomto zariadení nie je k dispozícii"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Príliš veľa pokusov o zadanie hesla"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Zariadenie je spravované"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Vaša organizácia spravuje toto zariadenie a môže sledovať sieťovú premávku. Klepnutím zobrazíte podrobnosti."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Vaše zariadenie bude vymazané"</string>
@@ -1860,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM karta je zakázaná"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefón je zakázaný"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Automaticky otvárané okno"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 7ad6bc2..da2a261 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1859,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Kartica SIM ni dovoljena"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon ni dovoljen"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pojavno okno"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 7f0a693..0669d4c 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Profili i punës u fshi për shkak të mungesës së aplikacionit të administratorit"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Aplikacioni i administratorit të profilit të punës mungon ose është dëmtuar. Si rezultat i kësaj, profili yt i punës dhe të dhënat përkatëse janë fshirë. Kontakto me administratorin për ndihmë."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Profili yt i punës nuk është më i disponueshëm në këtë pajisje"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Shumë përpjekje për fjalëkalimin"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Pajisja është e menaxhuar"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organizata jote e menaxhon këtë pajisje dhe mund të monitorojë trafikun e rrjetit. Trokit për detaje."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Pajisja do të spastrohet"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Karta SIM nuk lejohet"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefoni nuk lejohet"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Dritare kërcyese"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 1008215..26d7a298 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -174,8 +174,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Профил за Work је избрисан јер недостаје апликација за администраторе"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Апликација за администраторе на профилу за Work недостаје или је оштећена. Због тога су профил за Work и повезани подаци избрисани. Обратите се администратору за помоћ."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Профил за Work више није доступан на овом уређају"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Превише покушаја уноса лозинке"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Уређајем се управља"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Организација управља овим уређајем и може да надгледа мрежни саобраћај. Додирните за детаље."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Уређај ће бити обрисан"</string>
@@ -1825,4 +1824,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM картица није дозвољена"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Телефон није дозвољен"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Искачући прозор"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 44a66f8..5b3fdf6 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-kort tillåts inte"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Mobil tillåts inte"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"popup-fönster"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 9a78fd4..78fc186 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1787,4 +1787,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM imekataliwa"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Simu imekataliwa"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Dirisha Ibukizi"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 1cd5cd0..544d109 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"நிர்வாகிப் பயன்பாடு இல்லாததால், பணி விவரம் நீக்கப்பட்டது"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"பணி விவர நிர்வாகிப் பயன்பாடு இல்லை அல்லது அது சிதைந்துள்ளது. இதன் விளைவாக, உங்கள் பணி விவரமும் அதனுடன் தொடர்புடைய தரவும் நீக்கப்பட்டன. உதவிக்கு, நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"இந்தச் சாதனத்தில் இனி பணி விவரம் கிடைக்காது"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"கடவுச்சொல்லை அதிக முறை தவறாக முயற்சித்துவிட்டீர்கள்"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"சாதனம் நிர்வகிக்கப்படுகிறது"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"உங்கள் நிறுவனம் இந்தச் சாதனத்தை நிர்வகிக்கும், அத்துடன் அது நெட்வொர்க் ட்ராஃபிக்கைக் கண்காணிக்கலாம். விவரங்களுக்கு, தட்டவும்."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"சாதனத் தரவு அழிக்கப்படும்"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"சிம் அனுமதிக்கப்படவில்லை"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ஃபோன் அனுமதிக்கப்படவில்லை"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"பாப்அப் சாளரம்"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 9c1a529..75c37249 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"నిర్వాహక యాప్ లేనందున కార్యాలయ ప్రొఫైల్ తొలగించబడింది"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"కార్యాలయ ప్రొఫైల్ నిర్వాహక యాప్ లేదు లేదా పాడైంది. తత్ఫలితంగా, మీ కార్యాలయ ప్రొఫైల్ మరియు సంబంధిత డేటా తొలగించబడ్డాయి. సహాయం కోసం మీ నిర్వాహకులను సంప్రదించండి."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"ఈ పరికరంలో మీ కార్యాలయ ప్రొఫైల్ ఇప్పుడు అందుబాటులో లేదు"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"చాలా ఎక్కువ పాస్వర్డ్ ప్రయత్నాలు చేసారు"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"పరికరం నిర్వహించబడింది"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"మీ సంస్థ ఈ పరికరాన్ని నిర్వహిస్తుంది మరియు నెట్వర్క్ ట్రాఫిక్ని పర్యవేక్షించవచ్చు. వివరాల కోసం నొక్కండి."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"మీ పరికరంలోని డేటా తొలగించబడుతుంది"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM అనుమతించబడదు"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ఫోన్ అనుమతించబడదు"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"పాప్అప్ విండో"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 900f950..66a7280 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"ลบโปรไฟล์งานแล้วเนื่องจากไม่มีแอปผู้ดูแลระบบ"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"แอปผู้ดูแลระบบโปรไฟล์งานไม่มีอยู่หรือเสียหาย ระบบจึงทำการลบโปรไฟล์งานและข้อมูลที่เกี่ยวข้องของคุณออก โปรดติดต่อผู้ดูแลระบบเพื่อรับความช่วยเหลือ"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"โปรไฟล์งานของคุณไม่สามารถใช้ในอุปกรณ์นี้อีกต่อไป"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"ลองป้อนรหัสผ่านหลายครั้งเกินไป"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"อุปกรณ์มีการจัดการ"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"องค์กรของคุณจัดการอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย แตะเพื่อดูรายละเอียด"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"ระบบจะลบข้อมูลในอุปกรณ์ของคุณ"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"ไม่อนุญาตให้ใช้ซิม"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ไม่อนุญาตให้ใช้โทรศัพท์"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"หน้าต่างป๊อปอัป"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 267f2ed..bafcef3 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Na-delete ang profile sa trabaho dahil wala itong admin app"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Nawawala o nasira ang admin app ng profile sa trabaho. Dahil dito, na-delete ang profile mo sa trabaho at nauugnay na data. Makipag-ugnayan sa iyong admin para sa tulong."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Hindi na available sa device na ito ang iyong profile sa trabaho"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Masyadong maraming pagsubok sa password"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Pinamamahalaan ang device"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Pinamamahalaan ng iyong organisasyon ang device na ito, at maaari nitong subaybayan ang trapiko sa network. I-tap para sa mga detalye."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Buburahin ang iyong device"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"Hindi pinahihintulutan ang SIM"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Hindi pinahihintulutan ang telepono"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Window ng Popup"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 3d592fe..7e2d2bfe 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Eksik yönetici uygulaması nedeniyle iş profili silindi"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"İş profili yönetici uygulaması eksik ya da bozuk. Bunun sonucunda iş profiliniz ve ilgili veriler silindi. Yardım almak için yöneticiniz ile iletişim kurun."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"İş profiliniz arık bu cihazda kullanılamıyor"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Çok fazla şifre denemesi yapıldı"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Cihaz yönetiliyor"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Kuruluşunuz bu cihazı yönetmekte olup ağ trafiğini izleyebilir. Ayrıntılar için dokunun."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Cihazınız silinecek"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM\'e izin verilmiyor"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefona izin verilmiyor"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Pop-up Pencere"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index a00f488..050b26b 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1859,4 +1859,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-карта заборонена"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Телефон заборонено"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Спливаюче вікно"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 4e528bd..44e7350 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"گمشدہ منتظم ایپ کی وجہ سے دفتری پروفائل حذف کر دیا گیا"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"دفتری پروفائل کی منتظم ایپ یا تو غائب ہے یا خراب ہے۔ اس کی وجہ سے، آپ کا دفتری پروفائل اور متعلقہ ڈیٹا حذف کر دیے گئے ہیں۔ مدد کیلئے اپنے منتظم سے رابطہ کریں۔"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"آپ کا دفتری پروفائل اس آلہ پر مزید دستیاب نہیں ہے"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"پاس ورڈ کی بہت ساری کوششیں"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"آلہ زیر انتظام ہے"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"آپ کی تنظیم اس آلے کا نظم کرتی ہے اور وہ نیٹ ورک ٹریفک کی نگرانی کر سکتی ہے۔ تفاصیل کیلئے تھپتھپائیں۔"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"آپ کا آلہ صاف کر دیا جائے گا"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM کی اجازت نہیں ہے"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"فون کی اجازت نہیں ہے"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"پاپ اپ ونڈو"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index a269630..b62d5b9 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM karta ishlatish taqiqlangan"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Chaqiruvlar taqiqlangan"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Qalqib chiquvchi oyna"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 09df823..921f7c6 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Đã xóa hồ sơ công việc do thiếu ứng dụng quản trị"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Ứng dụng quản trị hồ sơ công việc bị thiếu hoặc hỏng. Do vậy, hồ sơ công việc của bạn và dữ liệu liên quan đã bị xóa. Hãy liên hệ với quản trị viên của bạn để được trợ giúp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Hồ sơ công việc của bạn không có sẵn trên thiết bị này nữa"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"Quá nhiều lần nhập mật khẩu"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"Thiết bị được quản lý"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"Tổ chức của bạn sẽ quản lý thiết bị này và có thể theo dõi lưu lượng truy cập mạng. Nhấn để biết chi tiết."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Thiết bị của bạn sẽ bị xóa"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM không được cho phép"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Điện thoại không được cho phép"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Cửa sổ bật lên"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b3c1af5..06b781d 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"由于缺少管理应用,工作资料已被删除"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"工作资料管理应用缺失或损坏,因此系统已删除您的工作资料及相关数据。如需帮助,请与您的管理员联系。"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"您的工作资料已不在此设备上"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"密码尝试次数过多"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"设备为受管理设备"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"贵单位会管理该设备,且可能会监控网络流量。点按即可了解详情。"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"系统将清空您的设备"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"不受允许的 SIM 卡"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"不受允许的手机"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"弹出式窗口"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 04a62a6..aac5fcc 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"由於沒有管理員應用程式,工作設定檔已刪除"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"工作設定檔管理員應用程式已遺失或損毀。因此,您的工作設定檔和相關資料已刪除。請聯絡您的管理員以取得協助。"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"您的工作設定檔無法再在此裝置上使用"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"密碼輸入錯誤的次數過多"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"裝置已受管理"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"您的機構會管理此裝置,並可能會監控網絡流量。輕按即可瞭解詳情。"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"您的裝置將被清除"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"不允許使用 SIM 卡"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"不允許使用手機"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"彈出式視窗"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 0e9827a..6a35994 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -172,8 +172,7 @@
<string name="work_profile_deleted_description" msgid="1100529432509639864">"Work 設定檔因管理員應用程式遺失而遭到刪除"</string>
<string name="work_profile_deleted_details" msgid="6307630639269092360">"Work 設定檔管理員應用程式遺失或已毀損,因此系統刪除了你的 Work 設定檔和相關資料。如需協助,請與你的管理員聯絡。"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"你的 Work 設定檔已不在這個裝置上"</string>
- <!-- no translation found for work_profile_deleted_reason_maximum_password_failure (8986903510053359694) -->
- <skip />
+ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="8986903510053359694">"密碼輸入錯誤的次數過多"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"裝置受到管理"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"貴機構會管理這個裝置,且可能監控網路流量。輕觸即可瞭解詳情。"</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"你的裝置資料將遭到清除"</string>
@@ -1790,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"不受允許的 SIM 卡"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"不受允許的手機"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"彈出式視窗"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index f341da1..6f5e4cb 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1789,4 +1789,6 @@
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"I-SIM ayivunyelwe"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"Ifoni ayivunyelwe"</string>
<string name="popup_window_default_title" msgid="4874318849712115433">"Iwindi lesigelekeqe"</string>
+ <!-- no translation found for slice_more_content (8504342889413274608) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 11cdb76..4b9839f 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2546,16 +2546,24 @@
<attr name="filterTouchesWhenObscured" format="boolean" />
<!-- Defines the quality of translucent drawing caches. This property is used
- only when the drawing cache is enabled and translucent. The default value is auto. -->
+ only when the drawing cache is enabled and translucent. The default value is auto.
+ Deprecated: The view drawing cache was largely made obsolete with the introduction of
+ hardware-accelerated rendering in API 11. -->
<attr name="drawingCacheQuality">
<!-- Lets the framework decide what quality level should be used
- for the drawing cache. -->
+ for the drawing cache.
+ Deprecated: The view drawing cache was largely made obsolete with the introduction
+ of hardware-accelerated rendering in API 11. -->
<enum name="auto" value="0" />
<!-- Low quality. When set to low quality, the drawing cache uses a lower color
- depth, thus losing precision in rendering gradients, but uses less memory. -->
+ depth, thus losing precision in rendering gradients, but uses less memory.
+ Deprecated: The view drawing cache was largely made obsolete with the introduction
+ of hardware-accelerated rendering in API 11. -->
<enum name="low" value="1" />
<!-- High quality. When set to high quality, the drawing cache uses a higher
- color depth but uses more memory. -->
+ color depth but uses more memory.
+ Deprecated: The view drawing cache was largely made obsolete with the introduction
+ of hardware-accelerated rendering in API 11. -->
<enum name="high" value="2" />
</attr>
@@ -3060,7 +3068,9 @@
instance during a scrolling.) This property lets you persist the cache
in memory after its initial usage. Persisting the cache consumes more
memory but may prevent frequent garbage collection is the cache is created
- over and over again. By default the persistence is set to scrolling. -->
+ over and over again. By default the persistence is set to scrolling.
+ Deprecated: The view drawing cache was largely made obsolete with the introduction of
+ hardware-accelerated rendering in API 11. -->
<attr name="persistentDrawingCache">
<!-- The drawing cache is not persisted after use. -->
<flag name="none" value="0x0" />
@@ -3072,7 +3082,9 @@
<flag name="all" value="0x3" />
</attr>
<!-- Defines whether the ViewGroup should always draw its children using their
- drawing cache or not. The default value is true. -->
+ drawing cache or not. The default value is true.
+ Deprecated: The view drawing cache was largely made obsolete with the introduction of
+ hardware-accelerated rendering in API 11. -->
<attr name="alwaysDrawnWithCache" format="boolean" />
<!-- Sets whether this ViewGroup's drawable states also include
its children's drawable states. This is used, for example, to
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index e6c829f..0e90287 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1449,8 +1449,7 @@
quit it. Only one such app can be running at a time; if the user
tries to launch a second such app, they will be prompted
to quit the first before doing so. While the
- application is running, the user will be informed of this.
- @hide -->
+ application is running, the user will be informed of this. -->
<attr name="cantSaveState" format="boolean" />
<attr name="uiOptions" />
<!-- Declare that your application will be able to deal with RTL (right to left) layouts.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index dcb56a2..570f37c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2352,9 +2352,37 @@
<!-- Package name for default network scorer app; overridden by product overlays. -->
<string name="config_defaultNetworkScorerPackageName"></string>
- <!-- default device has recents property -->
+ <!-- Determines whether recent tasks are provided to the user. Default device has recents
+ property. If this is false, then the following recents config flags are ignored. -->
<bool name="config_hasRecents">true</bool>
+ <!-- The minimum number of visible recent tasks to be presented to the user through the
+ SystemUI. Can be -1 if there is no minimum limit. -->
+ <integer name="config_minNumVisibleRecentTasks_grid">-1</integer>
+
+ <!-- The maximum number of visible recent tasks to be presented to the user through the
+ SystemUI. Can be -1 if there is no maximum limit. -->
+ <integer name="config_maxNumVisibleRecentTasks_grid">9</integer>
+
+ <!-- The minimum number of visible recent tasks to be presented to the user through the
+ SystemUI. Can be -1 if there is no minimum limit. -->
+ <integer name="config_minNumVisibleRecentTasks_lowRam">-1</integer>
+
+ <!-- The maximum number of visible recent tasks to be presented to the user through the
+ SystemUI. Can be -1 if there is no maximum limit. -->
+ <integer name="config_maxNumVisibleRecentTasks_lowRam">9</integer>
+
+ <!-- The minimum number of visible recent tasks to be presented to the user through the
+ SystemUI. Can be -1 if there is no minimum limit. -->
+ <integer name="config_minNumVisibleRecentTasks">5</integer>
+
+ <!-- The maximum number of visible recent tasks to be presented to the user through the
+ SystemUI. Can be -1 if there is no maximum limit. -->
+ <integer name="config_maxNumVisibleRecentTasks">-1</integer>
+
+ <!-- The duration in which a recent task is considered in session and should be visible. -->
+ <integer name="config_activeTaskDurationHours">6</integer>
+
<!-- default window ShowCircularMask property -->
<bool name="config_windowShowCircularMask">false</bool>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 108ac1c..0364b81 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2745,18 +2745,6 @@
<!-- ===============================================================
Resources added in version O of the platform
-
- NOTE: add <public> elements within a <public-group> like so:
-
- <public-group type="attr" first-id="0x01010531">
- <public name="exampleAttr1" />
- <public name="exampleAttr2" />
- </public-group>
-
- To add a new public-group block, choose an id value that is 1 greater
- than the last of that item above. For example, the last "attr" id
- value above is 0x01010530, so the public-group of attrs below has
- the id value of 0x01010531.
=============================================================== -->
<eat-comment />
@@ -2827,18 +2815,6 @@
<!-- ===============================================================
Resources added in version O MR1 of the platform
-
- NOTE: add <public> elements within a <public-group> like so:
-
- <public-group type="attr" first-id="0x01010531">
- <public name="exampleAttr1" />
- <public name="exampleAttr2" />
- </public-group>
-
- To add a new public-group block, choose an id value that is 1 greater
- than the last of that item above. For example, the last "attr" id
- value above is 0x01010530, so the public-group of attrs below has
- the id value of 0x01010531.
=============================================================== -->
<eat-comment />
@@ -2868,6 +2844,7 @@
<eat-comment />
<public-group type="attr" first-id="0x0101056e">
+ <public name="cantSaveState" />
</public-group>
<public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8d12cab..f6b18ba 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -591,6 +591,11 @@
<!-- Text shown when viewing channel settings for notifications related to a usb connection -->
<string name="notification_channel_usb">USB connection</string>
+ <!-- Text shown when viewing channel settings for notification about a heavy-weight app
+ currently running.
+ [CHAR_LIMIT=NONE] -->
+ <string name="notification_channel_heavy_weight_app">App running</string>
+
<!-- This is the label for the notification channel settings that controls the behavior
of the notification about applications that are running in the background (that is,
perhaps confusingly, running foreground services but not the foreground UI on the screen).
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 53d09d8..5ac120b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -311,6 +311,13 @@
<java-symbol type="bool" name="config_enableMultiUserUI"/>
<java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
<java-symbol type="bool" name="config_hasRecents" />
+ <java-symbol type="integer" name="config_minNumVisibleRecentTasks_lowRam" />
+ <java-symbol type="integer" name="config_maxNumVisibleRecentTasks_lowRam" />
+ <java-symbol type="integer" name="config_minNumVisibleRecentTasks_grid" />
+ <java-symbol type="integer" name="config_maxNumVisibleRecentTasks_grid" />
+ <java-symbol type="integer" name="config_minNumVisibleRecentTasks" />
+ <java-symbol type="integer" name="config_maxNumVisibleRecentTasks" />
+ <java-symbol type="integer" name="config_activeTaskDurationHours" />
<java-symbol type="bool" name="config_windowShowCircularMask" />
<java-symbol type="bool" name="config_windowEnableCircularEmulatorDisplayOverlay" />
<java-symbol type="bool" name="config_wifi_framework_enable_associated_network_selection" />
@@ -3033,6 +3040,7 @@
<java-symbol type="string" name="notification_channel_alerts" />
<java-symbol type="string" name="notification_channel_retail_mode" />
<java-symbol type="string" name="notification_channel_usb" />
+ <java-symbol type="string" name="notification_channel_heavy_weight_app" />
<java-symbol type="string" name="config_defaultAutofillService" />
<java-symbol type="string" name="notification_channel_foreground_service" />
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
index 5f4199a..1e4c03e 100644
--- a/core/res/res/xml/default_zen_mode_config.xml
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -19,5 +19,5 @@
<!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. -->
<zen version="2">
- <allow calls="true" messages="false" reminders="true" events="true" />
+ <allow alarms="true" media_system_other="true" calls="false" messages="false" reminders="false" events="false" />
</zen>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 6731536..6c32590 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -342,6 +342,7 @@
Settings.Global.TETHER_DUN_REQUIRED,
Settings.Global.TETHER_OFFLOAD_DISABLED,
Settings.Global.TETHER_SUPPORTED,
+ Settings.Global.TEXT_CLASSIFIER_CONSTANTS,
Settings.Global.THEATER_MODE_ON,
Settings.Global.TRANSITION_ANIMATION_SCALE,
Settings.Global.TRUSTED_SOUND,
@@ -463,7 +464,6 @@
Settings.Secure.NFC_PAYMENT_FOREGROUND,
Settings.Secure.NIGHT_DISPLAY_ACTIVATED,
Settings.Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
- Settings.Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME,
Settings.Secure.PACKAGE_VERIFIER_STATE,
Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 461d537..4e83221 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -214,7 +214,7 @@
assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
}
- /** Test BatteryStatsImpl.noteScreenStateLocked. */
+ /** Test BatteryStatsImpl.noteScreenStateLocked sets timebases and screen states correctly. */
@SmallTest
public void testNoteScreenStateLocked() throws Exception {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
@@ -233,4 +233,52 @@
assertEquals(bi.getScreenState(), Display.STATE_OFF);
}
+ /** Test BatteryStatsImpl.noteScreenStateLocked updates timers correctly.
+ *
+ * Unknown and doze should both be subset of off state
+ *
+ * Timeline 0----100----200----310----400------------1000
+ * Unknown -------
+ * On -------
+ * Off ------- ----------------------
+ * Doze ----------------
+ */
+ @SmallTest
+ public void testNoteScreenStateTimersLocked() throws Exception {
+ final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+ MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+
+ clocks.realtime = clocks.uptime = 100;
+ // Device startup, setOnBatteryLocked calls updateTimebases
+ bi.updateTimeBasesLocked(true, Display.STATE_UNKNOWN, 100_000, 100_000);
+ // Turn on display at 200us
+ clocks.realtime = clocks.uptime = 200;
+ bi.noteScreenStateLocked(Display.STATE_ON);
+ assertEquals(150_000, bi.computeBatteryRealtime(250_000, STATS_SINCE_CHARGED));
+ assertEquals(100_000, bi.computeBatteryScreenOffRealtime(250_000, STATS_SINCE_CHARGED));
+ assertEquals(50_000, bi.getScreenOnTime(250_000, STATS_SINCE_CHARGED));
+ assertEquals(0, bi.getScreenDozeTime(250_000, STATS_SINCE_CHARGED));
+
+ clocks.realtime = clocks.uptime = 310;
+ bi.noteScreenStateLocked(Display.STATE_OFF);
+ assertEquals(250_000, bi.computeBatteryRealtime(350_000, STATS_SINCE_CHARGED));
+ assertEquals(140_000, bi.computeBatteryScreenOffRealtime(350_000, STATS_SINCE_CHARGED));
+ assertEquals(110_000, bi.getScreenOnTime(350_000, STATS_SINCE_CHARGED));
+ assertEquals(0, bi.getScreenDozeTime(350_000, STATS_SINCE_CHARGED));
+
+ clocks.realtime = clocks.uptime = 400;
+ bi.noteScreenStateLocked(Display.STATE_DOZE);
+ assertEquals(400_000, bi.computeBatteryRealtime(500_000, STATS_SINCE_CHARGED));
+ assertEquals(290_000, bi.computeBatteryScreenOffRealtime(500_000, STATS_SINCE_CHARGED));
+ assertEquals(110_000, bi.getScreenOnTime(500_000, STATS_SINCE_CHARGED));
+ assertEquals(100_000, bi.getScreenDozeTime(500_000, STATS_SINCE_CHARGED));
+
+ clocks.realtime = clocks.uptime = 1000;
+ bi.noteScreenStateLocked(Display.STATE_OFF);
+ assertEquals(1400_000, bi.computeBatteryRealtime(1500_000, STATS_SINCE_CHARGED));
+ assertEquals(1290_000, bi.computeBatteryScreenOffRealtime(1500_000, STATS_SINCE_CHARGED));
+ assertEquals(110_000, bi.getScreenOnTime(1500_000, STATS_SINCE_CHARGED));
+ assertEquals(600_000, bi.getScreenDozeTime(1500_000, STATS_SINCE_CHARGED));
+ }
+
}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 57c7549..0072012 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
+import android.annotation.WorkerThread;
import android.content.res.ResourcesImpl;
import android.os.Parcel;
import android.os.Parcelable;
@@ -1233,6 +1234,7 @@
* @param stream The outputstream to write the compressed data.
* @return true if successfully compressed to the specified stream.
*/
+ @WorkerThread
public boolean compress(CompressFormat format, int quality, OutputStream stream) {
checkRecycled("Can't compress a recycled bitmap");
// do explicit check before calling the native method
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index ffb39e3..f5bf754 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -354,6 +354,7 @@
* decode, in the case of which a more accurate, but slightly slower,
* IDCT method will be used instead.
*/
+ @Deprecated
public boolean inPreferQualityOverSpeed;
/**
@@ -412,6 +413,7 @@
* can check, inbetween the bounds decode and the image decode, to see
* if the operation is canceled.
*/
+ @Deprecated
public boolean mCancel;
/**
@@ -426,6 +428,7 @@
* or if inJustDecodeBounds is true, will set outWidth/outHeight
* to -1
*/
+ @Deprecated
public void requestCancelDecode() {
mCancel = true;
}
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index c4c14c9e..987096f 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -14,15 +14,27 @@
// libandroidfw is partially built for the host (used by obbtool, aapt, and others)
-cc_library {
- name: "libandroidfw",
- host_supported: true,
+cc_defaults {
+ name: "libandroidfw_defaults",
cflags: [
- "-Wall",
"-Werror",
- "-Wunused",
"-Wunreachable-code",
],
+ target: {
+ windows: {
+ // The Windows compiler warns incorrectly for value initialization with {}.
+ cppflags: ["-Wno-missing-field-initializers"],
+ },
+ host: {
+ cflags: ["-DSTATIC_ANDROIDFW_FOR_TOOLS"],
+ },
+ },
+}
+
+cc_library {
+ name: "libandroidfw",
+ defaults: ["libandroidfw_defaults"],
+ host_supported: true,
srcs: [
"ApkAssets.cpp",
"Asset.cpp",
@@ -67,7 +79,6 @@
},
},
host: {
- cflags: ["-DSTATIC_ANDROIDFW_FOR_TOOLS"],
shared: {
enabled: false,
},
@@ -84,9 +95,82 @@
},
windows: {
enabled: true,
- cppflags: ["-Wno-missing-field-initializers"], // The Windows compiler warns
- // incorrectly for value
- // initialization with {}.
},
},
}
+
+common_test_libs = [
+ "libandroidfw",
+ "libbase",
+ "libcutils",
+ "libutils",
+ "libziparchive",
+]
+
+cc_test {
+ name: "libandroidfw_tests",
+ host_supported: true,
+ defaults: ["libandroidfw_defaults"],
+ cppflags: [
+ // This is to suppress warnings/errors from gtest
+ "-Wno-unnamed-type-template-args",
+ ],
+ srcs: [
+ // Helpers/infra for testing.
+ "tests/CommonHelpers.cpp",
+ "tests/TestHelpers.cpp",
+ "tests/TestMain.cpp",
+
+ // Actual tests.
+ "tests/ApkAssets_test.cpp",
+ "tests/AppAsLib_test.cpp",
+ "tests/Asset_test.cpp",
+ "tests/AssetManager2_test.cpp",
+ "tests/AttributeFinder_test.cpp",
+ "tests/AttributeResolution_test.cpp",
+ "tests/ByteBucketArray_test.cpp",
+ "tests/Config_test.cpp",
+ "tests/ConfigLocale_test.cpp",
+ "tests/Idmap_test.cpp",
+ "tests/LoadedArsc_test.cpp",
+ "tests/ResourceUtils_test.cpp",
+ "tests/ResTable_test.cpp",
+ "tests/Split_test.cpp",
+ "tests/StringPiece_test.cpp",
+ "tests/Theme_test.cpp",
+ "tests/TypeWrappers_test.cpp",
+ "tests/ZipUtils_test.cpp",
+ ],
+ target: {
+ android: {
+ srcs: [
+ "tests/BackupData_test.cpp",
+ "tests/ObbFile_test.cpp",
+ ],
+ shared_libs: common_test_libs + ["libui"],
+ },
+ host: {
+ static_libs: common_test_libs + ["liblog", "libz"],
+ },
+ },
+ data: ["tests/data/**/*.apk"],
+}
+
+cc_benchmark {
+ name: "libandroidfw_benchmarks",
+ defaults: ["libandroidfw_defaults"],
+ srcs: [
+ // Helpers/infra for benchmarking.
+ "tests/BenchMain.cpp",
+ "tests/BenchmarkHelpers.cpp",
+ "tests/CommonHelpers.cpp",
+
+ // Actual benchmarks.
+ "tests/AssetManager2_bench.cpp",
+ "tests/SparseEntry_bench.cpp",
+ "tests/Theme_bench.cpp",
+ ],
+ shared_libs: common_test_libs,
+ data: ["tests/data/**/*.apk"],
+}
+
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
deleted file mode 100644
index 68c51ef..0000000
--- a/libs/androidfw/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (C) 2010 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
deleted file mode 100644
index 921fd14..0000000
--- a/libs/androidfw/tests/Android.mk
+++ /dev/null
@@ -1,126 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-# ==========================================================
-# Setup some common variables for the different build
-# targets here.
-# ==========================================================
-LOCAL_PATH:= $(call my-dir)
-
-testFiles := \
- ApkAssets_test.cpp \
- AppAsLib_test.cpp \
- Asset_test.cpp \
- AssetManager2_test.cpp \
- AttributeFinder_test.cpp \
- AttributeResolution_test.cpp \
- ByteBucketArray_test.cpp \
- Config_test.cpp \
- ConfigLocale_test.cpp \
- Idmap_test.cpp \
- LoadedArsc_test.cpp \
- ResourceUtils_test.cpp \
- ResTable_test.cpp \
- Split_test.cpp \
- StringPiece_test.cpp \
- TestHelpers.cpp \
- TestMain.cpp \
- Theme_test.cpp \
- TypeWrappers_test.cpp \
- ZipUtils_test.cpp
-
-benchmarkFiles := \
- AssetManager2_bench.cpp \
- BenchMain.cpp \
- BenchmarkHelpers.cpp \
- SparseEntry_bench.cpp \
- TestHelpers.cpp \
- Theme_bench.cpp
-
-androidfw_test_cflags := \
- -Wall \
- -Werror \
- -Wunused \
- -Wunreachable-code \
- -Wno-missing-field-initializers
-
-# gtest is broken.
-androidfw_test_cflags += -Wno-unnamed-type-template-args
-
-# ==========================================================
-# Build the host tests: libandroidfw_tests
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libandroidfw_tests
-LOCAL_CFLAGS := $(androidfw_test_cflags)
-LOCAL_SRC_FILES := $(testFiles)
-LOCAL_STATIC_LIBRARIES := \
- libandroidfw \
- libbase \
- libutils \
- libcutils \
- liblog \
- libz \
- libziparchive
-LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
-
-include $(BUILD_HOST_NATIVE_TEST)
-
-# ==========================================================
-# Build the device tests: libandroidfw_tests
-# ==========================================================
-ifneq ($(SDK_ONLY),true)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libandroidfw_tests
-LOCAL_CFLAGS := $(androidfw_test_cflags)
-LOCAL_SRC_FILES := $(testFiles) \
- BackupData_test.cpp \
- ObbFile_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- libandroidfw \
- libbase \
- libcutils \
- libutils \
- libui \
- libziparchive
-LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
-
-include $(BUILD_NATIVE_TEST)
-
-# ==========================================================
-# Build the device benchmarks: libandroidfw_benchmarks
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libandroidfw_benchmarks
-LOCAL_CFLAGS := $(androidfw_test_cflags)
-LOCAL_SRC_FILES := $(benchmarkFiles)
-LOCAL_STATIC_LIBRARIES := \
- libgoogle-benchmark
-LOCAL_SHARED_LIBRARIES := \
- libandroidfw \
- libbase \
- libcutils \
- libutils \
- libziparchive
-LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
-
-include $(BUILD_NATIVE_TEST)
-endif # Not SDK_ONLY
-
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 67de741..99a07a5 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -23,7 +23,6 @@
#include "androidfw/ResourceTypes.h"
#include "BenchmarkHelpers.h"
-#include "TestHelpers.h"
#include "data/basic/R.h"
#include "data/libclient/R.h"
#include "data/styles/R.h"
diff --git a/libs/androidfw/tests/BenchMain.cpp b/libs/androidfw/tests/BenchMain.cpp
index 105c5f9..58fc54a 100644
--- a/libs/androidfw/tests/BenchMain.cpp
+++ b/libs/androidfw/tests/BenchMain.cpp
@@ -18,7 +18,7 @@
#include "benchmark/benchmark.h"
-#include "TestHelpers.h"
+#include "BenchmarkHelpers.h"
int main(int argc, char** argv) {
::benchmark::Initialize(&argc, argv);
diff --git a/libs/androidfw/tests/BenchmarkHelpers.h b/libs/androidfw/tests/BenchmarkHelpers.h
index fc36664..0bb96b5 100644
--- a/libs/androidfw/tests/BenchmarkHelpers.h
+++ b/libs/androidfw/tests/BenchmarkHelpers.h
@@ -14,21 +14,22 @@
* limitations under the License.
*/
-#ifndef TESTS_BENCHMARKHELPERS_H_
-#define TESTS_BENCHMARKHELPERS_H_
+#ifndef ANDROIDFW_TESTS_BENCHMARKHELPERS_H
+#define ANDROIDFW_TESTS_BENCHMARKHELPERS_H
#include <string>
#include <vector>
+#include "androidfw/ResourceTypes.h"
#include "benchmark/benchmark.h"
-#include "androidfw/ResourceTypes.h"
+#include "CommonHelpers.h"
namespace android {
void GetResourceBenchmarkOld(const std::vector<std::string>& paths, const ResTable_config* config,
- uint32_t resid, benchmark::State& state);
+ uint32_t resid, ::benchmark::State& state);
} // namespace android
-#endif /* TESTS_BENCHMARKHELPERS_H_ */
+#endif // ANDROIDFW_TESTS_BENCHMARKHELPERS_H
diff --git a/libs/androidfw/tests/CommonHelpers.cpp b/libs/androidfw/tests/CommonHelpers.cpp
new file mode 100644
index 0000000..faa5350
--- /dev/null
+++ b/libs/androidfw/tests/CommonHelpers.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CommonHelpers.h"
+
+#include <iostream>
+
+#include "android-base/file.h"
+#include "android-base/logging.h"
+#include "android-base/strings.h"
+
+namespace android {
+
+static std::string sTestDataPath;
+
+void InitializeTest(int* argc, char** argv) {
+ // Set the default test data path to be the executable path directory + data.
+ SetTestDataPath(base::GetExecutableDirectory() + "/tests/data");
+
+ for (int i = 1; i < *argc; i++) {
+ const std::string arg = argv[i];
+ if (base::StartsWith(arg, "--testdata=")) {
+ SetTestDataPath(arg.substr(strlen("--testdata=")));
+ for (int j = i; j != *argc; j++) {
+ argv[j] = argv[j + 1];
+ }
+ --(*argc);
+ --i;
+ } else if (arg == "-h" || arg == "--help") {
+ std::cerr << "\nAdditional options specific to this test:\n"
+ " --testdata=[PATH]\n"
+ " Specify the location of test data used within the tests.\n";
+ exit(1);
+ }
+ }
+}
+
+void SetTestDataPath(const std::string& path) {
+ sTestDataPath = path;
+}
+
+const std::string& GetTestDataPath() {
+ CHECK(!sTestDataPath.empty()) << "no test data path set.";
+ return sTestDataPath;
+}
+
+std::string GetStringFromPool(const ResStringPool* pool, uint32_t idx) {
+ String8 str = pool->string8ObjectAt(idx);
+ return std::string(str.string(), str.length());
+}
+
+} // namespace android
diff --git a/libs/androidfw/tests/CommonHelpers.h b/libs/androidfw/tests/CommonHelpers.h
new file mode 100644
index 0000000..c160fbb
--- /dev/null
+++ b/libs/androidfw/tests/CommonHelpers.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROIDFW_TEST_COMMON_HELPERS_H
+#define ANDROIDFW_TEST_COMMON_HELPERS_H
+
+#include <ostream>
+#include <string>
+
+#include "androidfw/ResourceTypes.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
+
+namespace android {
+
+void InitializeTest(int* argc, char** argv);
+
+enum { MAY_NOT_BE_BAG = false };
+
+void SetTestDataPath(const std::string& path);
+
+const std::string& GetTestDataPath();
+
+std::string GetStringFromPool(const ResStringPool* pool, uint32_t idx);
+
+static inline bool operator==(const ResTable_config& a, const ResTable_config& b) {
+ return a.compare(b) == 0;
+}
+
+static inline ::std::ostream& operator<<(::std::ostream& out, const String8& str) {
+ return out << str.string();
+}
+
+static inline ::std::ostream& operator<<(::std::ostream& out, const String16& str) {
+ return out << String8(str).string();
+}
+
+static inline ::std::ostream& operator<<(::std::ostream& out, const ResTable_config& c) {
+ return out << c.toString();
+}
+
+} // namespace android
+
+#endif // ANDROIDFW_TEST_COMMON_HELPERS_H
diff --git a/libs/androidfw/tests/SparseEntry_bench.cpp b/libs/androidfw/tests/SparseEntry_bench.cpp
index 1ebf7ce..d6dc07d 100644
--- a/libs/androidfw/tests/SparseEntry_bench.cpp
+++ b/libs/androidfw/tests/SparseEntry_bench.cpp
@@ -18,7 +18,6 @@
#include "androidfw/ResourceTypes.h"
#include "BenchmarkHelpers.h"
-#include "TestHelpers.h"
#include "data/sparse/R.h"
namespace sparse = com::android::sparse;
diff --git a/libs/androidfw/tests/TestHelpers.cpp b/libs/androidfw/tests/TestHelpers.cpp
index 1e763a5..9e320a2 100644
--- a/libs/androidfw/tests/TestHelpers.cpp
+++ b/libs/androidfw/tests/TestHelpers.cpp
@@ -16,67 +16,22 @@
#include "TestHelpers.h"
-#include <libgen.h>
-#include <unistd.h>
-
-#include <memory>
-#include <string>
-
-#include "android-base/file.h"
-#include "android-base/logging.h"
-#include "android-base/strings.h"
#include "ziparchive/zip_archive.h"
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+
namespace android {
-static std::string sTestDataPath;
-
-// Extract the directory of the current executable path.
-static std::string GetExecutableDir() {
- const std::string path = base::GetExecutablePath();
- std::unique_ptr<char, decltype(&std::free)> mutable_path = {strdup(path.c_str()), std::free};
- std::string executable_dir = dirname(mutable_path.get());
- return executable_dir;
-}
-
-void InitializeTest(int* argc, char** argv) {
- // Set the default test data path to be the executable path directory.
- SetTestDataPath(GetExecutableDir());
-
- for (int i = 1; i < *argc; i++) {
- const std::string arg = argv[i];
- if (base::StartsWith(arg, "--testdata=")) {
- SetTestDataPath(arg.substr(strlen("--testdata=")));
- for (int j = i; j != *argc; j++) {
- argv[j] = argv[j + 1];
- }
- --(*argc);
- --i;
- } else if (arg == "-h" || arg == "--help") {
- std::cerr << "\nAdditional options specific to this test:\n"
- " --testdata=[PATH]\n"
- " Specify the location of test data used within the tests.\n";
- exit(1);
- }
- }
-}
-
-void SetTestDataPath(const std::string& path) { sTestDataPath = path; }
-
-const std::string& GetTestDataPath() {
- CHECK(!sTestDataPath.empty()) << "no test data path set.";
- return sTestDataPath;
-}
-
-::testing::AssertionResult ReadFileFromZipToString(const std::string& zip_path,
- const std::string& file,
- std::string* out_contents) {
+AssertionResult ReadFileFromZipToString(const std::string& zip_path, const std::string& file,
+ std::string* out_contents) {
out_contents->clear();
::ZipArchiveHandle handle;
int32_t result = OpenArchive(zip_path.c_str(), &handle);
if (result != 0) {
- return ::testing::AssertionFailure() << "Failed to open zip '" << zip_path
- << "': " << ::ErrorCodeString(result);
+ return AssertionFailure() << "Failed to open zip '" << zip_path
+ << "': " << ::ErrorCodeString(result);
}
::ZipString name(file.c_str());
@@ -84,8 +39,8 @@
result = ::FindEntry(handle, name, &entry);
if (result != 0) {
::CloseArchive(handle);
- return ::testing::AssertionFailure() << "Could not find file '" << file << "' in zip '"
- << zip_path << "' : " << ::ErrorCodeString(result);
+ return AssertionFailure() << "Could not find file '" << file << "' in zip '" << zip_path
+ << "' : " << ::ErrorCodeString(result);
}
out_contents->resize(entry.uncompressed_length);
@@ -94,41 +49,36 @@
out_contents->size());
if (result != 0) {
::CloseArchive(handle);
- return ::testing::AssertionFailure() << "Failed to extract file '" << file << "' from zip '"
- << zip_path << "': " << ::ErrorCodeString(result);
+ return AssertionFailure() << "Failed to extract file '" << file << "' from zip '" << zip_path
+ << "': " << ::ErrorCodeString(result);
}
::CloseArchive(handle);
- return ::testing::AssertionSuccess();
+ return AssertionSuccess();
}
-::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
- const char* expected_str) {
+AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
+ const char* expected_str) {
Res_value val;
ssize_t block = table.getResource(resource_id, &val, MAY_NOT_BE_BAG);
if (block < 0) {
- return ::testing::AssertionFailure() << "could not find resource";
+ return AssertionFailure() << "could not find resource";
}
if (val.dataType != Res_value::TYPE_STRING) {
- return ::testing::AssertionFailure() << "resource is not a string";
+ return AssertionFailure() << "resource is not a string";
}
const ResStringPool* pool = table.getTableStringBlock(block);
if (pool == NULL) {
- return ::testing::AssertionFailure() << "table has no string pool for block " << block;
+ return AssertionFailure() << "table has no string pool for block " << block;
}
const String8 actual_str = pool->string8ObjectAt(val.data);
if (String8(expected_str) != actual_str) {
- return ::testing::AssertionFailure() << actual_str.string();
+ return AssertionFailure() << actual_str.string();
}
- return ::testing::AssertionSuccess() << actual_str.string();
-}
-
-std::string GetStringFromPool(const ResStringPool* pool, uint32_t idx) {
- String8 str = pool->string8ObjectAt(idx);
- return std::string(str.string(), str.length());
+ return AssertionSuccess() << actual_str.string();
}
} // namespace android
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index ec78b2a..43a9955 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -14,53 +14,25 @@
* limitations under the License.
*/
-#ifndef TEST_HELPERS_H_
-#define TEST_HELPERS_H_
+#ifndef ANDROIDFW_TEST_TESTHELPERS_H
+#define ANDROIDFW_TEST_TESTHELPERS_H
-#include <ostream>
#include <string>
-#include <vector>
#include "androidfw/ResourceTypes.h"
#include "gtest/gtest.h"
-#include "utils/String16.h"
-#include "utils/String8.h"
-static inline ::std::ostream& operator<<(::std::ostream& out, const android::String8& str) {
- return out << str.string();
-}
-
-static inline ::std::ostream& operator<<(::std::ostream& out, const android::String16& str) {
- return out << android::String8(str).string();
-}
+#include "CommonHelpers.h"
namespace android {
-void InitializeTest(int* argc, char** argv);
-
-enum { MAY_NOT_BE_BAG = false };
-
-void SetTestDataPath(const std::string& path);
-
-const std::string& GetTestDataPath();
-
::testing::AssertionResult ReadFileFromZipToString(const std::string& zip_path,
const std::string& file,
std::string* out_contents);
-static inline bool operator==(const ResTable_config& a, const ResTable_config& b) {
- return a.compare(b) == 0;
-}
-
-static inline ::std::ostream& operator<<(::std::ostream& out, const ResTable_config& c) {
- return out << c.toString().string();
-}
-
::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
const char* expected_str);
-std::string GetStringFromPool(const ResStringPool* pool, uint32_t idx);
-
} // namespace android
-#endif // TEST_HELPERS_H_
+#endif // ANDROIDFW_TEST_TESTHELPERS_H
diff --git a/libs/hwui/ProfileDataContainer.cpp b/libs/hwui/ProfileDataContainer.cpp
index cbf3eb3..70a77ed 100644
--- a/libs/hwui/ProfileDataContainer.cpp
+++ b/libs/hwui/ProfileDataContainer.cpp
@@ -16,6 +16,8 @@
#include "ProfileDataContainer.h"
+#include <errno.h>
+
#include <log/log.h>
#include <cutils/ashmem.h>
@@ -75,4 +77,4 @@
}
} /* namespace uirenderer */
-} /* namespace android */
\ No newline at end of file
+} /* namespace android */
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index afb1193..f7a90b0 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -22,10 +22,11 @@
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <log/log.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#include <sys/mman.h>
@@ -366,4 +367,4 @@
}
} /* namespace uirenderer */
-} /* namespace android */
\ No newline at end of file
+} /* namespace android */
diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
index c1ca1e7..1e30d23 100644
--- a/libs/hwui/tests/common/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -81,10 +81,10 @@
mSurfaceControl = mSurfaceComposerClient->createSurface(String8("HwuiTest"),
gDisplay.w, gDisplay.h, PIXEL_FORMAT_RGBX_8888);
- SurfaceComposerClient::openGlobalTransaction();
- mSurfaceControl->setLayer(0x7FFFFFF);
- mSurfaceControl->show();
- SurfaceComposerClient::closeGlobalTransaction();
+ SurfaceComposerClient::Transaction t;
+ t.setLayer(mSurfaceControl, 0x7FFFFFF)
+ .show(mSurfaceControl)
+ .apply();
mSurface = mSurfaceControl->getSurface();
}
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index ed31b12..173cd50 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -148,8 +148,9 @@
}
}
- // Resize sprites if needed, inside a global transaction.
- bool haveGlobalTransaction = false;
+ // Resize sprites if needed.
+ SurfaceComposerClient::Transaction t;
+ bool needApplyTransaction = false;
for (size_t i = 0; i < numSprites; i++) {
SpriteUpdate& update = updates.editItemAt(i);
@@ -158,36 +159,24 @@
int32_t desiredHeight = update.state.icon.bitmap.height();
if (update.state.surfaceWidth < desiredWidth
|| update.state.surfaceHeight < desiredHeight) {
- if (!haveGlobalTransaction) {
- SurfaceComposerClient::openGlobalTransaction();
- haveGlobalTransaction = true;
- }
+ needApplyTransaction = true;
- status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
- if (status) {
- ALOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
- status, update.state.surfaceWidth, update.state.surfaceHeight,
- desiredWidth, desiredHeight);
- } else {
- update.state.surfaceWidth = desiredWidth;
- update.state.surfaceHeight = desiredHeight;
- update.state.surfaceDrawn = false;
- update.surfaceChanged = surfaceChanged = true;
+ t.setSize(update.state.surfaceControl,
+ desiredWidth, desiredHeight);
+ update.state.surfaceWidth = desiredWidth;
+ update.state.surfaceHeight = desiredHeight;
+ update.state.surfaceDrawn = false;
+ update.surfaceChanged = surfaceChanged = true;
- if (update.state.surfaceVisible) {
- status = update.state.surfaceControl->hide();
- if (status) {
- ALOGE("Error %d hiding sprite surface after resize.", status);
- } else {
- update.state.surfaceVisible = false;
- }
- }
+ if (update.state.surfaceVisible) {
+ t.hide(update.state.surfaceControl);
+ update.state.surfaceVisible = false;
}
}
}
}
- if (haveGlobalTransaction) {
- SurfaceComposerClient::closeGlobalTransaction();
+ if (needApplyTransaction) {
+ t.apply();
}
// Redraw sprites if needed.
@@ -240,8 +229,7 @@
}
}
- // Set sprite surface properties and make them visible.
- bool haveTransaction = false;
+ needApplyTransaction = false;
for (size_t i = 0; i < numSprites; i++) {
SpriteUpdate& update = updates.editItemAt(i);
@@ -253,75 +241,59 @@
|| (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
| DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
| DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
- status_t status;
- if (!haveTransaction) {
- SurfaceComposerClient::openGlobalTransaction();
- haveTransaction = true;
- }
+ needApplyTransaction = true;
if (wantSurfaceVisibleAndDrawn
&& (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) {
- status = update.state.surfaceControl->setAlpha(update.state.alpha);
- if (status) {
- ALOGE("Error %d setting sprite surface alpha.", status);
- }
+ t.setAlpha(update.state.surfaceControl,
+ update.state.alpha);
}
if (wantSurfaceVisibleAndDrawn
&& (becomingVisible || (update.state.dirty & (DIRTY_POSITION
| DIRTY_HOTSPOT)))) {
- status = update.state.surfaceControl->setPosition(
+ t.setPosition(
+ update.state.surfaceControl,
update.state.positionX - update.state.icon.hotSpotX,
update.state.positionY - update.state.icon.hotSpotY);
- if (status) {
- ALOGE("Error %d setting sprite surface position.", status);
- }
}
if (wantSurfaceVisibleAndDrawn
&& (becomingVisible
|| (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) {
- status = update.state.surfaceControl->setMatrix(
+ t.setMatrix(
+ update.state.surfaceControl,
update.state.transformationMatrix.dsdx,
update.state.transformationMatrix.dtdx,
update.state.transformationMatrix.dsdy,
update.state.transformationMatrix.dtdy);
- if (status) {
- ALOGE("Error %d setting sprite surface transformation matrix.", status);
- }
}
int32_t surfaceLayer = mOverlayLayer + update.state.layer;
if (wantSurfaceVisibleAndDrawn
&& (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
- status = update.state.surfaceControl->setLayer(surfaceLayer);
- if (status) {
- ALOGE("Error %d setting sprite surface layer.", status);
- }
+ t.setLayer(update.state.surfaceControl, surfaceLayer);
}
if (becomingVisible) {
- status = update.state.surfaceControl->show();
- if (status) {
- ALOGE("Error %d showing sprite surface.", status);
- } else {
- update.state.surfaceVisible = true;
- update.surfaceChanged = surfaceChanged = true;
- }
+ t.show(update.state.surfaceControl);
+
+ update.state.surfaceVisible = true;
+ update.surfaceChanged = surfaceChanged = true;
} else if (becomingHidden) {
- status = update.state.surfaceControl->hide();
- if (status) {
- ALOGE("Error %d hiding sprite surface.", status);
- } else {
- update.state.surfaceVisible = false;
- update.surfaceChanged = surfaceChanged = true;
- }
+ t.hide(update.state.surfaceControl);
+
+ update.state.surfaceVisible = false;
+ update.surfaceChanged = surfaceChanged = true;
}
}
}
- if (haveTransaction) {
- SurfaceComposerClient::closeGlobalTransaction();
+ if (needApplyTransaction) {
+ status_t status = t.apply();
+ if (status) {
+ ALOGE("Error applying Surface transaction");
+ }
}
// If any surfaces were changed, write back the new surface properties to the sprites.
diff --git a/libs/protoutil/Android.mk b/libs/protoutil/Android.mk
index a534816..2a2b087 100644
--- a/libs/protoutil/Android.mk
+++ b/libs/protoutil/Android.mk
@@ -22,15 +22,15 @@
-Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
LOCAL_SHARED_LIBRARIES := \
- libbinder \
+ libcutils \
liblog \
- libutils
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include
LOCAL_SRC_FILES := \
src/EncodedBuffer.cpp \
+ src/ProtoOutputStream.cpp \
src/protobuf.cpp \
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
diff --git a/libs/protoutil/include/android/util/EncodedBuffer.h b/libs/protoutil/include/android/util/EncodedBuffer.h
index cf09609..e568e4c 100644
--- a/libs/protoutil/include/android/util/EncodedBuffer.h
+++ b/libs/protoutil/include/android/util/EncodedBuffer.h
@@ -52,10 +52,10 @@
size_t index() const;
size_t offset() const;
- void move(size_t amt);
- inline void move() { move(1); };
+ Pointer* move(size_t amt);
+ inline Pointer* move() { return move(1); };
+ Pointer* rewind();
- void rewind();
Pointer copy() const;
private:
@@ -88,15 +88,71 @@
size_t currentToWrite();
/**
- * Write a varint into a vector. Return the size of the varint.
+ * Write a single byte to the buffer.
*/
- size_t writeRawVarint(uint32_t val);
+ void writeRawByte(uint8_t val);
+
+ /**
+ * Write a varint32 into the buffer. Return the size of the varint.
+ */
+ size_t writeRawVarint32(uint32_t val);
+
+ /**
+ * Write a varint64 into the buffer. Return the size of the varint.
+ */
+ size_t writeRawVarint64(uint64_t val);
+
+ /**
+ * Write Fixed32 into the buffer.
+ */
+ void writeRawFixed32(uint32_t val);
+
+ /**
+ * Write Fixed64 into the buffer.
+ */
+ void writeRawFixed64(uint64_t val);
/**
* Write a protobuf header. Return the size of the header.
*/
size_t writeHeader(uint32_t fieldId, uint8_t wireType);
+ /********************************* Edit APIs ************************************************/
+ /**
+ * Returns the edit pointer.
+ */
+ Pointer* ep();
+
+ /**
+ * Read a single byte at ep, and move ep to next byte;
+ */
+ uint8_t readRawByte();
+
+ /**
+ * Read varint starting at ep, ep will move to pos of next byte.
+ */
+ uint64_t readRawVarint();
+
+ /**
+ * Read 4 bytes starting at ep, ep will move to pos of next byte.
+ */
+ uint32_t readRawFixed32();
+
+ /**
+ * Read 8 bytes starting at ep, ep will move to pos of next byte.
+ */
+ uint64_t readRawFixed64();
+
+ /**
+ * Edit 4 bytes starting at pos.
+ */
+ void editRawFixed32(size_t pos, uint32_t val);
+
+ /**
+ * Copy _size_ bytes of data starting at __srcPos__ to wp.
+ */
+ void copy(size_t srcPos, size_t size);
+
/********************************* Read APIs ************************************************/
class iterator;
friend class iterator;
@@ -141,9 +197,8 @@
/**
* Read varint from iterator, the iterator will point to next available byte.
- * Return the number of bytes of the varint.
*/
- uint32_t readRawVarint();
+ uint64_t readRawVarint();
private:
const EncodedBuffer& mData;
@@ -160,6 +215,7 @@
vector<uint8_t*> mBuffers;
Pointer mWp;
+ Pointer mEp;
inline uint8_t* at(const Pointer& p) const; // helper function to get value
};
@@ -167,4 +223,5 @@
} // util
} // android
-#endif // ANDROID_UTIL_ENCODED_BUFFER_H
\ No newline at end of file
+#endif // ANDROID_UTIL_ENCODED_BUFFER_H
+
diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h
new file mode 100644
index 0000000..49ec169
--- /dev/null
+++ b/libs/protoutil/include/android/util/ProtoOutputStream.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_UTIL_PROTOOUTPUT_STREAM_H
+#define ANDROID_UTIL_PROTOOUTPUT_STREAM_H
+
+#include <android/util/EncodedBuffer.h>
+
+#include <stdint.h>
+#include <string>
+
+namespace android {
+namespace util {
+
+/**
+ * Class to write to a protobuf stream.
+ *
+ * Each write method takes an ID code from the protoc generated classes
+ * and the value to write. To make a nested object, call start
+ * and then end when you are done.
+ *
+ * See the java version implementation (ProtoOutputStream.java) for more infos.
+ */
+class ProtoOutputStream
+{
+public:
+ ProtoOutputStream(int fd);
+ ~ProtoOutputStream();
+
+ /**
+ * Write APIs for dumping protobuf data. Returns true if the write succeeds.
+ */
+ bool write(uint64_t fieldId, double val);
+ bool write(uint64_t fieldId, float val);
+ bool write(uint64_t fieldId, int val);
+ bool write(uint64_t fieldId, long long val);
+ bool write(uint64_t fieldId, bool val);
+ bool write(uint64_t fieldId, std::string val);
+ bool write(uint64_t fieldId, const char* val);
+
+ /**
+ * Starts a sub-message write session.
+ * Returns a token of this write session.
+ * Must call end(token) when finish write this sub-message.
+ */
+ long long start(uint64_t fieldId);
+ void end(long long token);
+
+ /**
+ * Flushes the protobuf data out.
+ */
+ bool flush();
+
+private:
+ EncodedBuffer mBuffer;
+ int mFd;
+ size_t mCopyBegin;
+ bool mCompact;
+ int mDepth;
+ int mObjectId;
+ long long mExpectedObjectToken;
+
+ inline void writeDoubleImpl(uint32_t id, double val);
+ inline void writeFloatImpl(uint32_t id, float val);
+ inline void writeInt64Impl(uint32_t id, long long val);
+ inline void writeInt32Impl(uint32_t id, int val);
+ inline void writeUint64Impl(uint32_t id, uint64_t val);
+ inline void writeUint32Impl(uint32_t id, uint32_t val);
+ inline void writeFixed64Impl(uint32_t id, uint64_t val);
+ inline void writeFixed32Impl(uint32_t id, uint32_t val);
+ inline void writeSFixed64Impl(uint32_t id, long long val);
+ inline void writeSFixed32Impl(uint32_t id, int val);
+ inline void writeZigzagInt64Impl(uint32_t id, long long val);
+ inline void writeZigzagInt32Impl(uint32_t id, int val);
+ inline void writeEnumImpl(uint32_t id, int val);
+ inline void writeBoolImpl(uint32_t id, bool val);
+ inline void writeUtf8StringImpl(uint32_t id, const char* val, size_t size);
+
+ bool compact();
+ size_t editEncodedSize(size_t rawSize);
+ bool compactSize(size_t rawSize);
+};
+
+}
+}
+
+#endif // ANDROID_UTIL_PROTOOUTPUT_STREAM_H
\ No newline at end of file
diff --git a/libs/protoutil/include/android/util/protobuf.h b/libs/protoutil/include/android/util/protobuf.h
index f4e8d09..ca45e26 100644
--- a/libs/protoutil/include/android/util/protobuf.h
+++ b/libs/protoutil/include/android/util/protobuf.h
@@ -24,6 +24,9 @@
using namespace std;
+const int FIELD_ID_SHIFT = 3;
+const uint8_t WIRE_TYPE_MASK = (1 << FIELD_ID_SHIFT) - 1;
+
const uint8_t WIRE_TYPE_VARINT = 0;
const uint8_t WIRE_TYPE_FIXED64 = 1;
const uint8_t WIRE_TYPE_LENGTH_DELIMITED = 2;
@@ -35,16 +38,20 @@
uint8_t read_wire_type(uint32_t varint);
/**
- * read field id from varint, it is varint >> 3;
+ * Read field id from varint, it is varint >> 3;
*/
uint32_t read_field_id(uint32_t varint);
/**
- * Write a varint into the buffer. Return the next position to write at.
- * There must be 10 bytes in the buffer. The same as
- * EncodedBuffer.writeRawVarint32
+ * Get the size of a varint.
*/
-uint8_t* write_raw_varint(uint8_t* buf, uint32_t val);
+size_t get_varint_size(uint64_t varint);
+
+/**
+ * Write a varint into the buffer. Return the next position to write at.
+ * There must be 10 bytes in the buffer.
+ */
+uint8_t* write_raw_varint(uint8_t* buf, uint64_t val);
/**
* Write a protobuf WIRE_TYPE_LENGTH_DELIMITED header. Return the next position
diff --git a/libs/protoutil/src/EncodedBuffer.cpp b/libs/protoutil/src/EncodedBuffer.cpp
index 84dc5b6..435ae88 100644
--- a/libs/protoutil/src/EncodedBuffer.cpp
+++ b/libs/protoutil/src/EncodedBuffer.cpp
@@ -15,6 +15,7 @@
*/
#include <android/util/EncodedBuffer.h>
+#include <android/util/protobuf.h>
#include <stdlib.h>
@@ -52,19 +53,21 @@
return mOffset;
}
-void
+EncodedBuffer::Pointer*
EncodedBuffer::Pointer::move(size_t amt)
{
size_t newOffset = mOffset + amt;
mIndex += newOffset / mChunkSize;
mOffset = newOffset % mChunkSize;
+ return this;
}
-void
+EncodedBuffer::Pointer*
EncodedBuffer::Pointer::rewind()
{
mIndex = 0;
mOffset = 0;
+ return this;
}
EncodedBuffer::Pointer
@@ -86,6 +89,7 @@
{
mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
mWp = Pointer(mChunkSize);
+ mEp = Pointer(mChunkSize);
}
EncodedBuffer::~EncodedBuffer()
@@ -137,28 +141,136 @@
return mChunkSize - mWp.offset();
}
+void
+EncodedBuffer::writeRawByte(uint8_t val)
+{
+ *writeBuffer() = val;
+ mWp.move();
+}
+
size_t
-EncodedBuffer::writeRawVarint(uint32_t val)
+EncodedBuffer::writeRawVarint64(uint64_t val)
{
size_t size = 0;
while (true) {
size++;
if ((val & ~0x7F) == 0) {
- *writeBuffer() = (uint8_t) val;
- mWp.move();
+ writeRawByte((uint8_t) val);
return size;
} else {
- *writeBuffer() = (uint8_t)((val & 0x7F) | 0x80);
- mWp.move();
+ writeRawByte((uint8_t)((val & 0x7F) | 0x80));
val >>= 7;
}
}
}
size_t
+EncodedBuffer::writeRawVarint32(uint32_t val)
+{
+ uint64_t v =(uint64_t)val;
+ return writeRawVarint64(v);
+}
+
+void
+EncodedBuffer::writeRawFixed32(uint32_t val)
+{
+ writeRawByte((uint8_t) val);
+ writeRawByte((uint8_t) (val>>8));
+ writeRawByte((uint8_t) (val>>16));
+ writeRawByte((uint8_t) (val>>24));
+}
+
+void
+EncodedBuffer::writeRawFixed64(uint64_t val)
+{
+ writeRawByte((uint8_t) val);
+ writeRawByte((uint8_t) (val>>8));
+ writeRawByte((uint8_t) (val>>16));
+ writeRawByte((uint8_t) (val>>24));
+ writeRawByte((uint8_t) (val>>32));
+ writeRawByte((uint8_t) (val>>40));
+ writeRawByte((uint8_t) (val>>48));
+ writeRawByte((uint8_t) (val>>56));
+}
+
+size_t
EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType)
{
- return writeRawVarint((fieldId << 3) | wireType);
+ return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType);
+}
+
+/******************************** Edit APIs ************************************************/
+EncodedBuffer::Pointer*
+EncodedBuffer::ep()
+{
+ return &mEp;
+}
+
+uint8_t
+EncodedBuffer::readRawByte()
+{
+ uint8_t val = *at(mEp);
+ mEp.move();
+ return val;
+}
+
+uint64_t
+EncodedBuffer::readRawVarint()
+{
+ uint64_t val = 0, shift = 0;
+ size_t start = mEp.pos();
+ while (true) {
+ uint8_t byte = readRawByte();
+ val += (byte & 0x7F) << shift;
+ if ((byte & 0x80) == 0) break;
+ shift += 7;
+ }
+ return val;
+}
+
+uint32_t
+EncodedBuffer::readRawFixed32()
+{
+ uint32_t val = 0;
+ for (auto i=0; i<32; i+=8) {
+ val += (uint32_t)readRawByte() << i;
+ }
+ return val;
+}
+
+uint64_t
+EncodedBuffer::readRawFixed64()
+{
+ uint64_t val = 0;
+ for (auto i=0; i<64; i+=8) {
+ val += (uint64_t)readRawByte() << i;
+ }
+ return val;
+}
+
+void
+EncodedBuffer::editRawFixed32(size_t pos, uint32_t val)
+{
+ size_t oldPos = mEp.pos();
+ mEp.rewind()->move(pos);
+ for (auto i=0; i<32; i+=8) {
+ *at(mEp) = (uint8_t) (val >> i);
+ mEp.move();
+ }
+ mEp.rewind()->move(oldPos);
+}
+
+void
+EncodedBuffer::copy(size_t srcPos, size_t size)
+{
+ if (size == 0) return;
+ Pointer cp(mChunkSize);
+ cp.move(srcPos);
+
+ while (cp.pos() < srcPos + size) {
+ writeRawByte(*at(cp));
+ cp.move();
+ }
}
/********************************* Read APIs ************************************************/
@@ -220,10 +332,10 @@
return res;
}
-uint32_t
+uint64_t
EncodedBuffer::iterator::readRawVarint()
{
- uint32_t val = 0, shift = 0;
+ uint64_t val = 0, shift = 0;
while (true) {
uint8_t byte = next();
val += (byte & 0x7F) << shift;
diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp
new file mode 100644
index 0000000..e9ca0dc
--- /dev/null
+++ b/libs/protoutil/src/ProtoOutputStream.cpp
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+#define LOG_TAG "libprotoutil"
+
+#include <android/util/protobuf.h>
+#include <android/util/ProtoOutputStream.h>
+#include <cutils/log.h>
+#include <cstring>
+
+namespace android {
+namespace util {
+
+/**
+ * Position of the field type in a (long long) fieldId.
+ */
+const uint64_t FIELD_TYPE_SHIFT = 32;
+
+/**
+ * Mask for the field types stored in a fieldId. Leaves a whole
+ * byte for future expansion, even though there are currently only 17 types.
+ */
+const uint64_t FIELD_TYPE_MASK = 0x0ffULL << FIELD_TYPE_SHIFT;
+
+const uint64_t FIELD_TYPE_UNKNOWN = 0;
+const uint64_t TYPE_DOUBLE = 1ULL << FIELD_TYPE_SHIFT; // double, exactly eight bytes on the wire.
+const uint64_t TYPE_FLOAT = 2ULL << FIELD_TYPE_SHIFT; // float, exactly four bytes on the wire.
+const uint64_t TYPE_INT64 = 3ULL << FIELD_TYPE_SHIFT; // int64, varint on the wire. Negative numbers
+ // take 10 bytes. Use TYPE_SINT64 if negative
+ // values are likely.
+const uint64_t TYPE_UINT64 = 4ULL << FIELD_TYPE_SHIFT; // uint64, varint on the wire.
+const uint64_t TYPE_INT32 = 5ULL << FIELD_TYPE_SHIFT; // int32, varint on the wire. Negative numbers
+ // take 10 bytes. Use TYPE_SINT32 if negative
+ // values are likely.
+const uint64_t TYPE_FIXED64 = 6ULL << FIELD_TYPE_SHIFT; // uint64, exactly eight bytes on the wire.
+const uint64_t TYPE_FIXED32 = 7ULL << FIELD_TYPE_SHIFT; // uint32, exactly four bytes on the wire.
+const uint64_t TYPE_BOOL = 8ULL << FIELD_TYPE_SHIFT; // bool, varint on the wire.
+const uint64_t TYPE_STRING = 9ULL << FIELD_TYPE_SHIFT; // UTF-8 text.
+const uint64_t TYPE_GROUP = 10ULL << FIELD_TYPE_SHIFT; // Tag-delimited message. Deprecated.
+const uint64_t TYPE_MESSAGE = 11ULL << FIELD_TYPE_SHIFT; // Length-delimited message.
+
+const uint64_t TYPE_BYTES = 12ULL << FIELD_TYPE_SHIFT; // Arbitrary byte array.
+const uint64_t TYPE_UINT32 = 13ULL << FIELD_TYPE_SHIFT; // uint32, varint on the wire
+const uint64_t TYPE_ENUM = 14ULL << FIELD_TYPE_SHIFT; // Enum, varint on the wire
+const uint64_t TYPE_SFIXED32 = 15ULL << FIELD_TYPE_SHIFT; // int32, exactly four bytes on the wire
+const uint64_t TYPE_SFIXED64 = 16ULL << FIELD_TYPE_SHIFT; // int64, exactly eight bytes on the wire
+const uint64_t TYPE_SINT32 = 17ULL << FIELD_TYPE_SHIFT; // int32, ZigZag-encoded varint on the wire
+const uint64_t TYPE_SINT64 = 18ULL << FIELD_TYPE_SHIFT; // int64, ZigZag-encoded varint on the wire
+
+//
+// FieldId flags for whether the field is single, repeated or packed.
+// TODO: packed is not supported yet.
+//
+const uint64_t FIELD_COUNT_SHIFT = 40;
+const uint64_t FIELD_COUNT_MASK = 0x0fULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_UNKNOWN = 0;
+const uint64_t FIELD_COUNT_SINGLE = 1ULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_REPEATED = 2ULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_PACKED = 4ULL << FIELD_COUNT_SHIFT;
+
+ProtoOutputStream::ProtoOutputStream(int fd)
+ :mBuffer(),
+ mFd(fd),
+ mCopyBegin(0),
+ mCompact(false),
+ mDepth(0),
+ mObjectId(0),
+ mExpectedObjectToken(0LL)
+{
+}
+
+ProtoOutputStream::~ProtoOutputStream()
+{
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, double val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
+ case TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
+ case TYPE_INT64: writeInt64Impl(id, (long long)val); break;
+ case TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
+ case TYPE_INT32: writeInt32Impl(id, (int)val); break;
+ case TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
+ case TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
+ case TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
+ case TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
+ case TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
+ case TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
+ case TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
+ default:
+ ALOGW("Field type %d is not supported when writing double val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, float val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
+ case TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
+ case TYPE_INT64: writeInt64Impl(id, (long long)val); break;
+ case TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
+ case TYPE_INT32: writeInt32Impl(id, (int)val); break;
+ case TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
+ case TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
+ case TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
+ case TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
+ case TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
+ case TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
+ case TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
+ default:
+ ALOGW("Field type %d is not supported when writing float val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, int val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
+ case TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
+ case TYPE_INT64: writeInt64Impl(id, (long long)val); break;
+ case TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
+ case TYPE_INT32: writeInt32Impl(id, (int)val); break;
+ case TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
+ case TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
+ case TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
+ case TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
+ case TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
+ case TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
+ case TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
+ case TYPE_ENUM: writeEnumImpl(id, (int)val); break;
+ case TYPE_BOOL: writeBoolImpl(id, val != 0); break;
+ default:
+ ALOGW("Field type %d is not supported when writing int val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, long long val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
+ case TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
+ case TYPE_INT64: writeInt64Impl(id, (long long)val); break;
+ case TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
+ case TYPE_INT32: writeInt32Impl(id, (int)val); break;
+ case TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
+ case TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
+ case TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
+ case TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
+ case TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
+ case TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
+ case TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
+ case TYPE_ENUM: writeEnumImpl(id, (int)val); break;
+ case TYPE_BOOL: writeBoolImpl(id, val != 0); break;
+ default:
+ ALOGW("Field type %d is not supported when writing long long val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, bool val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_BOOL:
+ writeBoolImpl(id, val);
+ return true;
+ default:
+ ALOGW("Field type %d is not supported when writing bool val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, string val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_STRING:
+ writeUtf8StringImpl(id, val.c_str(), val.size());
+ return true;
+ default:
+ ALOGW("Field type %d is not supported when writing string val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, const char* val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ int size = 0;
+ while (val[size] != '\0') size++;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_STRING:
+ writeUtf8StringImpl(id, val, size);
+ return true;
+ default:
+ ALOGW("Field type %d is not supported when writing char[] val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+}
+
+/**
+ * Make a token.
+ * Bits 61-63 - tag size (So we can go backwards later if the object had not data)
+ * - 3 bits, max value 7, max value needed 5
+ * Bit 60 - true if the object is repeated
+ * Bits 59-51 - depth (For error checking)
+ * - 9 bits, max value 512, when checking, value is masked (if we really
+ * are more than 512 levels deep)
+ * Bits 32-50 - objectId (For error checking)
+ * - 19 bits, max value 524,288. that's a lot of objects. IDs will wrap
+ * because of the overflow, and only the tokens are compared.
+ * Bits 0-31 - offset of the first size field in the buffer.
+ */
+long long
+makeToken(int tagSize, bool repeated, int depth, int objectId, int sizePos) {
+ return ((0x07L & (long long)tagSize) << 61)
+ | (repeated ? (1LL << 60) : 0)
+ | (0x01ffL & (long long)depth) << 51
+ | (0x07ffffL & (long long)objectId) << 32
+ | (0x0ffffffffL & (long long)sizePos);
+}
+
+/**
+ * Get the encoded tag size from the token.
+ */
+static int getTagSizeFromToken(long long token) {
+ return (int)(0x7 & (token >> 61));
+}
+
+/**
+ * Get the nesting depth of startObject calls from the token.
+ */
+static int getDepthFromToken(long long token) {
+ return (int)(0x01ff & (token >> 51));
+}
+
+/**
+ * Get the location of the childRawSize (the first 32 bit size field) in this object.
+ */
+static int getSizePosFromToken(long long token) {
+ return (int)token;
+}
+
+long long
+ProtoOutputStream::start(uint64_t fieldId)
+{
+ if ((fieldId & FIELD_TYPE_MASK) != TYPE_MESSAGE) {
+ ALOGE("Can't call start for non-message type field: 0x%llx", (long long)fieldId);
+ return 0;
+ }
+
+ uint32_t id = (uint32_t)fieldId;
+ mBuffer.writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
+
+ size_t sizePos = mBuffer.wp()->pos();
+
+ mDepth++;
+ mObjectId++;
+ mBuffer.writeRawFixed64(mExpectedObjectToken); // push previous token into stack.
+
+ mExpectedObjectToken = makeToken(get_varint_size(id),
+ (bool)(fieldId & FIELD_COUNT_REPEATED), mDepth, mObjectId, sizePos);
+ return mExpectedObjectToken;
+}
+
+void
+ProtoOutputStream::end(long long token)
+{
+ if (token != mExpectedObjectToken) {
+ ALOGE("Unexpected token: 0x%llx, should be 0x%llx", token, mExpectedObjectToken);
+ return;
+ }
+
+ int depth = getDepthFromToken(token);
+ if (depth != (mDepth & 0x01ff)) {
+ ALOGE("Unexpected depth: %d, should be %d", depth, mDepth);
+ return;
+ }
+ mDepth--;
+
+ int sizePos = getSizePosFromToken(token);
+ // number of bytes written in this start-end session.
+ int childRawSize = mBuffer.wp()->pos() - sizePos - 8;
+
+ // retrieve the old token from stack.
+ mBuffer.ep()->rewind()->move(sizePos);
+ mExpectedObjectToken = mBuffer.readRawFixed64();
+
+ // If raw size is larger than 0, write the negative value here to indicate a compact is needed.
+ if (childRawSize > 0) {
+ mBuffer.editRawFixed32(sizePos, -childRawSize);
+ mBuffer.editRawFixed32(sizePos+4, -1);
+ } else {
+ // reset wp which erase the header tag of the message when its size is 0.
+ mBuffer.wp()->rewind()->move(sizePos - getTagSizeFromToken(token));
+ }
+}
+
+bool
+ProtoOutputStream::compact() {
+ if (mCompact) return true;
+ if (mDepth != 0) {
+ ALOGE("Can't compact when depth(%d) is not zero. Missing calls to end.", mDepth);
+ return false;
+ }
+ // record the size of the original buffer.
+ size_t rawBufferSize = mBuffer.size();
+ if (rawBufferSize == 0) return true; // nothing to do if the buffer is empty;
+
+ // reset edit pointer and recursively compute encoded size of messages.
+ mBuffer.ep()->rewind();
+ if (editEncodedSize(rawBufferSize) == 0) {
+ ALOGE("Failed to editEncodedSize.");
+ return false;
+ }
+
+ // reset both edit pointer and write pointer, and compact recursively.
+ mBuffer.ep()->rewind();
+ mBuffer.wp()->rewind();
+ if (!compactSize(rawBufferSize)) {
+ ALOGE("Failed to compactSize.");
+ return false;
+ }
+ // copy the reset to the buffer.
+ if (mCopyBegin < rawBufferSize) {
+ mBuffer.copy(mCopyBegin, rawBufferSize - mCopyBegin);
+ }
+
+ // mark true means it is not legal to write to this ProtoOutputStream anymore
+ mCompact = true;
+ return true;
+}
+
+/**
+ * First compaction pass. Iterate through the data, and fill in the
+ * nested object sizes so the next pass can compact them.
+ */
+size_t
+ProtoOutputStream::editEncodedSize(size_t rawSize)
+{
+ size_t objectStart = mBuffer.ep()->pos();
+ size_t objectEnd = objectStart + rawSize;
+ size_t encodedSize = 0;
+ int childRawSize, childEncodedSize;
+ size_t childEncodedSizePos;
+
+ while (mBuffer.ep()->pos() < objectEnd) {
+ uint32_t tag = (uint32_t)mBuffer.readRawVarint();
+ encodedSize += get_varint_size(tag);
+ switch (read_wire_type(tag)) {
+ case WIRE_TYPE_VARINT:
+ do {
+ encodedSize++;
+ } while ((mBuffer.readRawByte() & 0x80) != 0);
+ break;
+ case WIRE_TYPE_FIXED64:
+ encodedSize += 8;
+ mBuffer.ep()->move(8);
+ break;
+ case WIRE_TYPE_LENGTH_DELIMITED:
+ childRawSize = (int)mBuffer.readRawFixed32();
+ childEncodedSizePos = mBuffer.ep()->pos();
+ childEncodedSize = (int)mBuffer.readRawFixed32();
+ if (childRawSize >= 0 && childRawSize == childEncodedSize) {
+ mBuffer.ep()->move(childRawSize);
+ } else if (childRawSize < 0 && childEncodedSize == -1){
+ childEncodedSize = editEncodedSize(-childRawSize);
+ mBuffer.editRawFixed32(childEncodedSizePos, childEncodedSize);
+ } else {
+ ALOGE("Bad raw or encoded values: raw=%d, encoded=%d at %zu",
+ childRawSize, childEncodedSize, childEncodedSizePos);
+ return 0;
+ }
+ encodedSize += get_varint_size(childEncodedSize) + childEncodedSize;
+ break;
+ case WIRE_TYPE_FIXED32:
+ encodedSize += 4;
+ mBuffer.ep()->move(4);
+ break;
+ default:
+ ALOGE("Unexpected wire type %d in editEncodedSize at [%zu, %zu]",
+ read_wire_type(tag), objectStart, objectEnd);
+ return 0;
+ }
+ }
+ return encodedSize;
+}
+
+/**
+ * Second compaction pass. Iterate through the data, and copy the data
+ * forward in the buffer, converting the pairs of uint32s into a single
+ * unsigned varint of the size.
+ */
+bool
+ProtoOutputStream::compactSize(size_t rawSize)
+{
+ size_t objectStart = mBuffer.ep()->pos();
+ size_t objectEnd = objectStart + rawSize;
+ int childRawSize, childEncodedSize;
+
+ while (mBuffer.ep()->pos() < objectEnd) {
+ uint32_t tag = (uint32_t)mBuffer.readRawVarint();
+ switch (read_wire_type(tag)) {
+ case WIRE_TYPE_VARINT:
+ while ((mBuffer.readRawByte() & 0x80) != 0) {}
+ break;
+ case WIRE_TYPE_FIXED64:
+ mBuffer.ep()->move(8);
+ break;
+ case WIRE_TYPE_LENGTH_DELIMITED:
+ mBuffer.copy(mCopyBegin, mBuffer.ep()->pos() - mCopyBegin);
+
+ childRawSize = (int)mBuffer.readRawFixed32();
+ childEncodedSize = (int)mBuffer.readRawFixed32();
+ mCopyBegin = mBuffer.ep()->pos();
+
+ // write encoded size to buffer.
+ mBuffer.writeRawVarint32(childEncodedSize);
+ if (childRawSize >= 0 && childRawSize == childEncodedSize) {
+ mBuffer.ep()->move(childEncodedSize);
+ } else if (childRawSize < 0){
+ if (!compactSize(-childRawSize)) return false;
+ } else {
+ ALOGE("Bad raw or encoded values: raw=%d, encoded=%d",
+ childRawSize, childEncodedSize);
+ return false;
+ }
+ break;
+ case WIRE_TYPE_FIXED32:
+ mBuffer.ep()->move(4);
+ break;
+ default:
+ ALOGE("Unexpected wire type %d in compactSize at [%zu, %zu]",
+ read_wire_type(tag), objectStart, objectEnd);
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool write_all(int fd, uint8_t const* buf, size_t size)
+{
+ while (size > 0) {
+ ssize_t amt = ::write(fd, buf, size);
+ if (amt < 0) {
+ return false;
+ }
+ size -= amt;
+ buf += amt;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::flush()
+{
+ if (mFd < 0) return false;
+ if (!compact()) return false;
+
+ EncodedBuffer::iterator it = mBuffer.begin();
+ while (it.readBuffer() != NULL) {
+ if (!write_all(mFd, it.readBuffer(), it.currentToRead())) return false;
+ it.rp()->move(it.currentToRead());
+ }
+ return true;
+}
+
+
+// =========================================================================
+// Private functions
+
+/**
+ * bit_cast
+ */
+template <class From, class To>
+inline To bit_cast(From const &from) {
+ To to;
+ memcpy(&to, &from, sizeof(to));
+ return to;
+}
+
+inline void
+ProtoOutputStream::writeDoubleImpl(uint32_t id, double val)
+{
+ if (val == 0.0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED64);
+ mBuffer.writeRawFixed64(bit_cast<double, uint64_t>(val));
+}
+
+inline void
+ProtoOutputStream::writeFloatImpl(uint32_t id, float val)
+{
+ if (val == 0.0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED32);
+ mBuffer.writeRawFixed32(bit_cast<float, uint32_t>(val));
+}
+
+inline void
+ProtoOutputStream::writeInt64Impl(uint32_t id, long long val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint64((uint64_t)val);
+}
+
+inline void
+ProtoOutputStream::writeInt32Impl(uint32_t id, int val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32((uint32_t)val);
+}
+
+inline void
+ProtoOutputStream::writeUint64Impl(uint32_t id, uint64_t val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint64(val);
+}
+
+inline void
+ProtoOutputStream::writeUint32Impl(uint32_t id, uint32_t val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32(val);
+}
+
+inline void
+ProtoOutputStream::writeFixed64Impl(uint32_t id, uint64_t val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED64);
+ mBuffer.writeRawFixed64(val);
+}
+
+inline void
+ProtoOutputStream::writeFixed32Impl(uint32_t id, uint32_t val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED32);
+ mBuffer.writeRawFixed32(val);
+}
+
+inline void
+ProtoOutputStream::writeSFixed64Impl(uint32_t id, long long val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED64);
+ mBuffer.writeRawFixed64((uint64_t)val);
+}
+
+inline void
+ProtoOutputStream::writeSFixed32Impl(uint32_t id, int val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED32);
+ mBuffer.writeRawFixed32((uint32_t)val);
+}
+
+inline void
+ProtoOutputStream::writeZigzagInt64Impl(uint32_t id, long long val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint64((val << 1) ^ (val >> 63));
+}
+
+inline void
+ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32((val << 1) ^ (val >> 31));
+}
+
+inline void
+ProtoOutputStream::writeEnumImpl(uint32_t id, int val)
+{
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32((uint32_t) val);
+}
+
+inline void
+ProtoOutputStream::writeBoolImpl(uint32_t id, bool val)
+{
+ if (!val) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32(val ? 1 : 0);
+}
+
+inline void
+ProtoOutputStream::writeUtf8StringImpl(uint32_t id, const char* val, size_t size)
+{
+ if (val == NULL || size == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
+ mBuffer.writeRawFixed32(size);
+ mBuffer.writeRawFixed32(size);
+ for (size_t i=0; i<size; i++) {
+ mBuffer.writeRawByte((uint8_t)val[i]);
+ }
+}
+
+} // util
+} // android
+
diff --git a/libs/protoutil/src/protobuf.cpp b/libs/protoutil/src/protobuf.cpp
index ec5325c..1c7eef9 100644
--- a/libs/protoutil/src/protobuf.cpp
+++ b/libs/protoutil/src/protobuf.cpp
@@ -22,17 +22,28 @@
uint8_t
read_wire_type(uint32_t varint)
{
- return (uint8_t) (varint & 0x07);
+ return (uint8_t) (varint & WIRE_TYPE_MASK);
}
uint32_t
read_field_id(uint32_t varint)
{
- return varint >> 3;
+ return varint >> FIELD_ID_SHIFT;
+}
+
+size_t
+get_varint_size(uint64_t varint)
+{
+ size_t size = 1;
+ while ((varint & ~0x7F)) {
+ size++;
+ varint >>= 7;
+ }
+ return size;
}
uint8_t*
-write_raw_varint(uint8_t* buf, uint32_t val)
+write_raw_varint(uint8_t* buf, uint64_t val)
{
uint8_t* p = buf;
while (true) {
@@ -49,7 +60,7 @@
uint8_t*
write_length_delimited_tag_header(uint8_t* buf, uint32_t fieldId, size_t size)
{
- buf = write_raw_varint(buf, (fieldId << 3) | 2);
+ buf = write_raw_varint(buf, (fieldId << FIELD_ID_SHIFT) | WIRE_TYPE_LENGTH_DELIMITED);
buf = write_raw_varint(buf, size);
return buf;
}
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 26ead3d..20405d3 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -202,6 +202,22 @@
* @see #SUPPRESSIBLE_USAGES
*/
public final static int SUPPRESSIBLE_NEVER = 3;
+ /**
+ * @hide
+ * Denotes a usage for alarms,
+ * will be muted when the Zen mode doesn't allow alarms
+ * @see #SUPPRESSIBLE_USAGES
+ */
+ public final static int SUPPRESSIBLE_ALARM = 4;
+ /**
+ * @hide
+ * Denotes a usage for all other sounds not caught in SUPPRESSIBLE_NOTIFICATION,
+ * SUPPRESSIBLE_CALL,SUPPRESSIBLE_NEVER or SUPPRESSIBLE_ALARM.
+ * This includes media, system, game, navigation, the assistant, and more.
+ * These will be muted when the Zen mode doesn't allow media/system/other.
+ * @see #SUPPRESSIBLE_USAGES
+ */
+ public final static int SUPPRESSIBLE_MEDIA_SYSTEM_OTHER = 5;
/**
* @hide
@@ -221,6 +237,13 @@
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY, SUPPRESSIBLE_NEVER);
SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION, SUPPRESSIBLE_NEVER);
+ SUPPRESSIBLE_USAGES.put(USAGE_ALARM, SUPPRESSIBLE_ALARM);
+ SUPPRESSIBLE_USAGES.put(USAGE_MEDIA, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER);
+ SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_SONIFICATION, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER);
+ SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER);
+ SUPPRESSIBLE_USAGES.put(USAGE_GAME, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER);
+ SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER);
+ SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER);
}
/**
diff --git a/media/java/android/media/tv/ITvInputHardware.aidl b/media/java/android/media/tv/ITvInputHardware.aidl
index 96223ba..94c1013 100644
--- a/media/java/android/media/tv/ITvInputHardware.aidl
+++ b/media/java/android/media/tv/ITvInputHardware.aidl
@@ -40,12 +40,6 @@
void setStreamVolume(float volume);
/**
- * Dispatch key event to HDMI service. The events would be automatically converted to
- * HDMI CEC commands. If the hardware is not representing an HDMI port, this method will fail.
- */
- boolean dispatchKeyEventToHdmi(in KeyEvent event);
-
- /**
* Override default audio sink from audio policy. When override is on, it is
* TvInputService's responsibility to adjust to audio configuration change
* (for example, when the audio sink becomes unavailable or more desirable
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index d7a9ede..fd1f2cf 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -2590,12 +2590,9 @@
}
}
+ /** @removed */
public boolean dispatchKeyEventToHdmi(KeyEvent event) {
- try {
- return mInterface.dispatchKeyEventToHdmi(event);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
+ return false;
}
public void overrideAudioSink(int audioType, String audioAddress, int samplingRate,
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index cf9515e..a7a7ea9 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Kon nie instellings vir <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> oopmaak nie"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Die invoermetode kan dalk alle teks wat jy invoer, versamel, insluitend persoonlike data soos wagwoorde en kredietkaartnommers. Dit kom van die program <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Wil jy dié invoermetode gebruik?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Let wel: Ná \'n herselflaai kan hierdie program nie begin voordat jy jou foon ontsluit het nie"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS-registrasiestaat"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Geregistreer"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nie geregistreer nie"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Onbeskikbaar"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index a84ee81..bff8fe2 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"የ<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ቅንብሮች መክፈት አልተሳካም"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"ይህ ግቤት ስልት የሚትተይበውን ፅሁፍ ሁሉ፣ እንደይለፍ ቃል እና የብድር ካርድ ጨምሮ የግል ውሂብ ምናልባት መሰብሰብ ይችላል። ከትግበራው ይመጣል። <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ይህን ግቤት ስልትይጠቀም?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ማስታወሻ፦ እንደገና ከማስነሳት በኋላ ይህ መተግበሪያ ስልክዎን እስከሚከፍቱት ድረስ ሊጀምር አይችልም"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"የIMS ምዝገባ ቀን"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"የተመዘገበ"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"አልተመዘገበም"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"አይገኝም"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index b9a16b96..457a6dd 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"تعذّر فتح الإعدادات لـ <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"يمكن أن يكون أسلوب الإدخال هذا قادرًا على جمع كل النصوص التي تكتبها، بما في ذلك البيانات الشخصية مثل كلمات المرور وأرقام بطاقات الائتمان. يتم الحصول على هذا الأسلوب من التطبيق <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. هل تريد استخدام أسلوب الإدخال هذا؟"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ملاحظة: بعد إعادة التشغيل، يتعذر بدء هذا التطبيق إلى أن تلغي قفل هاتفك."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"حالة تسجيل IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"مُسجَّل"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"غير مُسجَّل"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"غير متاح"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 0a86706..8b453ab 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> üçün ayarları açmaq alınmadı"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Bu daxiletmə metodu yazdığınız bütün mətni toplaya bilər. Buna kredit kart kimi şəxsi məlumat aid ola bilər. Kökü <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> tətbiqindədir. Bu daxiletmə metodu istifadə olunsun?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Qeyd: Yenidən yüklənmədən sonra, bu cihazın kilidini açmamış tətbiq başlaya bilməz"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS qeydiyyat statusu"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Qeydiyyatlı"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Qeydiyyatsız"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Əlçatmazdır"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 1e84d3d..ba0de57 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Otvaranje podešavanja za aplikaciju <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> nije uspelo"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ovaj metod unosa možda može da prikuplja sav tekst koji unosite, uključujući lične podatke, kao što su lozinke i brojevi kreditnih kartica. Potiče od aplikacije <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Želite li da koristite ovaj metod unosa?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Napomena: Posle restartovanja ova aplikacija ne može da se pokrene dok ne otključate telefon"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Status IMS registracije"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrovan je"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nije registrovan"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Nedostupno"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index e47bc43..49a18b6 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Не атрымалася адкрыць параметры <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Гэты метад уводу можа збіраць увесь тэкст, які ўводзіцца, у тым лiку такiя персанальныя дадзеныя, як паролі і нумары крэдытных карт. Ён выкарыстоўваецца прыкладаннем <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Выкарыстоўваць гэты метад уводу?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Заўвага. Пасля перазагрузкі гэта праграма не зможа запусціцца, пакуль вы не разблакіруеце тэлефон"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Стан рэгістрацыі IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Зарэгістраваны"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не зарэгістраваны"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Адсутнічае"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 77beb4c..8fbef19 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Отварянето на настройките за <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> не бе успешно"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Този метод за въвеждане може да събира целия въведен от вас текст, включително лични данни като пароли и номера на кредитни карти. Той произлиза от приложението <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Искате ли да го използвате?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Забележка: След рестартиране това приложение не може да се стартира, докато не отключите телефона си"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Състояние на регистрацията за незабавни съобщения"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Регистрирано"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не е регистрирано"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Няма данни"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 424e7b9..ec48835 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> জন্য সেটিংস খুলতে ব্যর্থ হয়েছে"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"এই ইনপুট পদ্ধতিটি হয়তো পাসওয়ার্ড এবং ক্রেডিট কার্ড নম্বর সহ আপনার টাইপ করা সমস্ত টেক্সট সংগ্রহ করতে সক্ষম হতে পারে। এটি <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> অ্যাপ থেকে এসেছে। এই ইনপুট পদ্ধতিটি ব্যবহার করবেন?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"দ্রষ্টব্য: পুনরায় চালু করার পরে, আপনি আপনার ফোন আনলক না করা পর্যন্ত এই অ্যাপটিকে চালু করতে পারবেন না"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS রেজিস্ট্রেশনের স্থিতি"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"রেজিস্টার করা"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"রেজিস্টার করা নয়"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"অনুপলব্ধ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 97cbfbf..a331286 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -110,7 +110,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
- <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB dijeljenje veze"</string>
+ <string name="tether_settings_title_usb" msgid="6688416425801386511">"Povezivanje mobitela USB-om"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prijenosna pristupna tačka"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Dijeljenje Bluetooth veze"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Dijeljenje veze"</string>
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nije uspjelo otvaranje postavki za <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ovaj način unosa može prikupiti sav tekst koji otkucate, uključujući lične podatke kao što su lozinke i brojevi kreditnih kartica. Način omogućava aplikacija <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Da li želite koristiti ovaj način unosa?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Napomena: Nakon ponovnog pokretanja, ova aplikacija se neće moći pokrenuti dok ne otključate telefon"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Stanje IMS registracije"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrirano"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nije registrirano"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Nije dostupno"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 479cf38..145f61c 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"No s\'ha pogut obrir la configuració de: <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Pot ser que aquest mètode d\'introducció pugui recopilar tot el que escriviu, incloses dades personals, com ara contrasenyes i números de targetes de crèdit. Ve de l\'aplicació <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Voleu utilitzar aquest mètode d\'introducció?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Nota: després de reiniciar, l\'aplicació no s\'iniciarà fins que no desbloquegis el telèfon"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Estat del registre d\'IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrat"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Sense registrar"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"No disponible"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 97a76f7..994afae 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nastavení aplikace <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> se nepodařilo otevřít"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Prostřednictvím této vstupní metody zadávání dat lze shromažďovat zadaný text včetně osobních údajů, jako jsou hesla a čísla platebních karet. Metoda je poskytována aplikací <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Chcete tuto metodu zadávání dat použít?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Poznámka: Po restartování se tato aplikace nespustí, dokud telefon neodemknete."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Stav registrace IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrováno"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Neregistrováno"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Není k dispozici"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 6a006cc..e916853 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -329,7 +329,7 @@
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertér…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Allerede filkrypteret"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Konverterer til filbaseret kryptering"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Konvertér datapartitionen til filbaseret kryptering.\nAdvarsel! Alle dine data vil blive slettet.\n Dette er en alfafunktion, og den fungerer muligvis ikke korrekt.\n Tryk på \"Ryd og konvertér…\" for at fortsætte."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Konvertér datapartitionen til filbaseret kryptering.\nAdvarsel! Alle dine data vil blive fuldstændigt slettet.\n Dette er en alfafunktion, og den fungerer muligvis ikke korrekt.\n Tryk på \"Ryd og konvertér…\" for at fortsætte."</string>
<string name="button_convert_fbe" msgid="5152671181309826405">"Ryd og konvertér…"</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Farvetilstand for billeder"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Brug sRGB"</string>
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Indstillingerne for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> kunne ikke åbnes"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Denne inputmetode kan muligvis indsamle al indtastet tekst, f.eks. personlige data såsom adgangskoder og kreditkortnumre. Den kommer fra appen <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Vil du anvende denne inputmetode?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Bemærk! Efter en genstart kan denne app ikke starte, før du låser din telefon op"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Status for IMS-registrering"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registreret"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ikke registreret"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Utilgængelig"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 2203bc6..1ec4fee 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Einstellungen für <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> konnten nicht geöffnet werden."</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Diese Eingabemethode kann den gesamten von dir eingegebenen Text erfassen, einschließlich personenbezogener Daten wie Passwörter und Kreditkartennummern. Sie ist Teil der App \"<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>\". Möchtest du diese Eingabemethode verwenden?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Hinweis: Nach einem Neustart wird diese App erst gestartet, wenn du dein Smartphone entsperrst"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS-Registrierungsstatus"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registriert"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nicht registriert"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Nicht verfügbar"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 514cfd8..2548a5d 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Δεν ήταν δυνατό το άνοιγμα των ρυθμίσεων για την εφαρμογή <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Αυτή η μέθοδος εισαγωγής ενδέχεται να έχει τη δυνατότητα να συλλέξει όλα τα κείμενα που πληκτρολογείτε, συμπεριλαμβανομένων προσωπικών δεδομένων, όπως είναι οι κωδικοί πρόσβασης και οι αριθμοί πιστωτικής κάρτας. Προέρχεται από την εφαρμογή <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Να γίνει χρήση αυτής της μεθόδου εισαγωγής;"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Σημείωση: Μετά από μια επανεκκίνηση, δεν είναι δυνατή η έναρξη αυτής της συσκευής προτού ξεκλειδώσετε το τηλέφωνό σας"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Κατάσταση εγγραφής υπηρεσίας IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Εγγεγραμμένη"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Μη εγγεγραμμένη"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Μη διαθέσιμο"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index aa5af8e..9e24004 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Failed to open settings for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"This input method may be able to collect all the text that you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Note: After a reboot, this app can\'t start until you unlock your phone"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS registration state"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index aa5af8e..9e24004 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Failed to open settings for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"This input method may be able to collect all the text that you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Note: After a reboot, this app can\'t start until you unlock your phone"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS registration state"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index aa5af8e..9e24004 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Failed to open settings for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"This input method may be able to collect all the text that you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Note: After a reboot, this app can\'t start until you unlock your phone"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS registration state"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index aa5af8e..9e24004 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Failed to open settings for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"This input method may be able to collect all the text that you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Note: After a reboot, this app can\'t start until you unlock your phone"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS registration state"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 66d8fe0..77c0e4f 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Failed to open settings for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"This input method may be able to collect all the text you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Note: After a reboot, this app can\'t start until you unlock your phone"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS registration state"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 743700e..ff26eef 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Se produjo un error al abrir la configuración de <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>."</string>
<string name="ime_security_warning" msgid="4135828934735934248">"El método de entrada puede recopilar todo el texto que escribas, incluidos los datos personales como contraseñas y números de tarjetas de crédito. Proviene de la aplicación <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. ¿Deseas utilizar este método de entrada?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Nota: Luego de reiniciar el dispositivo, esta app no podrá iniciarse hasta que desbloquees tu teléfono"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Estado de registro de IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrado"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Sin registrar"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"No disponible"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index d964728..20bab13 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Error al abrir los ajustes de <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Este método de entrada puede registrar todo lo que escribas, incluidos datos personales, como las contraseñas y los números de las tarjetas de crédito. Procede de la aplicación <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. ¿Quieres usar este método de entrada?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Nota: Después de reiniciar, tienes que desbloquear el teléfono para que esta aplicación se pueda iniciar"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Estado del registro de IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrado"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"No registrado"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"No disponible"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index cfcc4c6..a0341fb 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Rakenduse <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> seadete avamine ebaõnnestus"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"See sisestusmeetod võib koguda kogu teie sisestatava teksti, sh isikuandmed (nt paroolid ja krediitkaardinumbrid). See pärineb rakendusest <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Kas soovite seda sisestusmeetodit kasutada?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Märkus. Pärast taaskäivitamist ei saa see rakendus käivituda enne, kui olete telefoni avanud"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS-i registreerimise olek"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registreeritud"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ei ole registreeritud"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Pole saadaval"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index d7595e8..e8d9a5e 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Ezin izan dira <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> aplikazioaren ezarpenak ireki."</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Idazketa-metodoak idazten duzun testu guztia bil dezake, pasahitzak eta kreditu-txarteleko zenbakiak bezalako datu pertsonalak barne. <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> aplikazioak egin du eskaera. Idazketa-metodo hori erabili nahi duzu?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Oharra: berrabiarazi ondoren, ezin izango da abiarazi aplikazio hau telefonoa desblokeatzen duzun arte"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS erregistratzearen egoera"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Erregistratuta"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Erregistratu gabe"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Ez dago erabilgarri"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index f582486..326192d 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"تنظیمات <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> بازنشد"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"این روش ورودی ممکن است بتواند تمام متنی را که تایپ میکنید جمعآوری کند، از جمله اطلاعات شخصی مانند گذرواژهها و شمارههای کارت اعتباری. این روش توسط برنامه <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ارائه میشود. از این روش ورودی استفاده میکنید؟"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"توجه: بعد از راهاندازی تا زمانیکه قفل تلفنتان را باز نکنید، این برنامه نمیتواند شروع شود"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"وضعیت ثبت IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"ثبتشده"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ثبت نشده است"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"در دسترس نیست"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 83073d1..6321086 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Sovelluksen <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> asetuksia ei voi avata"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Tämä syöttötapa saattaa kerätä kaiken kirjoittamasi tekstin, mukaan luettuna henkilökohtaiset tiedot kuten salasanat ja luottokortin numerot. Se on lähtöisin sovelluksesta <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Käytetäänkö tätä syöttötapaa?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Huom. Jotta voit käynnistää tämän sovelluksen uudelleenkäynnistyksen jälkeen, sinun täytyy avata puhelimen lukitus."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS-rekisteröinnin tila"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Rekisteröity"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ei rekisteröity"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Ei käytettävissä"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 54d6864..00c02ce 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Échec de l\'ouverture des paramètres de l\'application <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>."</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ce mode de saisie est susceptible d\'enregistrer le texte que vous saisissez, y compris vos données personnelles, telles que les mots de passe et les numéros de carte de paiement. Il provient de l\'application <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Voulez-vous vraiment l\'activer?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Remarque : Après un redémarrage, vous ne pouvez pas lancer cette application tant que vous n\'avez pas déverrouillé votre téléphone."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"État d\'enregistrement IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Enregistré"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Non enregistré"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Non accessible"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index e35d330..a5625e4 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Échec de l\'ouverture des paramètres de l\'application <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>."</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ce mode de saisie est susceptible d\'enregistrer le texte que vous saisissez, y compris vos données personnelles, telles que les mots de passe et les numéros de carte de paiement. Il provient de l\'application <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Voulez-vous vraiment l\'activer ?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Remarque : Après un redémarrage, vous ne pouvez pas lancer cette application tant que vous n\'avez pas déverrouillé votre téléphone."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"État de l\'enregistrement IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Enregistré"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Non enregistré"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Non disponible"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 8291cb1..e1ea694 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Non se puido abrir a configuración de <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"É posible que este método de entrada poida recompilar todo o texto que escribas, incluídos os datos persoais como os contrasinais e os números de tarxetas de crédito. Provén da aplicación <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Queres usar este método de entrada?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Nota: Tras un reinicio, non se pode iniciar esta aplicación ata que desbloquees o teléfono"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Estado de rexistro de IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Rexistrado"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Non rexistrado"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Non dispoñible"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index ca14118..0e8dd47 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> માટેની સેટિંગ્સ ખોલવામાં નિષ્ફળ"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"આ ઇનપુટ પદ્ધતિ પાસવર્ડ્સ અને ક્રેડિટ કાર્ડ નંબર જેવી વ્યક્તિગત માહિતી સહિત તમે લખો છો તે તમામ ટેક્સ્ટ એકત્રિત કરવા માટે સક્ષમ હોઈ શકે છે. તે ઍપ્લિકેશન <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> માંથી આવે છે. આ ઇનપુટ પદ્ધતિ વાપરીએ?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"નોંધ: રીબૂટ કર્યાં પછી, જ્યાં સુધી તમે તમારો ફોન અનલૉક કરશો નહીં ત્યાં સુધી આ ઍપ્લિકેશન શરૂ થઈ શકશે નહીં"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS રજિસ્ટ્રેશનની સ્થિતિ"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"રજિસ્ટર કરેલ"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"રજિસ્ટર કરેલ નથી"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"અનુપલબ્ધ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index bde80f2..28bc68a 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> के लिए सेटिंग खोलने में विफल रहा"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"यह इनपुट विधि, पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा सहित आपके द्वारा लिखे जाने वाले सभी लेख को एकत्र कर सकती है. यह <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ऐप्स से आती है. इस इनपुट विधि का उपयोग करें?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"नोट: पुनः बूट करने के बाद, यह ऐप्लिकेशन तब तक शुरू नहीं हो सकता है जब तक कि आप अपना फ़ोन अनलॉक ना कर लें"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS रजिस्ट्रेशन की स्थिति"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"रजिस्टर है"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"रजिस्टर नहीं है"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"अनुपलब्ध"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index ec2b9cf..b5c5439 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Otvaranje postavki za aplikaciju <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> nije uspjelo"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ovaj način unosa možda može prikupljati sav tekst koji unosite, uključujući osobne podatke poput zaporki i brojeva kreditnih kartica. To omogućuje aplikacija <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Upotrijebiti taj način unosa?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Napomena: ova se aplikacija ne može pokrenuti nakon ponovnog pokretanja dok ne otključate telefon"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Stanje registracije IMS-a"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrirano"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nije registrirano"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Nije dostupno"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 3fe6a78..47d6c98 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nem sikerült megnyitni a(z) <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> beállításait."</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ez a beviteli módszer alkalmas lehet a beírt szövegek – köztük az olyan személyes adatok, mint a jelszavak és a hitelkártyaszámok - összegyűjtésére. A <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> alkalmazás kapcsolta be. Használja ezt a módszert?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Megjegyzés: Újraindítás után ez az alkalmazás csak a telefon feloldását követően indul el"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS-regisztráció állapota"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Regisztrált"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nem regisztrált"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Nem érhető el"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 119e24c..6f11cd8 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Չստացվեց ցույց տալ <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>-ի տվյալները"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Այս ներմուծման եղանակը հնարավորություն է տալիս հավաքել ձեր մուտքագրած ողջ տեքստը՝ ընդգրկելով անձնական տեղեկություններ, ինչպես գաղտնաբառն ու բանկային քարտի համարները: Սկզբնաղբյուրը <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> հավելվածն է: Կիրառե՞լ այս եղանակը:"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Ուշադրություն. Վերաբեռնումից հետո այս հավելվածը չի գործարկվի մինչև չապակողպեք հեռախոսը"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS ծառայության գրանցման կարգավիճակը"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Գրանցված է"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Գրանցված չէ"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Անհասանելի"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index c2db508..b4a58bb 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Gagal membuka setelan untuk <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Metode masukan ini mungkin dapat mengumpulkan semua teks yang Anda ketik, termasuk data pribadi seperti sandi dan nomor kartu kredit. Metode ini berasal dari aplikasi <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Gunakan metode masukan ini?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Catatan: Setelah boot ulang, aplikasi ini tidak dapat dimulai hingga kunci ponsel dibuka"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Status pendaftaran IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Terdaftar"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Tidak terdaftar"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Tidak Tersedia"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 883e909..29b1b5d 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Ekki tókst að opna stillingar <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Þessi innsláttaraðferð getur hugsanlega skráð allan texta sem þú slærð inn, þ. á m. persónuupplýsingar á borð við aðgangsorð og kreditkortanúmer. Hún kemur frá forritinu <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Viltu nota þessa innsláttaraðferð?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Athugaðu: Eftir endurræsingu er ekki hægt að ræsa þetta forrit fyrr en þú tekur símann úr lás"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Staða IMS-skráningar"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Skráð"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ekki skráð"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Ekki tiltækt"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index e53e4da..46004c3 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Impossibile aprire le impostazioni di <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Questo metodo di immissione potrebbe riuscire a raccogliere tutto il testo digitato, compresi i dati personali come password e numeri di carte di credito. Deriva dall\'applicazione <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Utilizzare questo metodo di immissione?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Nota: dopo il riavvio, devi sbloccare il telefono per poter avviare l\'app."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Stato di registrazione IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrato"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Non registrato"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Non disponibile"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 363b064..24f4684 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"פתיחת הגדרות עבור <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> נכשלה"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"ייתכן ששיטת קלט זו תוכל לאסוף את כל הטקסט שאתה מקליד, כולל נתונים אישיים כגון סיסמאות ומספרי כרטיס אשראי. היא מגיעה מהאפליקציה <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. האם להשתמש בשיטת קלט זו?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"שים לב: לאחר הפעלה מחדש של המכשיר, ניתן להפעיל את האפליקציה רק לאחר שתבטל את נעילת הטלפון"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"סטטוס הרשמה ל-IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"רשום"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"לא רשום"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"לא זמין"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index dfd199a..bb3f5a9 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -390,4 +390,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>の設定を開くことができませんでした"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"この入力方法を選択すると、すべての入力内容の収集をアプリ(<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>)に許可することになります。これにはパスワードやクレジットカード番号などの個人情報も含まれます。この入力方法を使用しますか?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"注: 再起動後、スマートフォンのロックを解除するまでこのアプリを起動することはできません"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS 登録ステータス"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"登録済み"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"未登録"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"不明"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 7fac639..2280261 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>-ისთვის პარამეტრების გახსნა ვერ მოხერხდა"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"შეყვანის ამ მეთოდმა შესაძლოა მოახერხოს თქვენი აკრეფილი ყველა ტექსტის, მათ შორის პერსონალური მონაცემების, პაროლებისა და საკრედიტო ბარათის ნომრების შენახვა. ეს მეთოდი ეკუთვნის <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>-ს. გამოვიყენო შეყვანის ეს მეთოდი?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"შენიშვნა: გადატვირთვის შემდეგ, ეს აპი ვერ გაეშვება, სანამ ტელეფონს არ განბლოკავთ"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS რეგისტრაციის სტატუსი"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"რეგისტრირებული"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"არარეგისტრირებული"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"მიუწვდომელია"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 3b806a5..03bd3cd 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> қолданбасы үшін параметрлерді ашу орындалмады"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Бұл енгізу әдісі сіз терген барлық мәтінді, кілтсөз және кредит карта нөмірлері сияқты жеке ақпаратты қоса, жинауы мүмкін. Бұл <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> қолданбасы арқылы жасалады. Осы әдіс қолданылсын ба?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Ескертпе: қайта жүктегеннен кейін, телефонның құлпын ашпайынша, бұл қолданба іске қосылмайды"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS тіркеу күйі"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Тіркелген"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Тіркелмеген"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Қол жетімсіз"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 2160bae..6414141 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"បានបរាជ័យក្នុងការបើកការកំណត់សម្រាប់ <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"វិធីសាស្ត្របញ្ចូលនេះអាចប្រមូលអត្ថបទដែលអ្នកវាយទាំងអស់ រួមមានទិន្នន័យផ្ទាល់ខ្លួន ដូចជ ពាក្យសម្ងាត់ និងលេខកាតឥណទាន។ វាបានមកពីកម្មវិធី <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ។ ប្រើវិធីសាស្ត្របញ្ចូលនេះ?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ចំណាំ៖ បន្ទាប់ពីបិទបើកឡើងវិញហើយ កម្មវិធីនេះមិនអាចចាប់ផ្តើមបានទេ រហូតទាល់តែអ្នកដោះសោទូរស័ព្ទរបស់អ្នក"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"ស្ថានភាពនៃការចុះឈ្មោះ IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"បានចុះឈ្មោះ"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"មិនបានចុះឈ្មោះ"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"មិនមាន"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index a47a92c..d108dd6 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -121,7 +121,7 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ಬಳಕೆದಾರ: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"ಕೆಲವು ಡೀಫಾಲ್ಟ್ಗಳನ್ನು ಹೊಂದಿಸಲಾಗಿದೆ"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ಡೀಫಾಲ್ಟ್ಗಳನ್ನು ಹೊಂದಿಸಲಾಗಿಲ್ಲ"</string>
- <string name="tts_settings" msgid="8186971894801348327">"ಪಠ್ಯದಿಂದ ಧ್ವನಿಗೆ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ಪಠ್ಯದಿಂದ ಧ್ವನಿಯ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="tts_settings_title" msgid="1237820681016639683">"ಧ್ವನಿಗೆ-ಪಠ್ಯದ ಔಟ್ಪುಟ್"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"ಧ್ವನಿಯ ಪ್ರಮಾಣ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ಪಠ್ಯವನ್ನು ಹೇಳಿದ ವೇಗ"</string>
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಲು ವಿಫಲವಾಗಿದೆ"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"ವೈಯಕ್ತಿಕ ಡೇಟಾಗಳಾದ ಪಾಸ್ವರ್ಡ್ಗಳು ಮತ್ತು ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನೀವು ಟೈಪ್ ಮಾಡುವ ಎಲ್ಲ ಪಠ್ಯವನ್ನು ಸಂಗ್ರಹಿಸಲು ಈ ಇನ್ಪುಟ್ ವಿಧಾನಕ್ಕೆ ಸಾಧ್ಯವಾಗಬಹುದು. ಇದು <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಬರುತ್ತದೆ. ಈ ಇನ್ಪುಟ್ ವಿಧಾನವನ್ನು ಬಳಸುವುದೇ?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ಗಮನಿಸಿ: ರೀಬೂಟ್ ನಂತರ, ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಅನ್ಲಾಕ್ ಮಾಡುವ ತನಕ ಈ ಆಪ್ ಪ್ರಾರಂಭಗೊಳ್ಳುವುದಿಲ್ಲ"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS ನೋಂದಣಿ ಸ್ಥಿತಿ"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"ನೋಂದಾಯಿಸಲಾಗಿದೆ"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ನೋಂದಾಯಿಸಲಾಗಿಲ್ಲ"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"ಲಭ್ಯವಿಲ್ಲ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 852c78e..ec03fb1 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> 설정을 열지 못했음"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> 앱에서 지원하는 이 입력 방법을 사용하면 비밀번호 및 신용카드 번호와 같은 개인 정보를 비롯하여 입력한 모든 텍스트가 수집될 수 있습니다. 사용하시겠습니까?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"참고: 재부팅한 후 이 앱은 휴대전화를 잠금 해제해야 시작됩니다."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS 등록 상태"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"등록됨"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"등록되지 않음"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"사용할 수 없음"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 380d0ff..883811d 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> тууралоолору ачылган жок"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Бул киргизүү ыкмасы сиз терген бардык тексттер, сырсөздөр жана кредиттик карталар сыяктуу жеке маалыматтарды кошо чогултушу мүмкүн. Бул <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> колдонмосу менен байланыштуу. Ушул киргизүү ыкма колдонулсунбу?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Эскертүү: Өчүрүп-күйгүзгөндөн кийин, бул колдонмо телефондун кулпусу ачылмайынча иштебейт"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS каттоо абалы"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Катталган"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Катталган эмес"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Жеткиликсиз"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index eb10dbb..464b490 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"ລົ້ມເຫລວໃນການເປີດການຕັ້ງຄ່າຂອງ <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"ວິທີການປ້ອນຂໍ້ມູນນີ້ ອາດສາມາດເກັບກຳທຸກຂໍ້ຄວາມທີ່ທ່ານພິມ, ຮວມເຖິງຂໍ້ມູນສ່ວນໂຕເຊັ່ນລະຫັດຜ່ານ ແລະໝາຍເລກບັດເຄຣດິດນຳ. ມັນມາຈາກແອັບຯ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. ທ່ານຕ້ອງການໃຊ້ວິທີການປ້ອນຂໍ້ມູນນີ້ບໍ່?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ໝາຍເຫດ: ຫຼັງຈາກເປີດຂຶ້ນມາໃໝ່ແລ້ວ, ແອັບນີ້ຈະບໍ່ສາມາດເລີ່ມໄດ້ຈົນກວ່າທ່ານຈະປົດລັອກໂທລະສັບຂອງທ່ານ"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"ສະຖານະການລົງທະບຽນ IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"ລົງທະບຽນແລ້ວ"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ບໍ່ໄດ້ລົງທະບຽນ"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"ບໍ່ມີຂໍ້ມູນ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index adf6f8a..fd3bc18 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nepavyko atidaryti „<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>“ nustatymų"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Naudojant šį įvesties metodą galima rinkti visą įvedamą tekstą, įskaitant asmeninius duomenis, pvz., slaptažodžius ir kredito kortelių numerius. Jis pateikiamas naudojant programą „<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>“. Naudoti šį įvesties metodą?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Pastaba: paleidus iš naujo nebus galima paleisti programos, kol neatrakinsite telefono"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS registracijos būsena"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Užregistruota"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Neužregistruota"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Užimta"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 280900a..a6d308a 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Neizdevās atvērt lietotnes <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> iestatījumus."</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Izmantojot šo ievades metodi, var tikt vākta informācija par visu ierakstīto tekstu, tostarp personiskiem datiem, piemēram, parolēm un kredītkaršu numuriem. Šī metode ir saistīta ar lietotni <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Vai lietot šo ievades metodi?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Piezīme. Šo lietotni pēc atkārtotas palaišanas nevarēs startēt, kamēr netiks atbloķēts tālrunis."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS reģistrācijas statuss"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Reģistrēts"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nav reģistrēts"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Nepieejams"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 51697bd..8882cb7 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Подесувањата за <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> не се отворија"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Овој метод на внес може да го собере сиот текст кој го пишувате, вклучувајќи и лични податоци како што се, лозинки и броеви на кредитни картички. Тоа го прави апликацијата <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Користи го овој метод на внес?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Забелешка: по рестартирање, апликацијава не може да се вклучи додека не го отклучите телефонот"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Состојба на IMS-регистрација"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Регистриран"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не е регистриран"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Недостапен"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index d96607e..8f711b3 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> എന്നതിനായുള്ള ക്രമീകരണങ്ങൾ തുറക്കുന്നതിൽ പരാജയപ്പെട്ടു"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"പാസ്വേഡുകൾ, ക്രെഡിറ്റ് കാർഡ് നമ്പറുകൾ എന്നിവ പോലുള്ള വ്യക്തിഗതമായ ഡാറ്റയുൾപ്പെടെ നിങ്ങൾ ടൈപ്പുചെയ്യുന്ന എല്ലാ വാചകവും ഈ ടൈപ്പുചെയ്യൽ രീതിയ്ക്ക് ശേഖരിക്കാനായേക്കും. ഇത് <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> അപ്ലിക്കേഷനിൽ നിന്നും വരുന്നു. ഈ ടൈപ്പുചെയ്യൽ രീതി ഉപയോഗിക്കണോ?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ശ്രദ്ധിക്കുക: റീബൂട്ടിന് ശേഷം, ഫോൺ അൺലോക്കുചെയ്യുന്നത് വരെ ഈ ആപ്പ് ആരംഭിക്കാൻ കഴിയില്ല"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS രജിസ്ട്രേഷൻ നില"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"രജിസ്റ്റർ ചെയ്തു"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"രജിസ്റ്റർ ചെയ്തിട്ടില്ല"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"ലഭ്യമല്ല"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index e13886d..2e1f5e6 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>-н тохиргоог нээж чадсангүй"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Энэ оруулах арга нь таны нууц үгс, зээлийн картын дугаар гэх мэт бичсэн хувийн мэдээллийг цуглуулах боломжтой байж болно. Үүнийг <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> апп нийлүүлдэг. Энэ оруулах аргыг ашиглах уу?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Санамж: Дахин асаасны дараа энэ апп нь таныг утасны түгжээгээ тайлах хүртэл эхлэх боломжгүй"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS бүртгэлийн байдал"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Бүртгэсэн"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Бүртгээгүй"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Байхгүй"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index ae61916..63e2e87 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> साठी सेटिंग्ज उघडण्यात अयशस्वी"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"ही इनपुट पद्धत संकेतशब्द आणि क्रेडिट कार्ड नंबर यासह, आपण टाइप करता तो सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. ही <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> अॅपवरून येते. ही इनपुट पद्धत वापरायची?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"टीप: रीबूट केल्यानंतर, तुम्ही आपला फोन अनलॉक करे पर्यंत हे अॅप सुरू होऊ शकत नाही"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS नोंदणी स्थिती"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"नोंदवलेले"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"नोंदवलेले नाही"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"अनुपलब्ध"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index a44e5b1..9d81cea 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Gagal membuka tetapan untuk <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Kaedah input ini mungkin boleh mengumpulkan semua teks yang anda taipkan, termasuk data peribadi seperti kata laluan dan nombor kad kredit. Ia datang daripada aplikasi <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Gunakan kaedah input ini?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Perhatian: Selepas but semula, apl ini tidak dapat dimulakan sehingga anda membuka kunci telefon"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Keadaan pendaftaran IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Berdaftar"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Tidak didaftarkan"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Tidak tersedia"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index af95eac..aa241a9 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>အတွက် ဆက်တင်းများဖွင့်ရန် မအောင်မြင်ပါ။"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"ဤထည့်သွင်းမှုနည်းလမ်းမှာ သင့်ကိုယ်ရေးအချက်အလက်များဖြစ်သော စကားဝှက်များနှင့် ကရက်ဒစ်ကဒ်နံပါတ်စသည်တို့ကို ရယူသွားမည်ဖြစ်သည်။ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>အပလီကေးရှင်းမှလာပါသည်။ ဤထည့်သွင်းမှုနည်းလမ်းကို အသုံးပြုမည်လား?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"မှတ်ချက် − ပြန်လည်စတင်ပြီးနောက် သင့်ဖုန်းကိုလော့ခ်မဖွင့်မချင်း ဤအက်ပ်ကို အသုံးပြု၍မရပါ"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS မှတ်ပုံတင်ခြင်း အခြေအနေ"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"မှတ်ပုံတင်ထားသည်"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"မှတ်ပုံတင်မထားပါ"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"မရရှိနိုင်ပါ။"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 13d27ac..daf0051 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Kunne ikke åpne innstillingene for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Denne inndatametoden har tilgang til all tekst du skriver, blant annet personlige opplysninger som for eksempel passord og kredittkortnumre. Den kommer fra appen <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Vil du bruke denne inndatametoden?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Merk: Etter en omstart kan ikke denne appen starte før du låser opp telefonen din"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Tilstand for IMS-registrering"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrert"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ikke registrert"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Ikke tilgjengelig"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 58c5ffc..105c442 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>का लागि सेटिङहरू खोल्न विफल भयो।"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"यस इनपुट विधिले तपाईँले टाइप गर्नुहुने सम्पूर्ण पाठ बटु्ल्न सक्छ, व्यक्तिगत डेटा जस्तै पासवर्ड र क्रेडिट कार्ड नम्बर लगायतका। यो <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> अनुप्रयोगबाट आउँदछ। यो इनपुट विधि प्रयोग गर्ने हो?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"टिपोट: पुनःबुट पछि तपाईँले आफ्नो फोनलाई अनलक नगरेसम्म यो अनुप्रयोग सुरु हुन सक्दैन"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS दर्ताको स्थिति"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"दर्ता गरिएको"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"दर्ता नगरिएको"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"अनुपलब्ध"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 5cce79e..d8ae320 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Instellingen openen voor <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> mislukt"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Deze invoermethode verzamelt mogelijk alle tekst die je typt, inclusief persoonlijke gegevens zoals wachtwoorden en creditcardnummers. De methode is afkomstig uit de app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Deze invoermethode inschakelen?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Opmerking: Wanneer je telefoon opnieuw is opgestart, kan deze app pas worden gestart nadat je je telefoon hebt ontgrendeld"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS-registratiestatus"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Geregistreerd"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Niet geregistreerd"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Niet beschikbaar"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index becb559..b54d296 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ਲਈ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਵਿੱਚ ਅਸਫਲ"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"ਇਹ ਇਨਪੁੱਟ ਵਿਧੀ ਤੁਹਾਡੇ ਵੱਲੋਂ ਟਾਈਪ ਕੀਤਾ ਜਾਣ ਵਾਲੀ ਸਾਰੀ ਲਿਖਤ ਇਕੱਤਰ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੋ ਸਕਦੀ ਹੈ, ਨਿੱਜੀ ਡਾਟਾ ਸਮੇਤ ਜਿਵੇਂ ਪਾਸਵਰਡ ਅਤੇ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ। ਇਹ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ਐਪ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਕੀ ਇਹ ਸਪੈੱਲ ਚੈਕਰ ਵਰਤਣਾ ਹੈ?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ਨੋਟ ਕਰੋ: ਰੀਬੂਟ ਤੋਂ ਬਾਅਦ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਨਹੀਂ ਕਰਦੇ ਤਦ ਤੱਕ ਇਹ ਐਪ ਚਾਲੂ ਨਹੀਂ ਹੋ ਸਕਦੀ"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS ਰਜਿਸਟਰੇਸ਼ਨ ਸਥਿਤੀ"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"ਰਜਿਸਟਰ ਕੀਤੀ ਗਈ"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ਰਜਿਸਟਰ ਨਹੀਂ ਕੀਤੀ ਗਈ"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"ਅਣਉਪਲਬਧ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index e3c69fb..4810279 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nie udało się otworzyć ustawień aplikacji <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ta metoda wprowadzania tekstu może gromadzić cały wpisywany tekst, w tym dane osobowe takie jak hasła czy numery kart kredytowych. Pochodzi ona z aplikacji <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Użyć jej?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Uwaga: po restarcie ta aplikacja będzie mogła uruchomić się dopiero po odblokowaniu telefonu"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Stan rejestracji IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Zarejestrowane"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Niezarejestrowane"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Niedostępny"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 88c69eb..7a080a2 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Falha ao abrir as configurações de <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Este método de entrada pode coletar todo o texto que você digita, incluindo dados pessoais, como senhas e números de cartão de crédito. É um método do app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Usar este método de entrada?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Observação: após uma reinicialização, não é possível iniciar este app até que você desbloqueie seu smartphone"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Estado do registro de IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrado"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Não registrado"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Não disponível"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index dd73f3c..9229e13 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Falha ao abrir as definições para <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Este método de introdução pode permitir a recolha de todo o texto que digitar, incluindo dados pessoais como, por exemplo, palavras-passe e números de cartões de crédito. Decorre da aplicação <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Utilizar este método de introdução?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Nota: após reiniciar, só é possível iniciar esta aplicação quando o telemóvel for desbloqueado."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Estado do registo IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registado"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Não registado"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Indisponível"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 88c69eb..7a080a2 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Falha ao abrir as configurações de <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Este método de entrada pode coletar todo o texto que você digita, incluindo dados pessoais, como senhas e números de cartão de crédito. É um método do app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Usar este método de entrada?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Observação: após uma reinicialização, não é possível iniciar este app até que você desbloqueie seu smartphone"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Estado do registro de IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrado"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Não registrado"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Não disponível"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 93ad315..df34d58 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Deschiderea setărilor pentru <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> a eșuat"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Această metodă de introducere de text poate culege în întregime textul introdus, inclusiv datele personale, cum ar fi parolele și numerele cardurilor de credit. Metoda provine de la aplicația <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Utilizați această metodă de introducere de text?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Notă: după repornire, această aplicație nu poate porni până nu deblocați telefonul"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Situația înregistrării IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Înregistrat"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Neînregistrat"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Indisponibilă"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index ee5169b..3752cb3 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Не удалось открыть настройки приложения \"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>\""</string>
<string name="ime_security_warning" msgid="4135828934735934248">"При использовании этого способа могут собираться все вводимые данные, в том числе пароли и номера кредитных карт. Запрос поступил от приложения \"<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>\". Использовать этот способ ввода?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Примечание. Чтобы запустить это приложение после перезагрузки, разблокируйте экран."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Статус регистрации сервиса IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Зарегистрирован"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не зарегистрирован"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Недоступно"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 1ce6786..36fd952 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> සඳහා සැකසීම් විවෘත කිරීම අසාර්ථක විය"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"මෙම ආදාන ක්රමය මුරපද සහ ණයපත් අංක වැනි පෞද්ගලික දත්ත ඇතුළුව ඔබ ටයිප් කරන පෙළ එකතු කිරීමට හැකිය, එය <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> යෙදුමන් ලැබේ. මෙම ආදාන ක්රමය භාවිතා කරන්නද?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"සටහන: නැවත පණ ගැන්වීමකට පසුව, ඔබ ඔබේ දුරකථනය අගුලු හරින තෙක් මෙම යෙදුම ආරම්භ කළ නොහැකිය"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS ලියාපදිංචි තත්ත්වය"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"ලියාපදිංචි වී ඇත"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ලියාපදිංචි වී නැත"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"ලබාගත නොහැක"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index b1d2fa3..2eea457 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nastavenia aplikácie <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> sa nepodarilo otvoriť"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Pri tejto metóde vstupu sa môže zhromažďovať zadávaný text vrátane osobných údajov, ako sú heslá alebo čísla kreditných kariet. Táto metóda je poskytovaná aplikáciou <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Chcete použiť túto metódu vstupu?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Poznámka: Po reštartovaní sa táto aplikácia spustí až vtedy, keď odomknete telefón"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Stav registrácie IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrované"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Neregistrované"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Nie je k dispozícii"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 21badd6..e7e6212 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Ni mogoče odpreti nastavitev za <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ta način vnosa lahko morda zbere besedilo, ki ga vtipkate, vključno z osebnimi podatki, kot so gesla in številke kreditnih kartic. Omogoča ga aplikacija <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Ali želite uporabiti ta način vnosa?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Opomba: po vnovičnem zagonu te aplikacije ni mogoče zagnati, če ne odklenete telefona."</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Stanje registracije IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrirana"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ni registrirana"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Ni na voljo"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 54cde3c..f557d81 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Dështoi në hapjen e cilësimeve për <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Kjo metodë hyrjeje mund të mbledhë të gjithë tekstin që shkruan, përfshirë të dhënat personale si fjalëkalimet dhe numrat e kartave të kreditit. Kjo vjen nga aplikacioni <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Të përdoret kjo metodë hyrjeje?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Shënim: Pas një rinisjeje, ky aplikacion nuk mund të niset derisa të shkyçësh telefonin"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Gjendja e regjistrimit të IMS-së"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Regjistruar"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Paregjistruar"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Nuk ofrohet"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 4e0bee0..1c0fb24 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Отварање подешавања за апликацију <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> није успело"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Овај метод уноса можда може да прикупља сав текст који уносите, укључујући личне податке, као што су лозинке и бројеви кредитних картица. Потиче од апликације <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Желите ли да користите овај метод уноса?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Напомена: После рестартовања ова апликација не може да се покрене док не откључате телефон"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Статус IMS регистрације"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Регистрован je"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Није регистрован"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Недоступно"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index dea265d..c233bec 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Det gick inte att öppna inställningarna för <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Den här inmatningsmetoden kan samla all text som du skriver, inklusive personliga uppgifter som lösenord och kreditkortsnummer. Den kommer från appen <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Vill du använda inmatningsmetoden?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Obs! När du har startat om enheten måste du låsa upp mobilen innan du kan starta den här appen"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS-registrering"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrerad"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ej registrerad"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Inte tillgängligt"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 7126594..700153b 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Imeshindwa kufungua mipangilio ya <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Huenda mbinu hii ya kuingiza ikakusanya maandishi yote unayoandika, pamoja na data ya kibinafsi kama vile manenosiri na nambari za kadi za mkopo. Inatoka kwa programu <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Je, ungependa kutumia mbinu hii ya kingiza?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Kumbuka: Baada ya kuwasha tena programu hii, hutaweza kuitumia hadi utakapofungua simu yako"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Hali ya usajili wa IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Imesajiliwa"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Haijasajiliwa"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Hapatikani"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 4f563fa..5ea41c4 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> க்கான அமைப்புகளைத் திறப்பதில் தோல்வி"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"இந்த உள்ளீட்டு முறையானது, கடவுச்சொற்கள் மற்றும் கிரெடிட் கார்டு எண்கள் போன்ற தனிப்பட்ட தகவல் உள்பட நீங்கள் உள்ளிடும் எல்லா உரையையும் சேகரிக்கக்கூடும். இது <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> பயன்பாட்டிலிருந்து வந்துள்ளது. இந்த உள்ளீட்டு முறையைப் பயன்படுத்தவா?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"குறிப்பு: மறுதொடக்கம் செய்த பிறகு, மொபைலைத் திறக்கும் வரை இந்தப் பயன்பாட்டால் தொடங்க முடியாது"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS பதிவின் நிலை"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"பதிவு செய்யப்பட்டது"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"பதிவு செய்யப்படவில்லை"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"கிடைக்கவில்லை"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 0d1ca375..7daa89e 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> యొక్క సెట్టింగ్లను తెరవడం విఫలమైంది"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"ఈ ఇన్పుట్ పద్ధతి మీరు టైప్ చేసే మొత్తం వచనాన్ని అలాగే పాస్వర్డ్లు మరియు క్రెడిట్ కార్డు నంబర్ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> అనువర్తనంలో అందించబడుతుంది. ఈ ఇన్పుట్ పద్ధతిని ఉపయోగించాలా?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"గమనిక: రీబూట్ చేసాక, మీరు మీ ఫోన్ను అన్లాక్ చేసే వరకు ఈ యాప్ ప్రారంభం కాదు"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS నమోదు స్థితి"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"నమోదు చేయబడింది"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"నమోదు కాలేదు"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"అందుబాటులో లేదు"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index f7ba20a..37fba990 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"ไม่สามารถเปิดการตั้งค่าสำหรับ <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"วิธีการป้อนข้อมูลนี้อาจเก็บข้อความทั้งหมดที่คุณพิมพ์ รวมถึงข้อมูลส่วนบุคคล เช่น รหัสผ่านและหมายเลขบัตรเครดิต โดยมาจากแอปพลิเคชัน <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ใช้วิธีการป้อนข้อมูลนี้หรือไม่"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"หมายเหตุ: หลังจากเริ่มต้นใหม่ แอปนี้จะไม่สามารถเริ่มการทำงานได้จนกว่าคุณจะปลดล็อกโทรศัพท์"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"สถานะการลงทะเบียน IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"ลงทะเบียนแล้ว"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ไม่ได้ลงทะเบียน"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"ไม่ว่าง"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 10d8102..25227a3 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nabigong buksan ang mga setting para sa <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Maaaring magawa ng pamamaraan ng pag-input na ito na kolektahin ang lahat ng tekstong iyong tina-type, kabilang ang personal na data katulad ng mga password at mga numero ng credit card. Nagmumula ito sa app na <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Gamitin ang pamamaraan ng pag-input na ito?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Tandaan: Pagkatapos ng pag-reboot, hindi makakapagsimula ang app na ito hangga\'t hindi mo ina-unlock ang iyong telepono"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Status ng pagpaparehistro ng IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Nakarehistro"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Hindi nakarehistro"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Hindi available"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 3d8d0d3..893d8b3 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ayarları açılamadı"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Bu giriş yöntemi, şifreler ve kredi kartı numaraları gibi kişisel veriler de dahil olmak üzere yazdığınız tüm metni toplayabilir. Bu yöntem, <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> uygulamasının bir özelliğidir. Bu giriş yöntemini kullanmak istiyor musunuz?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Not: Yeniden başlatma sonrasında, telefonunuzun kilidi açılıncaya kadar bu uygulama başlatılamaz"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS kaydı durumu"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Kaydettirildi"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Kaydettirilmedi"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Kullanılamıyor"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 7d2c6fd..f3ed643 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Не вдалося відкрити налаштування для програми <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Під час використання цього методу введення може записуватись весь текст, який ви вводите, зокрема паролі й номери кредитних карток. Цей метод запитує програма <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Використати цей метод введення?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Примітка: щоб запустити цей додаток після перезавантаження, спершу потрібно буде розблокувати телефон"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Статус реєстрації IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Зареєстровано"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не зареєстровано"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Недоступно"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 63c040e..550280d 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> کیلئے ترتیبات کھولنے میں ناکام ہوگیا"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"اندراج کا یہ طریقہ آپ کے ٹائپ کردہ سبھی متن کو جمع کر سکتا ہے، بشمول ذاتی ڈیٹا جیسے پاس ورڈز اور کریڈٹ کارڈ نمبرز۔ یہ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ایپ سے آتا ہے۔ اندراج کا یہ طریقہ استعمال کریں؟"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"نوٹ: ریبوٹ کرنے کے بعد یہ ایپ تب تک شروع نہیں ہو سکتی جب تک آپ اپنا فون غیر مقفل نہ کر لیں"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS رجسٹریشن کی صورتحال"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"رجسٹر شدہ"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"رجسٹر نہیں ہے"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"غیر دستیاب"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index fbe9026..055613b 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> sozlamalarini ochmadi"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Ushbu yozish usuli barcha yozgan matnlaringizni to‘plab olishi mumkin, jumladan kredit karta raqamlari va parollar kabi shaxsiy ma‘lumotlarni ham. Usul <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ilovasi bilan o‘rnatiladi. Ushbu usuldan foydalanilsinmi?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Eslatma: O‘chirib-yoqilgandan so‘ng, bu ilova to telefoningiz qulfdan chiqarilmaguncha ishga tushmaydi"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS registratsiyasi holati"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Registratsiya qilingan"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Registratsiya qilinmagan"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Mavjud emas"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 07d0999..bc5df8f 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Không thể mở cài đặt cho <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Phương thức nhập này có thể thu thập tất cả văn bản bạn nhập, bao gồm dữ liệu cá nhân như mật khẩu và số thẻ tín dụng. Phương thức nhập này đến từ ứng dụng <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Sử dụng phương thức nhập này?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Lưu ý: Sau khi khởi động lại, ứng dụng này không thể khởi động cho đến khi bạn mở khóa điện thoại"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Trạng thái đăng ký IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Đã đăng ký"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Chưa được đăng ký"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Không có"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 1850f61..4bbc976 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"无法打开 <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> 的设置"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"此输入法可能会收集您输入的所有内容,包括密码和信用卡号等个人数据。它来自“<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>”应用。要使用此输入法吗?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"注意:重新启动后,您必须将手机解锁才能运行此应用"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS 注册状态"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"已注册"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"未注册"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"无法获取"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 379a1f1..e70b63b 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"無法開啟 <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> 的設定"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"這個輸入法可能會收集您輸入的所有文字,包括密碼和信用卡號碼等個人資料。這個輸入法由 <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> 應用程式提供,您要使用嗎?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"注意:重新啟動後,您必須解鎖手機,才可開始使用此應用程式"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS 註冊狀態"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"已註冊"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"未註冊"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"無法使用"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 2abca68..38ec6c7 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"無法開啟「<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>」的設定"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"這個輸入法是由「<xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>」應用程式所提供,它可能會收集你輸入的所有文字,包括密碼和信用卡號等個人資料。要啟用這個輸入法嗎?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"注意:重新啟動後,你必須將手機解鎖,才能執行這個應用程式"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"IMS 註冊狀態"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"已註冊"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"未註冊"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"無法取得"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 1de1312..1c15d54 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -388,4 +388,8 @@
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Yehlulekile ukuvula izilungiselelo ze-<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ime_security_warning" msgid="4135828934735934248">"Indlela yokufakwayo ingase ikwazi ukuqoqa wonke umbhalo owuthayiphayo, kuhlanganise idatha yomuntu siqu njengamaphasiwedi nezinombolo zekhadi lesikoloto. Iphuma kuhlelo lokusebenza <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Sebenzisa indlela yokufaka?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Yazi: Ngemuva kokuqalisa, lolu hlelo lokusebenza alukwazi ukuqala uze uvule ifoni yakho"</string>
+ <string name="ims_reg_title" msgid="7609782759207241443">"Isimo sokubhaliswa se-IMS"</string>
+ <string name="ims_reg_status_registered" msgid="933003316932739188">"Kubhalisiwe"</string>
+ <string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Akubhalisiwe"</string>
+ <string name="status_unavailable" msgid="7862009036663793314">"Ayitholakali"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e561239..4bae85f 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -536,8 +536,8 @@
<string name="activity_not_found" msgid="348423244327799974">"L\'aplicació no està instal·lada al dispositiu"</string>
<string name="clock_seconds" msgid="7689554147579179507">"Mostra els segons del rellotge"</string>
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
- <string name="qs_rearrange" msgid="8060918697551068765">"Reorganitza Configuració ràpida"</string>
- <string name="show_brightness" msgid="6613930842805942519">"Mostra la brillantor a Configuració ràpida"</string>
+ <string name="qs_rearrange" msgid="8060918697551068765">"Reorganitza la configuració ràpida"</string>
+ <string name="show_brightness" msgid="6613930842805942519">"Mostra la brillantor a configuració ràpida"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vols activar el Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connectar el teclat amb la tauleta, primer has d\'activar el Bluetooth."</string>
@@ -705,7 +705,7 @@
<string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha afegit a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha suprimit"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha mogut a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de la configuració ràpida."</string>
+ <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de configuració ràpida."</string>
<string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificació de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="dock_forced_resizable" msgid="5914261505436217520">"És possible que l\'aplicació no funcioni amb la pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'aplicació no admet la pantalla dividida."</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index 7baa57e..0cb6423 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -57,16 +57,16 @@
SecurityMode getSecurityMode(int userId) {
KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
- if (SubscriptionManager.isValidSubscriptionId(
- monitor.getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED))) {
- return SecurityMode.SimPin;
- }
-
if (mIsPukScreenAvailable && SubscriptionManager.isValidSubscriptionId(
monitor.getNextSubIdForState(IccCardConstants.State.PUK_REQUIRED))) {
return SecurityMode.SimPuk;
}
+ if (SubscriptionManager.isValidSubscriptionId(
+ monitor.getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED))) {
+ return SecurityMode.SimPin;
+ }
+
final int security = mLockPatternUtils.getActivePasswordQuality(userId);
switch (security) {
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 4b37715..592dda0 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -83,7 +83,6 @@
private boolean mMenuRowIntercepting;
private boolean mLongPressSent;
- private LongPressListener mLongPressListener;
private Runnable mWatchLongPress;
private final long mLongPressTimeout;
@@ -115,10 +114,6 @@
mFlingAnimationUtils = new FlingAnimationUtils(context, getMaxEscapeAnimDuration() / 1000f);
}
- public void setLongPressListener(LongPressListener listener) {
- mLongPressListener = listener;
- }
-
public void setDensityScale(float densityScale) {
mDensityScale = densityScale;
}
@@ -257,7 +252,7 @@
}
}
- public void removeLongPressCallback() {
+ public void cancelLongPress() {
if (mWatchLongPress != null) {
mHandler.removeCallbacks(mWatchLongPress);
mWatchLongPress = null;
@@ -288,33 +283,27 @@
mInitialTouchPos = getPos(ev);
mPerpendicularInitialTouchPos = getPerpendicularPos(ev);
mTranslation = getTranslation(mCurrView);
- if (mLongPressListener != null) {
- if (mWatchLongPress == null) {
- mWatchLongPress = new Runnable() {
- @Override
- public void run() {
- if (mCurrView != null && !mLongPressSent) {
- mLongPressSent = true;
+ if (mWatchLongPress == null) {
+ mWatchLongPress = new Runnable() {
+ @Override
+ public void run() {
+ if (mCurrView != null && !mLongPressSent) {
+ mLongPressSent = true;
+ mCurrView.getLocationOnScreen(mTmpPos);
+ final int x = (int) ev.getRawX() - mTmpPos[0];
+ final int y = (int) ev.getRawY() - mTmpPos[1];
+ if (mCurrView instanceof ExpandableNotificationRow) {
mCurrView.sendAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
- mCurrView.getLocationOnScreen(mTmpPos);
- final int x = (int) ev.getRawX() - mTmpPos[0];
- final int y = (int) ev.getRawY() - mTmpPos[1];
- MenuItem menuItem = null;
- if (mCurrView instanceof ExpandableNotificationRow) {
- menuItem = ((ExpandableNotificationRow) mCurrView)
- .getProvider().getLongpressMenuItem(mContext);
- }
- if (menuItem != null) {
- mLongPressListener.onLongPress(mCurrView, x, y,
- menuItem);
- }
+ ExpandableNotificationRow currRow =
+ (ExpandableNotificationRow) mCurrView;
+ currRow.doLongClickCallback(x, y);
}
}
- };
- }
- mHandler.postDelayed(mWatchLongPress, mLongPressTimeout);
+ }
+ };
}
+ mHandler.postDelayed(mWatchLongPress, mLongPressTimeout);
}
break;
@@ -331,7 +320,7 @@
mDragging = true;
mInitialTouchPos = getPos(ev);
mTranslation = getTranslation(mCurrView);
- removeLongPressCallback();
+ cancelLongPress();
}
}
break;
@@ -343,7 +332,7 @@
mCurrView = null;
mLongPressSent = false;
mMenuRowIntercepting = false;
- removeLongPressCallback();
+ cancelLongPress();
if (captured) return true;
break;
}
@@ -586,7 +575,7 @@
// We are not doing anything, make sure the long press callback
// is not still ticking like a bomb waiting to go off.
- removeLongPressCallback();
+ cancelLongPress();
return false;
}
}
@@ -734,15 +723,4 @@
*/
float getFalsingThresholdFactor();
}
-
- /**
- * Equivalent to View.OnLongClickListener with coordinates
- */
- public interface LongPressListener {
- /**
- * Equivalent to {@link View.OnLongClickListener#onLongClick(View)} with coordinates
- * @return whether the longpress was handled
- */
- boolean onLongPress(View v, int x, int y, MenuItem item);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 283ac0c..b96bd9b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -81,23 +81,15 @@
implements RecentsComponent, CommandQueue.Callbacks {
private final static String TAG = "Recents";
- private final static boolean DEBUG = false;
public final static int EVENT_BUS_PRIORITY = 1;
public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
- public final static int RECENTS_GROW_TARGET_INVALID = -1;
public final static Set<String> RECENTS_ACTIVITIES = new HashSet<>();
static {
RECENTS_ACTIVITIES.add(RecentsImpl.RECENTS_ACTIVITY);
}
- // Purely for experimentation
- private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg";
- private final static String ACTION_SHOW_RECENTS = "com.android.systemui.recents.ACTION_SHOW";
- private final static String ACTION_HIDE_RECENTS = "com.android.systemui.recents.ACTION_HIDE";
- private final static String ACTION_TOGGLE_RECENTS = "com.android.systemui.recents.ACTION_TOGGLE";
-
private static final String COUNTER_WINDOW_SUPPORTED = "window_enter_supported";
private static final String COUNTER_WINDOW_UNSUPPORTED = "window_enter_unsupported";
private static final String COUNTER_WINDOW_INCOMPATIBLE = "window_enter_incompatible";
@@ -107,11 +99,6 @@
private static RecentsTaskLoader sTaskLoader;
private static RecentsConfiguration sConfiguration;
- // For experiments only, allows another package to handle recents if it is defined in the system
- // properties. This is limited to show/toggle/hide, and does not tie into the ActivityManager,
- // and does not reside in the home stack.
- private String mOverrideRecentsPackageName;
-
private Handler mHandler;
private RecentsImpl mImpl;
private int mDraggingInRecentsCurrentUser;
@@ -204,21 +191,13 @@
@Override
public void start() {
- sDebugFlags = new RecentsDebugFlags(mContext);
+ sDebugFlags = new RecentsDebugFlags();
sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
sConfiguration = new RecentsConfiguration(mContext);
sTaskLoader = new RecentsTaskLoader(mContext);
mHandler = new Handler();
mImpl = new RecentsImpl(mContext);
- // Check if there is a recents override package
- if (Build.IS_USERDEBUG || Build.IS_ENG) {
- String cnStr = SystemProperties.get(RECENTS_OVERRIDE_SYSPROP_KEY);
- if (!cnStr.isEmpty()) {
- mOverrideRecentsPackageName = cnStr;
- }
- }
-
// Register with the event bus
EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
EventBus.getDefault().register(sSystemServicesProxy, EVENT_BUS_PRIORITY);
@@ -257,16 +236,8 @@
return;
}
- if (proxyToOverridePackage(ACTION_SHOW_RECENTS)) {
- return;
- }
- try {
- ActivityManager.getService().closeSystemDialogs(SYSTEM_DIALOG_REASON_RECENT_APPS);
- } catch (RemoteException e) {
- }
-
+ sSystemServicesProxy.sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents();
-
int currentUser = sSystemServicesProxy.getCurrentUser();
if (sSystemServicesProxy.isSystemUser(currentUser)) {
mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
@@ -301,10 +272,6 @@
return;
}
- if (proxyToOverridePackage(ACTION_HIDE_RECENTS)) {
- return;
- }
-
int currentUser = sSystemServicesProxy.getCurrentUser();
if (sSystemServicesProxy.isSystemUser(currentUser)) {
mImpl.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
@@ -336,12 +303,7 @@
return;
}
- if (proxyToOverridePackage(ACTION_TOGGLE_RECENTS)) {
- return;
- }
-
int growTarget = getComponent(Divider.class).getView().growsRecents();
-
int currentUser = sSystemServicesProxy.getCurrentUser();
if (sSystemServicesProxy.isSystemUser(currentUser)) {
mImpl.toggleRecents(growTarget);
@@ -820,21 +782,6 @@
(Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);
}
- /**
- * Attempts to proxy the following action to the override recents package.
- * @return whether the proxying was successful
- */
- private boolean proxyToOverridePackage(String action) {
- if (mOverrideRecentsPackageName != null) {
- Intent intent = new Intent(action);
- intent.setPackage(mOverrideRecentsPackageName);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendBroadcast(intent);
- return true;
- }
- return false;
- }
-
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Recents");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 86b7790..ab2181c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -79,7 +79,6 @@
import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
-import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
@@ -188,41 +187,6 @@
} else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
// When switching users, dismiss Recents to Home similar to screen off
finish();
- } else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
- // If the time shifts but the currentTime >= lastStackActiveTime, then that boundary
- // is still valid. Otherwise, we need to reset the lastStackactiveTime to the
- // currentTime and remove the old tasks in between which would not be previously
- // visible, but currently would be in the new currentTime
- int currentUser = SystemServicesProxy.getInstance(RecentsActivity.this)
- .getCurrentUser();
- long oldLastStackActiveTime = Settings.Secure.getLongForUser(getContentResolver(),
- Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, -1, currentUser);
- if (oldLastStackActiveTime != -1) {
- long currentTime = System.currentTimeMillis();
- if (currentTime < oldLastStackActiveTime) {
- // We are only removing tasks that are between the new current time
- // and the old last stack active time, they were not visible and in the
- // TaskStack so we don't need to remove any associated TaskViews but we do
- // need to load the task id's from the system
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(ctx);
- loader.preloadRawTasks(loadPlan, false /* includeFrontMostExcludedTask */);
- List<ActivityManager.RecentTaskInfo> tasks = loadPlan.getRawTasks();
- for (int i = tasks.size() - 1; i >= 0; i--) {
- ActivityManager.RecentTaskInfo task = tasks.get(i);
- if (currentTime <= task.lastActiveTime && task.lastActiveTime <
- oldLastStackActiveTime) {
- Recents.getSystemServices().removeTask(task.persistentId);
- }
- }
- Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
- currentTime, currentUser);
-
- // Clear the last PiP task time, it's an edge case and we'd rather it
- // not relaunch the PiP task if the user double taps
- RecentsImpl.clearLastPipTime();
- }
- }
}
}
};
@@ -383,7 +347,6 @@
// Register the broadcast receiver to handle messages when the screen is turned off
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
registerReceiver(mSystemBroadcastReceiver, filter);
@@ -467,8 +430,7 @@
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!loadPlan.hasTasks()) {
- loader.preloadTasks(loadPlan, launchState.launchedToTaskId,
- !launchState.launchedFromHome && !launchState.launchedViaDockGesture);
+ loader.preloadTasks(loadPlan, launchState.launchedToTaskId);
}
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
@@ -751,15 +713,11 @@
}
public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
- EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(true));
mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
mRecentsView.invalidate();
}
public final void onBusEvent(ExitRecentsWindowFirstAnimationFrameEvent event) {
- if (mRecentsView.isLastTaskLaunchedFreeform()) {
- EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(false));
- }
mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
mRecentsView.invalidate();
}
@@ -889,8 +847,7 @@
RecentsActivityLaunchState launchState = config.getLaunchState();
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
- loader.preloadTasks(loadPlan, -1 /* runningTaskId */,
- false /* includeFrontMostExcludedTask */);
+ loader.preloadTasks(loadPlan, -1 /* runningTaskId */);
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
@@ -931,13 +888,9 @@
Recents.getTaskLoader().dump(prefix, writer);
String id = Integer.toHexString(System.identityHashCode(this));
- long lastStackActiveTime = Settings.Secure.getLongForUser(getContentResolver(),
- Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, -1,
- SystemServicesProxy.getInstance(this).getCurrentUser());
writer.print(prefix); writer.print(TAG);
writer.print(" visible="); writer.print(mIsVisible ? "Y" : "N");
- writer.print(" lastStackTaskActiveTime="); writer.print(lastStackActiveTime);
writer.print(" currentTime="); writer.print(System.currentTimeMillis());
writer.print(" [0x"); writer.print(id); writer.print("]");
writer.println();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index 0262a09..cb00843 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -26,15 +26,13 @@
/**
* Tunable debug flags
*/
-public class RecentsDebugFlags implements TunerService.Tunable {
+public class RecentsDebugFlags {
public static class Static {
// Enables debug drawing for the transition thumbnail
public static final boolean EnableTransitionThumbnailDebugMode = false;
// This disables the bitmap and icon caches
public static final boolean DisableBackgroundCache = false;
- // Enables the task affiliations
- public static final boolean EnableAffiliatedTaskGroups = false;
// Enables the button above the stack
public static final boolean EnableStackActionButton = true;
// Overrides the Tuner flags and enables the timeout
@@ -50,19 +48,6 @@
public static final int MockTasksPackageCount = 3;
// Defines the number of mock recents tasks to create
public static final int MockTaskCount = 100;
- // Enables the simulated task affiliations
- public static final boolean EnableMockTaskGroups = false;
- // Defines the number of mock task affiliations per group
- public static final int MockTaskGroupsTaskCount = 12;
- }
-
- /**
- * We read the prefs once when we start the activity, then update them as the tuner changes
- * the flags.
- */
- public RecentsDebugFlags(Context context) {
- // Register all our flags, this will also call onTuningChanged() for each key, which will
- // initialize the current state of each flag
}
/**
@@ -70,7 +55,7 @@
*/
public boolean isFastToggleRecentsEnabled() {
SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.hasFreeformWorkspaceSupport() || ssp.isTouchExplorationEnabled()) {
+ if (ssp.isTouchExplorationEnabled()) {
return false;
}
return Static.EnableFastToggleTimeout;
@@ -82,9 +67,4 @@
public boolean isPagingEnabled() {
return Static.EnablePaging;
}
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- EventBus.getDefault().send(new DebugFlagsChangedEvent());
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 3e2a5f3..4e721d7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -77,7 +77,6 @@
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.Task.TaskKey;
-import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.model.ThumbnailData;
import com.android.systemui.recents.views.RecentsTransitionHelper;
@@ -142,7 +141,7 @@
ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask();
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
- loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */);
+ loader.preloadTasks(plan, -1);
TaskStack stack = plan.getTaskStack();
RecentsActivityLaunchState launchState = new RecentsActivityLaunchState();
RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
@@ -283,7 +282,7 @@
// We can use a new plan since the caches will be the same.
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
- loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */);
+ loader.preloadTasks(plan, -1);
RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
launchOpts.numVisibleTasks = loader.getIconCacheSize();
launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize();
@@ -473,8 +472,7 @@
// RecentsActivity) only if there is a task to animate to. Post this to ensure that we
// don't block the touch feedback on the nav bar button which triggers this.
mHandler.post(() -> {
- MutableBoolean isHomeStackVisible = new MutableBoolean(true);
- if (!ssp.isRecentsActivityVisible(isHomeStackVisible)) {
+ if (!ssp.isRecentsActivityVisible(null)) {
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
if (runningTask == null) {
return;
@@ -482,7 +480,7 @@
RecentsTaskLoader loader = Recents.getTaskLoader();
sInstanceLoadPlan = loader.createLoadPlan(mContext);
- loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible.value);
+ loader.preloadTasks(sInstanceLoadPlan, runningTask.id);
TaskStack stack = sInstanceLoadPlan.getTaskStack();
if (stack.getTaskCount() > 0) {
// Only preload the icon (but not the thumbnail since it may not have been taken
@@ -522,7 +520,7 @@
SystemServicesProxy ssp = Recents.getSystemServices();
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
- loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */);
+ loader.preloadTasks(plan, -1);
TaskStack focusedStack = plan.getTaskStack();
// Return early if there are no tasks in the focused stack
@@ -577,7 +575,7 @@
SystemServicesProxy ssp = Recents.getSystemServices();
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
- loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */);
+ loader.preloadTasks(plan, -1);
TaskStack focusedStack = plan.getTaskStack();
// Return early if there are no tasks in the focused stack
@@ -595,43 +593,38 @@
Task toTask = null;
ActivityOptions launchOpts = null;
int taskCount = tasks.size();
- int numAffiliatedTasks = 0;
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
if (task.key.id == runningTask.id) {
- TaskGrouping group = task.group;
- Task.TaskKey toTaskKey;
if (showNextTask) {
- toTaskKey = group.getNextTaskInGroup(task);
- launchOpts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_launch_next_affiliated_task_target,
- R.anim.recents_launch_next_affiliated_task_source);
+ if ((i + 1) < taskCount) {
+ toTask = tasks.get(i + 1);
+ launchOpts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_next_affiliated_task_target,
+ R.anim.recents_launch_next_affiliated_task_source);
+ }
} else {
- toTaskKey = group.getPrevTaskInGroup(task);
- launchOpts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_launch_prev_affiliated_task_target,
- R.anim.recents_launch_prev_affiliated_task_source);
+ if ((i - 1) >= 0) {
+ toTask = tasks.get(i - 1);
+ launchOpts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_prev_affiliated_task_target,
+ R.anim.recents_launch_prev_affiliated_task_source);
+ }
}
- if (toTaskKey != null) {
- toTask = focusedStack.findTaskWithId(toTaskKey.id);
- }
- numAffiliatedTasks = group.getTaskCount();
break;
}
}
// Return early if there is no next task
if (toTask == null) {
- if (numAffiliatedTasks > 1) {
- if (showNextTask) {
- ssp.startInPlaceAnimationOnFrontMostApplication(
- ActivityOptions.makeCustomInPlaceAnimation(mContext,
- R.anim.recents_launch_next_affiliated_task_bounce));
- } else {
- ssp.startInPlaceAnimationOnFrontMostApplication(
- ActivityOptions.makeCustomInPlaceAnimation(mContext,
- R.anim.recents_launch_prev_affiliated_task_bounce));
- }
+ if (showNextTask) {
+ ssp.startInPlaceAnimationOnFrontMostApplication(
+ ActivityOptions.makeCustomInPlaceAnimation(mContext,
+ R.anim.recents_launch_next_affiliated_task_bounce));
+ } else {
+ ssp.startInPlaceAnimationOnFrontMostApplication(
+ ActivityOptions.makeCustomInPlaceAnimation(mContext,
+ R.anim.recents_launch_prev_affiliated_task_bounce));
}
return;
}
@@ -753,8 +746,7 @@
stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top,
systemInsets.left, systemInsets.right, mTmpBounds);
stackLayout.reset();
- stackLayout.initialize(displayRect, windowRect, mTmpBounds,
- TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
+ stackLayout.initialize(displayRect, windowRect, mTmpBounds);
}
}
@@ -873,61 +865,29 @@
getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask,
Rect windowOverrideRect) {
final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
- if (runningTask != null
- && runningTask.configuration.windowConfiguration.getWindowingMode()
- == WINDOWING_MODE_FREEFORM) {
- ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
- ArrayList<Task> tasks = mDummyStackView.getStack().getStackTasks();
- TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
- TaskStackViewScroller stackScroller = mDummyStackView.getScroller();
- mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */);
- mDummyStackView.updateToInitialState();
+ // Update the destination rect
+ Task toTask = new Task();
+ TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask,
+ windowOverrideRect);
- for (int i = tasks.size() - 1; i >= 0; i--) {
- Task task = tasks.get(i);
- if (task.isFreeformTask()) {
- mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
- stackScroller.getStackScroll(), mTmpTransform, null,
- windowOverrideRect);
- GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform);
- Rect toTaskRect = new Rect();
- mTmpTransform.rect.round(toTaskRect);
- specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect));
- }
- }
- AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()];
- specs.toArray(specsArray);
+ RectF toTaskRect = toTransform.rect;
+ AppTransitionAnimationSpecsFuture future =
+ new RecentsTransitionHelper(mContext).getAppTransitionFuture(
+ () -> {
+ Rect rect = new Rect();
+ toTaskRect.round(rect);
+ GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(toTask,
+ toTransform);
+ return Lists.newArrayList(new AppTransitionAnimationSpec(
+ toTask.key.id, thumbnail, rect));
+ });
- // For low end ram devices, wait for transition flag is reset when Recents entrance
- // animation is complete instead of when the transition animation starts
- return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
- specsArray, mHandler, isLowRamDevice ? null : mResetToggleFlagListener, this),
- null);
- } else {
- // Update the destination rect
- Task toTask = new Task();
- TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask,
- windowOverrideRect);
-
- RectF toTaskRect = toTransform.rect;
- AppTransitionAnimationSpecsFuture future =
- new RecentsTransitionHelper(mContext).getAppTransitionFuture(
- () -> {
- Rect rect = new Rect();
- toTaskRect.round(rect);
- GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(toTask,
- toTransform);
- return Lists.newArrayList(new AppTransitionAnimationSpec(
- toTask.key.id, thumbnail, rect));
- });
-
- // For low end ram devices, wait for transition flag is reset when Recents entrance
- // animation is complete instead of when the transition animation starts
- return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
- mHandler, future.getFuture(), isLowRamDevice ? null : mResetToggleFlagListener,
- false /* scaleUp */), future);
- }
+ // For low end ram devices, wait for transition flag is reset when Recents entrance
+ // animation is complete instead of when the transition animation starts
+ return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
+ mHandler, future.getFuture(), isLowRamDevice ? null : mResetToggleFlagListener,
+ false /* scaleUp */), future);
}
/**
@@ -942,7 +902,7 @@
runningTaskOut.copyFrom(launchTask);
} else {
// If no task is specified or we can not find the task just use the front most one
- launchTask = stack.getStackFrontMostTask(true /* includeFreeform */);
+ launchTask = stack.getStackFrontMostTask();
runningTaskOut.copyFrom(launchTask);
}
@@ -1012,7 +972,7 @@
sInstanceLoadPlan = loader.createLoadPlan(mContext);
}
if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
- loader.preloadTasks(sInstanceLoadPlan, runningTaskId, !isHomeStackVisible);
+ loader.preloadTasks(sInstanceLoadPlan, runningTaskId);
}
TaskStack stack = sInstanceLoadPlan.getTaskStack();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateFreeformTaskViewVisibilityEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateFreeformTaskViewVisibilityEvent.java
deleted file mode 100644
index b42da9c..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateFreeformTaskViewVisibilityEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent to update the visibility of all visible freeform task views.
- */
-public class UpdateFreeformTaskViewVisibilityEvent extends EventBus.Event {
-
- public final boolean visible;
-
- public UpdateFreeformTaskViewVisibilityEvent(boolean visible) {
- this.visible = visible;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/NamedCounter.java b/packages/SystemUI/src/com/android/systemui/recents/misc/NamedCounter.java
deleted file mode 100644
index ec3c39c..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/NamedCounter.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.misc;
-
-/**
- * Used to generate successive incremented names.
- */
-public class NamedCounter {
-
- int mCount;
- String mPrefix = "";
- String mSuffix = "";
-
- public NamedCounter(String prefix, String suffix) {
- mPrefix = prefix;
- mSuffix = suffix;
- }
-
- /** Returns the next name. */
- public String nextName() {
- String name = mPrefix + mCount + mSuffix;
- mCount++;
- return name;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index bddf9a5..b1eb77d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.misc;
+import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -25,7 +26,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -45,7 +45,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -68,7 +67,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.provider.Settings.Secure;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.util.ArraySet;
@@ -140,11 +138,9 @@
UserManager mUm;
Display mDisplay;
String mRecentsPackage;
- ComponentName mAssistComponent;
private int mCurrentUserId;
boolean mIsSafeMode;
- boolean mHasFreeformWorkspaceSupport;
Bitmap mDummyIcon;
int mDummyThumbnailWidth;
@@ -319,10 +315,6 @@
ServiceManager.checkService(DreamService.DREAM_SERVICE));
mDisplay = mWm.getDefaultDisplay();
mRecentsPackage = context.getPackageName();
- mHasFreeformWorkspaceSupport =
- mPm.hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT) ||
- Settings.Global.getInt(context.getContentResolver(),
- DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
mIsSafeMode = mPm.isSafeMode();
mCurrentUserId = mAm.getCurrentUser();
@@ -339,9 +331,6 @@
mBgProtectionPaint.setColor(0xFFffffff);
mBgProtectionCanvas = new Canvas();
- // Resolve the assist intent
- mAssistComponent = mAssistUtils.getAssistComponentForUser(UserHandle.myUserId());
-
// Since SystemServicesProxy can be accessed from a per-SysUI process component, create a
// per-process listener to keep track of the current user id to reduce the number of binder
// calls to fetch it.
@@ -385,20 +374,15 @@
/**
* Returns a list of the recents tasks.
- *
- * @param includeFrontMostExcludedTask if set, will ensure that the front most excluded task
- * will be visible, otherwise no excluded tasks will be
- * visible.
*/
- public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId,
- boolean includeFrontMostExcludedTask, ArraySet<Integer> quietProfileIds) {
+ public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
if (mAm == null) return null;
// If we are mocking, then create some recent tasks
if (RecentsDebugFlags.Static.EnableMockTasks) {
ArrayList<ActivityManager.RecentTaskInfo> tasks =
new ArrayList<ActivityManager.RecentTaskInfo>();
- int count = Math.min(numLatestTasks, RecentsDebugFlags.Static.MockTaskCount);
+ int count = Math.min(numTasks, RecentsDebugFlags.Static.MockTaskCount);
for (int i = 0; i < count; i++) {
// Create a dummy component name
int packageIndex = i % RecentsDebugFlags.Static.MockTasksPackageCount;
@@ -412,7 +396,7 @@
rti.baseIntent = new Intent();
rti.baseIntent.setComponent(cn);
rti.description = description;
- rti.firstActiveTime = rti.lastActiveTime = i;
+ rti.lastActiveTime = i;
if (i % 2 == 0) {
rti.taskDescription = new ActivityManager.TaskDescription(description,
Bitmap.createBitmap(mDummyIcon), null,
@@ -427,57 +411,24 @@
return tasks;
}
- // Remove home/recents/excluded tasks
- int minNumTasksToQuery = 10;
- int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
- int flags = ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS |
- ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK |
- ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS |
- ActivityManager.RECENT_IGNORE_UNAVAILABLE |
- ActivityManager.RECENT_INCLUDE_PROFILES;
- if (includeFrontMostExcludedTask) {
- flags |= ActivityManager.RECENT_WITH_EXCLUDED;
- }
- List<ActivityManager.RecentTaskInfo> tasks = null;
try {
- tasks = mAm.getRecentTasksForUser(numTasksToQuery, flags, userId);
+ List<ActivityManager.RecentTaskInfo> tasks = mIam.getRecentTasks(numTasks,
+ RECENT_IGNORE_UNAVAILABLE, userId).getList();
+ Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
+ while (iter.hasNext()) {
+ ActivityManager.RecentTaskInfo t = iter.next();
+
+ // Remove the task if it or it's package are blacklsited
+ if (sRecentsBlacklist.contains(t.realActivity.getClassName()) ||
+ sRecentsBlacklist.contains(t.realActivity.getPackageName())) {
+ iter.remove();
+ }
+ }
+ return tasks;
} catch (Exception e) {
Log.e(TAG, "Failed to get recent tasks", e);
- }
-
- // Break early if we can't get a valid set of tasks
- if (tasks == null) {
return new ArrayList<>();
}
-
- boolean isFirstValidTask = true;
- Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
- while (iter.hasNext()) {
- ActivityManager.RecentTaskInfo t = iter.next();
-
- // NOTE: The order of these checks happens in the expected order of the traversal of the
- // tasks
-
- // Remove the task if it or it's package are blacklsited
- if (sRecentsBlacklist.contains(t.realActivity.getClassName()) ||
- sRecentsBlacklist.contains(t.realActivity.getPackageName())) {
- iter.remove();
- continue;
- }
-
- // Remove the task if it is marked as excluded, unless it is the first most task and we
- // are requested to include it
- boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
- == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
- isExcluded |= quietProfileIds.contains(t.userId);
- if (isExcluded && (!isFirstValidTask || !includeFrontMostExcludedTask)) {
- iter.remove();
- }
-
- isFirstValidTask = false;
- }
-
- return tasks.subList(0, Math.min(tasks.size(), numLatestTasks));
}
/**
@@ -572,13 +523,6 @@
}
/**
- * Returns whether this device has freeform workspaces.
- */
- public boolean hasFreeformWorkspaceSupport() {
- return mHasFreeformWorkspaceSupport;
- }
-
- /**
* Returns whether this device is in the safe mode.
*/
public boolean isInSafeMode() {
@@ -646,7 +590,7 @@
*/
public boolean hasSoftNavigationBar() {
try {
- return WindowManagerGlobal.getWindowManagerService().hasNavigationBar();
+ return mIwm.hasNavigationBar();
} catch (RemoteException e) {
e.printStackTrace();
}
@@ -715,7 +659,7 @@
ActivityManager.TaskSnapshot snapshot = null;
try {
- snapshot = ActivityManager.getService().getTaskSnapshot(taskId, reducedResolution);
+ snapshot = mIam.getTaskSnapshot(taskId, reducedResolution);
} catch (RemoteException e) {
Log.w(TAG, "Failed to retrieve snapshot", e);
}
@@ -933,22 +877,6 @@
}
/**
- * Returns a logo used on TV for the specified Activity.
- */
- public Drawable getActivityLogo(ActivityInfo info) {
- if (mPm == null) return null;
-
- // If we are mocking, then return a mock logo
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- return new ColorDrawable(0xFF666666);
- }
-
- Drawable logo = info.loadLogo(mPm);
- return logo;
- }
-
-
- /**
* Returns the given label for a user, badging if necessary.
*/
private String getBadgedLabel(String label, int userId) {
@@ -968,24 +896,6 @@
return mKgm.isDeviceLocked(userId);
}
- /** Returns the package name of the home activity. */
- public String getHomeActivityPackageName() {
- if (mPm == null) return null;
- if (RecentsDebugFlags.Static.EnableMockTasks) return null;
-
- ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
- ComponentName defaultHomeActivity = mPm.getHomeActivities(homeActivities);
- if (defaultHomeActivity != null) {
- return defaultHomeActivity.getPackageName();
- } else if (homeActivities.size() == 1) {
- ResolveInfo info = homeActivities.get(0);
- if (info.activityInfo != null) {
- return info.activityInfo.packageName;
- }
- }
- return null;
- }
-
/**
* Returns whether the provided {@param userId} represents the system user.
*/
@@ -1195,7 +1105,7 @@
return;
}
try {
- WindowManagerGlobal.getWindowManagerService().endProlongedAnimations();
+ mIwm.endProlongedAnimations();
} catch (Exception e) {
e.printStackTrace();
}
@@ -1205,7 +1115,7 @@
if (mWm == null) return;
try {
- WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(listener);
+ mIwm.registerDockedStackListener(listener);
} catch (Exception e) {
e.printStackTrace();
}
@@ -1232,8 +1142,7 @@
if (mWm == null) return;
try {
- WindowManagerGlobal.getWindowManagerService().getStableInsets(Display.DEFAULT_DISPLAY,
- outStableInsets);
+ mIwm.getStableInsets(Display.DEFAULT_DISPLAY, outStableInsets);
} catch (Exception e) {
e.printStackTrace();
}
@@ -1243,9 +1152,7 @@
IAppTransitionAnimationSpecsFuture future, IRemoteCallback animStartedListener,
boolean scaleUp) {
try {
- WindowManagerGlobal.getWindowManagerService()
- .overridePendingAppTransitionMultiThumbFuture(future, animStartedListener,
- scaleUp);
+ mIwm.overridePendingAppTransitionMultiThumbFuture(future, animStartedListener, scaleUp);
} catch (RemoteException e) {
Log.w(TAG, "Failed to override transition: " + e);
}
@@ -1292,14 +1199,6 @@
});
}
- public void updateOverviewLastStackActiveTimeAsync(long newLastStackActiveTime,
- int currentUserId) {
- mUiOffloadThread.submit(() -> {
- Settings.Secure.putLongForUser(mContext.getContentResolver(),
- Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId);
- });
- }
-
public interface StartActivityFromRecentsResultListener {
void onStartActivityResult(boolean succeeded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index d5e0313..62ba30b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -57,10 +57,6 @@
*/
public class RecentsTaskLoadPlan {
- private static int MIN_NUM_TASKS = 5;
- private static int SESSION_BEGIN_TIME = 1000 /* ms/s */ * 60 /* s/min */ * 60 /* min/hr */ *
- 6 /* hrs */;
-
/** The set of conditions to load tasks. */
public static class Options {
public int runningTaskId = -1;
@@ -74,44 +70,24 @@
Context mContext;
- int mPreloadedUserId;
List<ActivityManager.RecentTaskInfo> mRawTasks;
TaskStack mStack;
- ArraySet<Integer> mCurrentQuietProfiles = new ArraySet<Integer>();
/** Package level ctor */
RecentsTaskLoadPlan(Context context) {
mContext = context;
}
- private void updateCurrentQuietProfilesCache(int currentUserId) {
- mCurrentQuietProfiles.clear();
-
- UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- List<UserInfo> profiles = userManager.getProfiles(currentUserId);
- if (profiles != null) {
- for (int i = 0; i < profiles.size(); i++) {
- UserInfo user = profiles.get(i);
- if (user.isManagedProfile() && user.isQuietModeEnabled()) {
- mCurrentQuietProfiles.add(user.id);
- }
- }
- }
- }
-
/**
* An optimization to preload the raw list of tasks. The raw tasks are saved in least-recent
* to most-recent order.
*
* Note: Do not lock, callers should synchronize on the loader before making this call.
*/
- void preloadRawTasks(boolean includeFrontMostExcludedTask) {
+ void preloadRawTasks() {
SystemServicesProxy ssp = Recents.getSystemServices();
int currentUserId = ssp.getCurrentUser();
- updateCurrentQuietProfilesCache(currentUserId);
- mPreloadedUserId = currentUserId;
- mRawTasks = ssp.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(),
- currentUserId, includeFrontMostExcludedTask, mCurrentQuietProfiles);
+ mRawTasks = ssp.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(), currentUserId);
// Since the raw tasks are given in most-recent to least-recent order, we need to reverse it
Collections.reverse(mRawTasks);
@@ -124,34 +100,22 @@
*
* The tasks will be ordered by:
* - least-recent to most-recent stack tasks
- * - least-recent to most-recent freeform tasks
*
* Note: Do not lock, since this can be calling back to the loader, which separately also drives
* this call (callers should synchronize on the loader before making this call).
*/
- void preloadPlan(RecentsTaskLoader loader, int runningTaskId,
- boolean includeFrontMostExcludedTask) {
+ void preloadPlan(RecentsTaskLoader loader, int runningTaskId) {
Resources res = mContext.getResources();
ArrayList<Task> allTasks = new ArrayList<>();
if (mRawTasks == null) {
- preloadRawTasks(includeFrontMostExcludedTask);
+ preloadRawTasks();
}
- SparseArray<Task.TaskKey> affiliatedTasks = new SparseArray<>();
- SparseIntArray affiliatedTaskCounts = new SparseIntArray();
SparseBooleanArray lockedUsers = new SparseBooleanArray();
String dismissDescFormat = mContext.getString(
R.string.accessibility_recents_item_will_be_dismissed);
String appInfoDescFormat = mContext.getString(
R.string.accessibility_recents_item_open_app_info);
- int currentUserId = mPreloadedUserId;
- long legacyLastStackActiveTime = migrateLegacyLastStackActiveTime(currentUserId);
- long lastStackActiveTime = Settings.Secure.getLongForUser(mContext.getContentResolver(),
- Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, legacyLastStackActiveTime, currentUserId);
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- lastStackActiveTime = 0;
- }
- long newLastStackActiveTime = -1;
int taskCount = mRawTasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
@@ -159,35 +123,12 @@
// Compose the task key
final int windowingMode = t.configuration.windowConfiguration.getWindowingMode();
Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, windowingMode, t.baseIntent,
- t.userId, t.firstActiveTime, t.lastActiveTime);
+ t.userId, t.lastActiveTime);
- // This task is only shown in the stack if it satisfies the historical time or min
- // number of tasks constraints. Freeform tasks are also always shown.
boolean isFreeformTask = windowingMode == WINDOWING_MODE_FREEFORM;
- boolean isStackTask;
- if (Recents.getConfiguration().isGridEnabled) {
- // When grid layout is enabled, we only show the first
- // TaskGridLayoutAlgorithm.MAX_LAYOUT_FROM_HOME_TASK_COUNT} tasks.
- isStackTask = t.lastActiveTime >= lastStackActiveTime &&
- i >= taskCount - TaskGridLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT;
- } else if (Recents.getConfiguration().isLowRamDevice) {
- // Show a max of 3 items
- isStackTask = t.lastActiveTime >= lastStackActiveTime &&
- i >= taskCount - TaskStackLowRamLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT;
- } else {
- isStackTask = isFreeformTask || !isHistoricalTask(t) ||
- (t.lastActiveTime >= lastStackActiveTime && i >= (taskCount - MIN_NUM_TASKS));
- }
+ boolean isStackTask = !isFreeformTask;
boolean isLaunchTarget = taskKey.id == runningTaskId;
- // The last stack active time is the baseline for which we show visible tasks. Since
- // the system will store all the tasks, we don't want to show the tasks prior to the
- // last visible ones, otherwise, as you dismiss them, the previous tasks may satisfy
- // the other stack-task constraints.
- if (isStackTask && newLastStackActiveTime < 0) {
- newLastStackActiveTime = t.lastActiveTime;
- }
-
// Load the title, icon, and color
ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey);
String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
@@ -210,24 +151,18 @@
boolean isLocked = lockedUsers.get(t.userId);
// Add the task to the stack
- Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
+ Task task = new Task(taskKey, icon,
thumbnail, title, titleDescription, dismissDescription, appInfoDescription,
activityColor, backgroundColor, isLaunchTarget, isStackTask, isSystemApp,
- t.supportsSplitScreenMultiWindow, t.bounds, t.taskDescription, t.resizeMode, t.topActivity,
- isLocked);
+ t.supportsSplitScreenMultiWindow, t.taskDescription, t.resizeMode,
+ t.topActivity, isLocked);
allTasks.add(task);
- affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
- affiliatedTasks.put(taskKey.id, taskKey);
- }
- if (newLastStackActiveTime != -1) {
- Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
- newLastStackActiveTime, currentUserId);
}
// Initialize the stacks
mStack = new TaskStack();
- mStack.setTasks(mContext, allTasks, false /* notifyStackChanges */);
+ mStack.setTasks(allTasks, false /* notifyStackChanges */);
}
/**
@@ -289,42 +224,4 @@
}
return false;
}
-
- /**
- * Returns whether this task is too old to be shown.
- */
- private boolean isHistoricalTask(ActivityManager.RecentTaskInfo t) {
- return t.lastActiveTime < (System.currentTimeMillis() - SESSION_BEGIN_TIME);
- }
-
-
- /**
- * Migrate the last active time from the prefs to the secure settings.
- *
- * The first time this runs, it will:
- * 1) fetch the last stack active time from the prefs
- * 2) set the prefs to the last stack active time for all users
- * 3) clear the pref
- * 4) return the last stack active time
- *
- * Subsequent calls to this will return zero.
- */
- private long migrateLegacyLastStackActiveTime(int currentUserId) {
- long legacyLastStackActiveTime = Prefs.getLong(mContext,
- Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, -1);
- if (legacyLastStackActiveTime != -1) {
- Prefs.remove(mContext, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME);
- UserManager userMgr = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- List<UserInfo> users = userMgr.getUsers();
- for (int i = 0; i < users.size(); i++) {
- int userId = users.get(i).id;
- if (userId != currentUserId) {
- Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
- legacyLastStackActiveTime, userId);
- }
- }
- return legacyLastStackActiveTime;
- }
- return 0;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 1b89386..94558c3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -337,18 +337,11 @@
return plan;
}
- /** Preloads raw recents tasks using the specified plan to store the output. */
- public synchronized void preloadRawTasks(RecentsTaskLoadPlan plan,
- boolean includeFrontMostExcludedTask) {
- plan.preloadRawTasks(includeFrontMostExcludedTask);
- }
-
/** Preloads recents tasks using the specified plan to store the output. */
- public synchronized void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId,
- boolean includeFrontMostExcludedTask) {
+ public synchronized void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId) {
try {
Trace.beginSection("preloadPlan");
- plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
+ plan.preloadPlan(this, runningTaskId);
} finally {
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index abdb5cb..ae417c0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import android.app.ActivityManager;
+import android.app.ActivityManager.TaskDescription;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -69,13 +70,11 @@
private int mHashCode;
- public TaskKey(int id, int windowingMode, Intent intent, int userId, long firstActiveTime,
- long lastActiveTime) {
+ public TaskKey(int id, int windowingMode, Intent intent, int userId, long lastActiveTime) {
this.id = id;
this.windowingMode = windowingMode;
this.baseIntent = intent;
this.userId = userId;
- this.firstActiveTime = firstActiveTime;
this.lastActiveTime = lastActiveTime;
updateHashCode();
}
@@ -125,20 +124,6 @@
public int temporarySortIndexInStack;
/**
- * The group will be computed separately from the initialization of the task
- */
- @ViewDebug.ExportedProperty(deepExport=true, prefix="group_")
- public TaskGrouping group;
- /**
- * The affiliationTaskId is the task id of the parent task or itself if it is not affiliated
- * with any task.
- */
- @ViewDebug.ExportedProperty(category="recents")
- public int affiliationTaskId;
- @ViewDebug.ExportedProperty(category="recents")
- public int affiliationColor;
-
- /**
* The icon is the task description icon (if provided), which falls back to the activity icon,
* which can then fall back to the application icon.
*/
@@ -160,15 +145,9 @@
public boolean useLightOnPrimaryColor;
/**
- * The bounds of the task, used only if it is a freeform task.
- */
- @ViewDebug.ExportedProperty(category="recents")
- public Rect bounds;
-
- /**
* The task description for this task, only used to reload task icons.
*/
- public ActivityManager.TaskDescription taskDescription;
+ public TaskDescription taskDescription;
/**
* The state isLaunchTarget will be set for the correct task upon launching Recents.
@@ -200,28 +179,22 @@
// Do nothing
}
- public Task(TaskKey key, int affiliationTaskId, int affiliationColor, Drawable icon,
- ThumbnailData thumbnail, String title, String titleDescription,
- String dismissDescription, String appInfoDescription, int colorPrimary,
- int colorBackground, boolean isLaunchTarget, boolean isStackTask, boolean isSystemApp,
- boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription,
+ public Task(TaskKey key, Drawable icon, ThumbnailData thumbnail, String title,
+ String titleDescription, String dismissDescription, String appInfoDescription,
+ int colorPrimary, int colorBackground, boolean isLaunchTarget, boolean isStackTask,
+ boolean isSystemApp, boolean isDockable, TaskDescription taskDescription,
int resizeMode, ComponentName topActivity, boolean isLocked) {
- boolean isInAffiliationGroup = (affiliationTaskId != key.id);
- boolean hasAffiliationGroupColor = isInAffiliationGroup && (affiliationColor != 0);
this.key = key;
- this.affiliationTaskId = affiliationTaskId;
- this.affiliationColor = affiliationColor;
this.icon = icon;
this.thumbnail = thumbnail;
this.title = title;
this.titleDescription = titleDescription;
this.dismissDescription = dismissDescription;
this.appInfoDescription = appInfoDescription;
- this.colorPrimary = hasAffiliationGroupColor ? affiliationColor : colorPrimary;
+ this.colorPrimary = colorPrimary;
this.colorBackground = colorBackground;
this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
Color.WHITE) > 3f;
- this.bounds = bounds;
this.taskDescription = taskDescription;
this.isLaunchTarget = isLaunchTarget;
this.isStackTask = isStackTask;
@@ -237,9 +210,6 @@
*/
public void copyFrom(Task o) {
this.key = o.key;
- this.group = o.group;
- this.affiliationTaskId = o.affiliationTaskId;
- this.affiliationColor = o.affiliationColor;
this.icon = o.icon;
this.thumbnail = o.thumbnail;
this.title = o.title;
@@ -249,7 +219,6 @@
this.colorPrimary = o.colorPrimary;
this.colorBackground = o.colorBackground;
this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
- this.bounds = o.bounds;
this.taskDescription = o.taskDescription;
this.isLaunchTarget = o.isLaunchTarget;
this.isStackTask = o.isStackTask;
@@ -276,11 +245,6 @@
mCallbacks.remove(cb);
}
- /** Set the grouping */
- public void setGroup(TaskGrouping group) {
- this.group = group;
- }
-
/** Updates the task's windowing mode. */
public void setWindowingMode(int windowingMode) {
key.setWindowingMode(windowingMode);
@@ -290,14 +254,6 @@
}
}
- /**
- * Returns whether this task is on the freeform task stack.
- */
- public boolean isFreeformTask() {
- SystemServicesProxy ssp = Recents.getSystemServices();
- return ssp.hasFreeformWorkspaceSupport() && key.windowingMode == WINDOWING_MODE_FREEFORM;
- }
-
/** Notifies the callback listeners that this task has been loaded */
public void notifyTaskDataLoaded(ThumbnailData thumbnailData, Drawable applicationIcon) {
this.icon = applicationIcon;
@@ -318,13 +274,6 @@
}
/**
- * Returns whether this task is affiliated with another task.
- */
- public boolean isAffiliatedTask() {
- return key.id != affiliationTaskId;
- }
-
- /**
* Returns the top activity component.
*/
public ComponentName getTopComponent() {
@@ -347,18 +296,12 @@
public void dump(String prefix, PrintWriter writer) {
writer.print(prefix); writer.print(key);
- if (isAffiliatedTask()) {
- writer.print(" "); writer.print("affTaskId=" + affiliationTaskId);
- }
if (!isDockable) {
writer.print(" dockable=N");
}
if (isLaunchTarget) {
writer.print(" launchTarget=Y");
}
- if (isFreeformTask()) {
- writer.print(" freeform=Y");
- }
if (isLocked) {
writer.print(" locked=Y");
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskGrouping.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskGrouping.java
deleted file mode 100644
index 2109376..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskGrouping.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.android.systemui.recents.model;
-
-import android.util.ArrayMap;
-
-import java.util.ArrayList;
-
-/** Represents a grouping of tasks witihin a stack. */
-public class TaskGrouping {
-
- int affiliation;
- long latestActiveTimeInGroup;
-
- Task.TaskKey mFrontMostTaskKey;
- ArrayList<Task.TaskKey> mTaskKeys = new ArrayList<Task.TaskKey>();
- ArrayMap<Task.TaskKey, Integer> mTaskKeyIndices = new ArrayMap<>();
-
- /** Creates a group with a specified affiliation. */
- public TaskGrouping(int affiliation) {
- this.affiliation = affiliation;
- }
-
- /** Adds a new task to this group. */
- void addTask(Task t) {
- mTaskKeys.add(t.key);
- if (t.key.lastActiveTime > latestActiveTimeInGroup) {
- latestActiveTimeInGroup = t.key.lastActiveTime;
- }
- t.setGroup(this);
- updateTaskIndices();
- }
-
- /** Removes a task from this group. */
- void removeTask(Task t) {
- mTaskKeys.remove(t.key);
- latestActiveTimeInGroup = 0;
- int taskCount = mTaskKeys.size();
- for (int i = 0; i < taskCount; i++) {
- long lastActiveTime = mTaskKeys.get(i).lastActiveTime;
- if (lastActiveTime > latestActiveTimeInGroup) {
- latestActiveTimeInGroup = lastActiveTime;
- }
- }
- t.setGroup(null);
- updateTaskIndices();
- }
-
- /** Returns the key of the next task in the group. */
- public Task.TaskKey getNextTaskInGroup(Task t) {
- int i = indexOf(t);
- if ((i + 1) < getTaskCount()) {
- return mTaskKeys.get(i + 1);
- }
- return null;
- }
-
- /** Returns the key of the previous task in the group. */
- public Task.TaskKey getPrevTaskInGroup(Task t) {
- int i = indexOf(t);
- if ((i - 1) >= 0) {
- return mTaskKeys.get(i - 1);
- }
- return null;
- }
-
- /** Gets the front task */
- public boolean isFrontMostTask(Task t) {
- return (t.key == mFrontMostTaskKey);
- }
-
- /** Finds the index of a given task in a group. */
- public int indexOf(Task t) {
- return mTaskKeyIndices.get(t.key);
- }
-
- /** Returns whether a task is in this grouping. */
- public boolean containsTask(Task t) {
- return mTaskKeyIndices.containsKey(t.key);
- }
-
- /** Returns whether one task is above another in the group. If they are not in the same group,
- * this returns false. */
- public boolean isTaskAboveTask(Task t, Task below) {
- return mTaskKeyIndices.containsKey(t.key) && mTaskKeyIndices.containsKey(below.key) &&
- mTaskKeyIndices.get(t.key) > mTaskKeyIndices.get(below.key);
- }
-
- /** Returns the number of tasks in this group. */
- public int getTaskCount() { return mTaskKeys.size(); }
-
- /** Updates the mapping of tasks to indices. */
- private void updateTaskIndices() {
- if (mTaskKeys.isEmpty()) {
- mFrontMostTaskKey = null;
- mTaskKeyIndices.clear();
- return;
- }
-
- int taskCount = mTaskKeys.size();
- mFrontMostTaskKey = mTaskKeys.get(mTaskKeys.size() - 1);
- mTaskKeyIndices.clear();
- for (int i = 0; i < taskCount; i++) {
- Task.TaskKey k = mTaskKeys.get(i);
- mTaskKeyIndices.put(k, i);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index fdae917..32e62cf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -18,8 +18,6 @@
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
@@ -52,8 +50,6 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsDebugFlags;
-import com.android.systemui.recents.misc.NamedCounter;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.views.AnimationProps;
@@ -64,10 +60,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
-import java.util.Random;
/**
@@ -75,7 +68,7 @@
*/
interface TaskFilter {
/** Returns whether the filter accepts the specified task */
- public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index);
+ boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index);
}
/**
@@ -85,7 +78,7 @@
ArrayList<Task> mTasks = new ArrayList<>();
ArrayList<Task> mFilteredTasks = new ArrayList<>();
- ArrayMap<Task.TaskKey, Integer> mTaskIndices = new ArrayMap<>();
+ ArrayMap<Task.TaskKey, Integer> mFilteredTaskIndices = new ArrayMap<>();
TaskFilter mFilter;
/** Sets the task filter, saving the current touch state */
@@ -112,25 +105,6 @@
updateFilteredTasks();
}
- /**
- * Moves the given task.
- */
- public void setTaskWindowingMode(Task task, int insertIndex, int windowingMode) {
- int taskIndex = indexOf(task);
- if (taskIndex != insertIndex) {
- mTasks.remove(taskIndex);
- if (taskIndex < insertIndex) {
- insertIndex--;
- }
- mTasks.add(insertIndex, task);
- }
-
- // Update the stack id now, after we've moved the task, and before we update the
- // filtered tasks
- task.setWindowingMode(windowingMode);
- updateFilteredTasks();
- }
-
/** Sets the list of tasks */
void set(List<Task> tasks) {
mTasks.clear();
@@ -150,8 +124,8 @@
/** Returns the index of this task in the list of filtered tasks */
int indexOf(Task t) {
- if (t != null && mTaskIndices.containsKey(t.key)) {
- return mTaskIndices.get(t.key);
+ if (t != null && mFilteredTaskIndices.containsKey(t.key)) {
+ return mFilteredTaskIndices.get(t.key);
}
return -1;
}
@@ -163,7 +137,7 @@
/** Returns whether the filtered list contains this task */
boolean contains(Task t) {
- return mTaskIndices.containsKey(t.key);
+ return mFilteredTaskIndices.containsKey(t.key);
}
/** Updates the list of filtered tasks whenever the base task list changes */
@@ -193,18 +167,13 @@
/** Updates the mapping of tasks to indices. */
private void updateFilteredTaskIndices() {
int taskCount = mFilteredTasks.size();
- mTaskIndices.clear();
+ mFilteredTaskIndices.clear();
for (int i = 0; i < taskCount; i++) {
Task t = mFilteredTasks.get(i);
- mTaskIndices.put(t.key, i);
+ mFilteredTaskIndices.put(t.key, i);
}
}
- /** Returns whether this task list is filtered */
- boolean hasFilter() {
- return (mFilter != null);
- }
-
/** Returns the list of filtered tasks */
ArrayList<Task> getTasks() {
return mFilteredTasks;
@@ -541,45 +510,15 @@
}
}
- // A comparator that sorts tasks by their freeform state
- private Comparator<Task> FREEFORM_COMPARATOR = new Comparator<Task>() {
- @Override
- public int compare(Task o1, Task o2) {
- if (o1.isFreeformTask() && !o2.isFreeformTask()) {
- return 1;
- } else if (o2.isFreeformTask() && !o1.isFreeformTask()) {
- return -1;
- }
- return Long.compare(o1.temporarySortIndexInStack, o2.temporarySortIndexInStack);
- }
- };
-
-
- // The task offset to apply to a task id as a group affiliation
- static final int IndividualTaskIdOffset = 1 << 16;
-
ArrayList<Task> mRawTaskList = new ArrayList<>();
FilteredTaskList mStackTaskList = new FilteredTaskList();
TaskStackCallbacks mCb;
- ArrayList<TaskGrouping> mGroups = new ArrayList<>();
- ArrayMap<Integer, TaskGrouping> mAffinitiesGroups = new ArrayMap<>();
-
public TaskStack() {
- // Ensure that we only show non-docked tasks
+ // Ensure that we only show stack tasks
mStackTaskList.setFilter(new TaskFilter() {
@Override
public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) {
- if (RecentsDebugFlags.Static.EnableAffiliatedTaskGroups) {
- if (t.isAffiliatedTask()) {
- // If this task is affiliated with another parent in the stack, then the
- // historical state of this task depends on the state of the parent task
- Task parentTask = taskIdMap.get(t.affiliationTaskId);
- if (parentTask != null) {
- t = parentTask;
- }
- }
- }
return t.isStackTask;
}
});
@@ -590,41 +529,6 @@
mCb = cb;
}
- /** Sets the windowing mode for a given task. */
- public void setTaskWindowingMode(Task task, int windowingMode) {
- // Find the index to insert into
- ArrayList<Task> taskList = mStackTaskList.getTasks();
- int taskCount = taskList.size();
- if (!task.isFreeformTask() && (windowingMode == WINDOWING_MODE_FREEFORM)) {
- // Insert freeform tasks at the front
- mStackTaskList.setTaskWindowingMode(task, taskCount, windowingMode);
- } else if (task.isFreeformTask() && (windowingMode == WINDOWING_MODE_FULLSCREEN)) {
- // Insert after the first stacked task
- int insertIndex = 0;
- for (int i = taskCount - 1; i >= 0; i--) {
- if (!taskList.get(i).isFreeformTask()) {
- insertIndex = i + 1;
- break;
- }
- }
- mStackTaskList.setTaskWindowingMode(task, insertIndex, windowingMode);
- }
- }
-
- /** Does the actual work associated with removing the task. */
- void removeTaskImpl(FilteredTaskList taskList, Task t) {
- // Remove the task from the list
- taskList.remove(t);
- // Remove it from the group as well, and if it is empty, remove the group
- TaskGrouping group = t.group;
- if (group != null) {
- group.removeTask(t);
- if (group.getTaskCount() == 0) {
- removeGroup(group);
- }
- }
- }
-
/**
* Removes a task from the stack, with an additional {@param animation} hint to the callbacks on
* how they should update themselves.
@@ -640,8 +544,8 @@
public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture,
boolean dismissRecentsIfAllRemoved) {
if (mStackTaskList.contains(t)) {
- removeTaskImpl(mStackTaskList, t);
- Task newFrontMostTask = getStackFrontMostTask(false /* includeFreeform */);
+ mStackTaskList.remove(t);
+ Task newFrontMostTask = getStackFrontMostTask();
if (mCb != null) {
// Notify that a task has been removed
mCb.onStackTaskRemoved(this, t, newFrontMostTask, animation,
@@ -658,7 +562,7 @@
ArrayList<Task> tasks = mStackTaskList.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task t = tasks.get(i);
- removeTaskImpl(mStackTaskList, t);
+ mStackTaskList.remove(t);
mRawTaskList.remove(t);
}
if (mCb != null && notifyStackChanges) {
@@ -669,10 +573,10 @@
/**
- * @see #setTasks(Context, List, boolean, boolean)
+ * @see #setTasks(List, boolean)
*/
- public void setTasks(Context context, TaskStack stack, boolean notifyStackChanges) {
- setTasks(context, stack.mRawTaskList, notifyStackChanges);
+ public void setTasks(TaskStack stack, boolean notifyStackChanges) {
+ setTasks(stack.mRawTaskList, notifyStackChanges);
}
/**
@@ -681,7 +585,7 @@
* @param tasks the new set of tasks to replace the current set.
* @param notifyStackChanges whether or not to callback on specific changes to the list of tasks.
*/
- public void setTasks(Context context, List<Task> tasks, boolean notifyStackChanges) {
+ public void setTasks(List<Task> tasks, boolean notifyStackChanges) {
// Compute a has set for each of the tasks
ArrayMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList);
ArrayMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks);
@@ -703,7 +607,6 @@
removedTasks.add(task);
}
}
- task.setGroup(null);
}
// Add any new tasks
@@ -726,17 +629,13 @@
for (int i = allTasks.size() - 1; i >= 0; i--) {
allTasks.get(i).temporarySortIndexInStack = i;
}
- Collections.sort(allTasks, FREEFORM_COMPARATOR);
mStackTaskList.set(allTasks);
mRawTaskList = allTasks;
- // Update the affiliated groupings
- createAffiliatedGroupings(context);
-
// Only callback for the removed tasks after the stack has updated
int removedTaskCount = removedTasks.size();
- Task newFrontMostTask = getStackFrontMostTask(false);
+ Task newFrontMostTask = getStackFrontMostTask();
for (int i = 0; i < removedTaskCount; i++) {
mCb.onStackTaskRemoved(this, removedTasks.get(i), newFrontMostTask,
AnimationProps.IMMEDIATE, false /* fromDockGesture */,
@@ -758,18 +657,12 @@
/**
* Gets the front-most task in the stack.
*/
- public Task getStackFrontMostTask(boolean includeFreeformTasks) {
+ public Task getStackFrontMostTask() {
ArrayList<Task> stackTasks = mStackTaskList.getTasks();
if (stackTasks.isEmpty()) {
return null;
}
- for (int i = stackTasks.size() - 1; i >= 0; i--) {
- Task task = stackTasks.get(i);
- if (!task.isFreeformTask() || includeFreeformTasks) {
- return task;
- }
- }
- return null;
+ return stackTasks.get(stackTasks.size() - 1);
}
/** Gets the task keys */
@@ -792,22 +685,6 @@
}
/**
- * Returns the set of "freeform" tasks in the stack.
- */
- public ArrayList<Task> getFreeformTasks() {
- ArrayList<Task> freeformTasks = new ArrayList<>();
- ArrayList<Task> tasks = mStackTaskList.getTasks();
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task task = tasks.get(i);
- if (task.isFreeformTask()) {
- freeformTasks.add(task);
- }
- }
- return freeformTasks;
- }
-
- /**
* Computes a set of all the active and historical tasks.
*/
public ArrayList<Task> computeAllTasksList() {
@@ -817,7 +694,7 @@
}
/**
- * Returns the number of stack and freeform tasks.
+ * Returns the number of stacktasks.
*/
public int getTaskCount() {
return mStackTaskList.size();
@@ -827,32 +704,7 @@
* Returns the number of stack tasks.
*/
public int getStackTaskCount() {
- ArrayList<Task> tasks = mStackTaskList.getTasks();
- int stackCount = 0;
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task task = tasks.get(i);
- if (!task.isFreeformTask()) {
- stackCount++;
- }
- }
- return stackCount;
- }
-
- /**
- * Returns the number of freeform tasks.
- */
- public int getFreeformTaskCount() {
- ArrayList<Task> tasks = mStackTaskList.getTasks();
- int freeformCount = 0;
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task task = tasks.get(i);
- if (task.isFreeformTask()) {
- freeformCount++;
- }
- }
- return freeformCount;
+ return mStackTaskList.size();
}
/**
@@ -930,143 +782,7 @@
}
return null;
}
-
- /******** Grouping ********/
-
- /** Adds a group to the set */
- public void addGroup(TaskGrouping group) {
- mGroups.add(group);
- mAffinitiesGroups.put(group.affiliation, group);
- }
-
- public void removeGroup(TaskGrouping group) {
- mGroups.remove(group);
- mAffinitiesGroups.remove(group.affiliation);
- }
-
- /** Returns the group with the specified affiliation. */
- public TaskGrouping getGroupWithAffiliation(int affiliation) {
- return mAffinitiesGroups.get(affiliation);
- }
-
- /**
- * Temporary: This method will simulate affiliation groups
- */
- void createAffiliatedGroupings(Context context) {
- mGroups.clear();
- mAffinitiesGroups.clear();
-
- if (RecentsDebugFlags.Static.EnableMockTaskGroups) {
- ArrayMap<Task.TaskKey, Task> taskMap = new ArrayMap<>();
- // Sort all tasks by increasing firstActiveTime of the task
- ArrayList<Task> tasks = mStackTaskList.getTasks();
- Collections.sort(tasks, new Comparator<Task>() {
- @Override
- public int compare(Task task, Task task2) {
- return Long.compare(task.key.firstActiveTime, task2.key.firstActiveTime);
- }
- });
- // Create groups when sequential packages are the same
- NamedCounter counter = new NamedCounter("task-group", "");
- int taskCount = tasks.size();
- String prevPackage = "";
- int prevAffiliation = -1;
- Random r = new Random();
- int groupCountDown = RecentsDebugFlags.Static.MockTaskGroupsTaskCount;
- for (int i = 0; i < taskCount; i++) {
- Task t = tasks.get(i);
- String packageName = t.key.getComponent().getPackageName();
- packageName = "pkg";
- TaskGrouping group;
- if (packageName.equals(prevPackage) && groupCountDown > 0) {
- group = getGroupWithAffiliation(prevAffiliation);
- groupCountDown--;
- } else {
- int affiliation = IndividualTaskIdOffset + t.key.id;
- group = new TaskGrouping(affiliation);
- addGroup(group);
- prevAffiliation = affiliation;
- prevPackage = packageName;
- groupCountDown = RecentsDebugFlags.Static.MockTaskGroupsTaskCount;
- }
- group.addTask(t);
- taskMap.put(t.key, t);
- }
- // Sort groups by increasing latestActiveTime of the group
- Collections.sort(mGroups, new Comparator<TaskGrouping>() {
- @Override
- public int compare(TaskGrouping taskGrouping, TaskGrouping taskGrouping2) {
- return Long.compare(taskGrouping.latestActiveTimeInGroup,
- taskGrouping2.latestActiveTimeInGroup);
- }
- });
- // Sort group tasks by increasing firstActiveTime of the task, and also build a new list
- // of tasks
- int taskIndex = 0;
- int groupCount = mGroups.size();
- for (int i = 0; i < groupCount; i++) {
- TaskGrouping group = mGroups.get(i);
- Collections.sort(group.mTaskKeys, new Comparator<Task.TaskKey>() {
- @Override
- public int compare(Task.TaskKey taskKey, Task.TaskKey taskKey2) {
- return Long.compare(taskKey.firstActiveTime, taskKey2.firstActiveTime);
- }
- });
- ArrayList<Task.TaskKey> groupTasks = group.mTaskKeys;
- int groupTaskCount = groupTasks.size();
- for (int j = 0; j < groupTaskCount; j++) {
- tasks.set(taskIndex, taskMap.get(groupTasks.get(j)));
- taskIndex++;
- }
- }
- mStackTaskList.set(tasks);
- } else {
- // Create the task groups
- ArrayMap<Task.TaskKey, Task> tasksMap = new ArrayMap<>();
- ArrayList<Task> tasks = mStackTaskList.getTasks();
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task t = tasks.get(i);
- TaskGrouping group;
- if (RecentsDebugFlags.Static.EnableAffiliatedTaskGroups) {
- int affiliation = t.affiliationTaskId > 0 ? t.affiliationTaskId :
- IndividualTaskIdOffset + t.key.id;
- if (mAffinitiesGroups.containsKey(affiliation)) {
- group = getGroupWithAffiliation(affiliation);
- } else {
- group = new TaskGrouping(affiliation);
- addGroup(group);
- }
- } else {
- group = new TaskGrouping(t.key.id);
- addGroup(group);
- }
- group.addTask(t);
- tasksMap.put(t.key, t);
- }
- // Update the task colors for each of the groups
- float minAlpha = context.getResources().getFloat(
- R.dimen.recents_task_affiliation_color_min_alpha_percentage);
- int taskGroupCount = mGroups.size();
- for (int i = 0; i < taskGroupCount; i++) {
- TaskGrouping group = mGroups.get(i);
- taskCount = group.getTaskCount();
- // Ignore the groups that only have one task
- if (taskCount <= 1) continue;
- // Calculate the group color distribution
- int affiliationColor = tasksMap.get(group.mTaskKeys.get(0)).affiliationColor;
- float alphaStep = (1f - minAlpha) / taskCount;
- float alpha = 1f;
- for (int j = 0; j < taskCount; j++) {
- Task t = tasksMap.get(group.mTaskKeys.get(j));
- t.colorPrimary = Utilities.getColorWithOverlay(affiliationColor, Color.WHITE,
- alpha);
- alpha -= alphaStep;
- }
- }
- }
- }
-
+
/**
* Computes the components of tasks in this stack that have been removed as a result of a change
* in the specified package.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
deleted file mode 100644
index 035c058..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.content.Context;
-import android.graphics.RectF;
-import android.util.ArrayMap;
-
-import com.android.systemui.R;
-import com.android.systemui.recents.model.Task;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * The layout logic for the contents of the freeform workspace.
- */
-public class FreeformWorkspaceLayoutAlgorithm {
-
- // Optimization, allows for quick lookup of task -> rect
- private ArrayMap<Task.TaskKey, RectF> mTaskRectMap = new ArrayMap<>();
-
- private int mTaskPadding;
-
- public FreeformWorkspaceLayoutAlgorithm(Context context) {
- reloadOnConfigurationChange(context);
- }
-
- /**
- * Reloads the layout for the current configuration.
- */
- public void reloadOnConfigurationChange(Context context) {
- // This is applied to the edges of each task
- mTaskPadding = context.getResources().getDimensionPixelSize(
- R.dimen.recents_freeform_layout_task_padding) / 2;
- }
-
- /**
- * Updates the layout for each of the freeform workspace tasks. This is called after the stack
- * layout is updated.
- */
- public void update(List<Task> freeformTasks, TaskStackLayoutAlgorithm stackLayout) {
- Collections.reverse(freeformTasks);
- mTaskRectMap.clear();
-
- int numFreeformTasks = stackLayout.mNumFreeformTasks;
- if (!freeformTasks.isEmpty()) {
-
- // Normalize the widths so that we can calculate the best layout below
- int workspaceWidth = stackLayout.mFreeformRect.width();
- int workspaceHeight = stackLayout.mFreeformRect.height();
- float normalizedWorkspaceWidth = (float) workspaceWidth / workspaceHeight;
- float normalizedWorkspaceHeight = 1f;
- float[] normalizedTaskWidths = new float[numFreeformTasks];
- for (int i = 0; i < numFreeformTasks; i++) {
- Task task = freeformTasks.get(i);
- float rowTaskWidth;
- if (task.bounds != null) {
- rowTaskWidth = (float) task.bounds.width() / task.bounds.height();
- } else {
- // If this is a stack task that was dragged into the freeform workspace, then
- // the task will not yet have an associated bounds, so assume the full workspace
- // width for the time being
- rowTaskWidth = normalizedWorkspaceWidth;
- }
- // Bound the task width to the workspace width so that at the worst case, it will
- // fit its own row
- normalizedTaskWidths[i] = Math.min(rowTaskWidth, normalizedWorkspaceWidth);
- }
-
- // Determine the scale to best fit each of the tasks in the workspace
- float rowScale = 0.85f;
- float rowWidth = 0f;
- float maxRowWidth = 0f;
- int rowCount = 1;
- for (int i = 0; i < numFreeformTasks;) {
- float width = normalizedTaskWidths[i] * rowScale;
- if (rowWidth + width > normalizedWorkspaceWidth) {
- // That is too long for this row, create new row
- if ((rowCount + 1) * rowScale > normalizedWorkspaceHeight) {
- // The new row is too high, so we need to try fitting again. Update the
- // scale to be the smaller of the scale needed to fit the task in the
- // previous row, or the scale needed to fit the new row
- rowScale = Math.min(normalizedWorkspaceWidth / (rowWidth + width),
- normalizedWorkspaceHeight / (rowCount + 1));
- rowCount = 1;
- rowWidth = 0;
- i = 0;
- } else {
- // The new row fits, so continue
- rowWidth = width;
- rowCount++;
- i++;
- }
- } else {
- // Task is OK in this row
- rowWidth += width;
- i++;
- }
- maxRowWidth = Math.max(rowWidth, maxRowWidth);
- }
-
- // Normalize each of the actual rects to that scale
- float defaultRowLeft = ((1f - (maxRowWidth / normalizedWorkspaceWidth)) *
- workspaceWidth) / 2f;
- float rowLeft = defaultRowLeft;
- float rowTop = ((1f - (rowScale * rowCount)) * workspaceHeight) / 2f;
- float rowHeight = rowScale * workspaceHeight;
- for (int i = 0; i < numFreeformTasks; i++) {
- Task task = freeformTasks.get(i);
- float width = rowHeight * normalizedTaskWidths[i];
- if (rowLeft + width > workspaceWidth) {
- // This goes on the next line
- rowTop += rowHeight;
- rowLeft = defaultRowLeft;
- }
- RectF rect = new RectF(rowLeft, rowTop, rowLeft + width, rowTop + rowHeight);
- rect.inset(mTaskPadding, mTaskPadding);
- rowLeft += width;
- mTaskRectMap.put(task.key, rect);
- }
- }
- }
-
- /**
- * Returns whether the transform is available for the given task.
- */
- public boolean isTransformAvailable(Task task, TaskStackLayoutAlgorithm stackLayout) {
- if (stackLayout.mNumFreeformTasks == 0 || task == null) {
- return false;
- }
- return mTaskRectMap.containsKey(task.key);
- }
-
- /**
- * Returns the transform for the given task. Any rect returned will be offset by the actual
- * transform for the freeform workspace.
- */
- public TaskViewTransform getTransform(Task task, TaskViewTransform transformOut,
- TaskStackLayoutAlgorithm stackLayout) {
- if (mTaskRectMap.containsKey(task.key)) {
- final RectF ffRect = mTaskRectMap.get(task.key);
-
- transformOut.scale = 1f;
- transformOut.alpha = 1f;
- transformOut.translationZ = stackLayout.mMaxTranslationZ;
- transformOut.dimAlpha = 0f;
- transformOut.viewOutlineAlpha = TaskStackLayoutAlgorithm.OUTLINE_ALPHA_MAX_VALUE;
- transformOut.rect.set(ffRect);
- transformOut.rect.offset(stackLayout.mFreeformRect.left, stackLayout.mFreeformRect.top);
- transformOut.visible = true;
- return transformOut;
- }
- return null;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index ee05d81..baa5e62 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -19,7 +19,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -188,20 +187,9 @@
} else {
LaunchTaskStartedEvent launchStartedEvent = new LaunchTaskStartedEvent(taskView,
screenPinningRequested);
- if (task.group != null && !task.group.isFrontMostTask(task)) {
- launchStartedEvent.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- startTaskActivity(stack, task, taskView, opts, transitionFuture,
- windowingMode, activityType);
- }
- });
- EventBus.getDefault().send(launchStartedEvent);
- } else {
- EventBus.getDefault().send(launchStartedEvent);
- startTaskActivity(stack, task, taskView, opts, transitionFuture,
- windowingMode, activityType);
- }
+ EventBus.getDefault().send(launchStartedEvent);
+ startTaskActivity(stack, task, taskView, opts, transitionFuture, windowingMode,
+ activityType);
}
Recents.getSystemServices().sendCloseSystemWindows(
StatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
@@ -329,7 +317,6 @@
// If this is a full screen stack, the transition will be towards the single, full screen
// task. We only need the transition spec for this task.
- List<AppTransitionAnimationSpec> specs = new ArrayList<>();
// TODO: Sometimes targetStackId is not initialized after reboot, so we also have to
// check for INVALID_STACK_ID (now WINDOWING_MODE_UNDEFINED)
@@ -338,6 +325,7 @@
|| windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
|| activityType == ACTIVITY_TYPE_ASSISTANT
|| windowingMode == WINDOWING_MODE_UNDEFINED) {
+ List<AppTransitionAnimationSpec> specs = new ArrayList<>();
if (taskView == null) {
specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
} else {
@@ -351,34 +339,7 @@
}
return specs;
}
-
- // Otherwise, for freeform tasks, create a new animation spec for each task we have to
- // launch
- TaskStack stack = stackView.getStack();
- ArrayList<Task> tasks = stack.getStackTasks();
- int taskCount = tasks.size();
- for (int i = taskCount - 1; i >= 0; i--) {
- Task t = tasks.get(i);
- if (t.isFreeformTask() || windowingMode == WINDOWING_MODE_FREEFORM) {
- TaskView tv = stackView.getChildViewForTask(t);
- if (tv == null) {
- // TODO: Create a different animation task rect for this case (though it should
- // never happen)
- specs.add(composeOffscreenAnimationSpec(t, offscreenTaskRect));
- } else {
- mTmpTransform.fillIn(taskView);
- stackLayout.transformToScreenCoordinates(mTmpTransform,
- null /* windowOverrideRect */);
- AppTransitionAnimationSpec spec = composeAnimationSpec(stackView, tv,
- mTmpTransform, true /* addHeaderBitmap */);
- if (spec != null) {
- specs.add(spec);
- }
- }
- }
- }
-
- return specs;
+ return Collections.emptyList();
}
/**
@@ -462,7 +423,7 @@
// force the task thumbnail to full stackView height immediately causing the transition
// jarring.
if (!Recents.getConfiguration().isLowRamDevice && taskView.getTask() !=
- stackView.getStack().getStackFrontMostTask(false /* includeFreeformTasks */)) {
+ stackView.getStack().getStackFrontMostTask()) {
taskRect.bottom = taskRect.top + stackView.getMeasuredHeight();
}
return new AppTransitionAnimationSpec(taskView.getTask().key.id, b, taskRect);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index c7edb9a..e2f157e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,10 +16,6 @@
package com.android.systemui.recents.views;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.ActivityOptions.OnAnimationStartedListener;
@@ -114,7 +110,6 @@
private final int mStackButtonShadowColor;
private boolean mAwaitingFirstLayout = true;
- private boolean mLastTaskLaunchedWasFreeform;
@ViewDebug.ExportedProperty(category="recents")
Rect mSystemInsets = new Rect();
@@ -232,7 +227,6 @@
// Reset the state
mAwaitingFirstLayout = !isResumingFromVisible;
- mLastTaskLaunchedWasFreeform = false;
// Update the stack
mTaskStackView.onReload(isResumingFromVisible);
@@ -319,13 +313,6 @@
}
}
- /**
- * Returns whether the last task launched was in the freeform stack or not.
- */
- public boolean isLastTaskLaunchedFreeform() {
- return mLastTaskLaunchedWasFreeform;
- }
-
/** Launches the focused task from the first stack if possible */
public boolean launchFocusedTask(int logEvent) {
if (mTaskStackView != null) {
@@ -542,7 +529,6 @@
/**** EventBus Events ****/
public final void onBusEvent(LaunchTaskEvent event) {
- mLastTaskLaunchedWasFreeform = event.task.isFreeformTask();
mTransitionHelper.launchTaskFromRecents(getStack(), event.task, mTaskStackView,
event.taskView, event.screenPinningRequested, event.targetWindowingMode,
event.targetActivityType);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index 81bf6af..f47c1d2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -161,20 +161,12 @@
for (int i = taskViews.size() - 1; i >= 0; i--) {
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- boolean currentTaskOccludesLaunchTarget = launchTargetTask != null &&
- launchTargetTask.group != null &&
- launchTargetTask.group.isTaskAboveTask(task, launchTargetTask);
- boolean hideTask = launchTargetTask != null &&
- launchTargetTask.isFreeformTask() &&
- task.isFreeformTask();
// Get the current transform for the task, which will be used to position it offscreen
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
- if (hideTask) {
- tv.setVisibility(View.INVISIBLE);
- } else if (launchState.launchedFromApp && !launchState.launchedViaDockGesture) {
+ if (launchState.launchedFromApp && !launchState.launchedViaDockGesture) {
if (task.isLaunchTarget) {
tv.onPrepareLaunchTargetForEnterAnimation();
} else if (isLowRamDevice && i >= taskViews.size() -
@@ -195,13 +187,6 @@
// com.android.server.wm.AppTransition#DEFAULT_APP_TRANSITION_DURATION}
mStackView.updateTaskViewToTransform(tv, mTmpTransform,
new AnimationProps(336, Interpolators.FAST_OUT_SLOW_IN));
- } else if (currentTaskOccludesLaunchTarget) {
- // Move the task view slightly lower so we can animate it in
- mTmpTransform.rect.offset(0, taskViewAffiliateGroupEnterOffset);
- mTmpTransform.alpha = 0f;
- mStackView.updateTaskViewToTransform(tv, mTmpTransform,
- AnimationProps.IMMEDIATE);
- tv.setClipViewInStack(false);
}
} else if (launchState.launchedFromHome) {
if (isLowRamDevice) {
@@ -266,9 +251,6 @@
int taskIndexFromBack = i;
final TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- boolean currentTaskOccludesLaunchTarget = launchTargetTask != null &&
- launchTargetTask.group != null &&
- launchTargetTask.group.isTaskAboveTask(task, launchTargetTask);
// Get the current transform for the task, which will be updated to the final transform
// to animate to depending on how recents was invoked
@@ -280,21 +262,6 @@
tv.onStartLaunchTargetEnterAnimation(mTmpTransform,
taskViewEnterFromAppDuration, mStackView.mScreenPinningEnabled,
postAnimationTrigger);
- } else {
- // Animate the task up if it was occluding the launch target
- if (currentTaskOccludesLaunchTarget) {
- AnimationProps taskAnimation = new AnimationProps(
- taskViewEnterFromAffiliatedAppDuration, Interpolators.ALPHA_IN,
- new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- postAnimationTrigger.decrement();
- tv.setClipViewInStack(true);
- }
- });
- postAnimationTrigger.increment();
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- }
}
} else if (launchState.launchedFromHome) {
@@ -423,9 +390,6 @@
for (int i = 0; i < taskViewCount; i++) {
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- boolean currentTaskOccludesLaunchTarget = launchingTask != null &&
- launchingTask.group != null &&
- launchingTask.group.isTaskAboveTask(task, launchingTask);
if (tv == launchingTaskView) {
tv.setClipViewInStack(false);
@@ -437,17 +401,6 @@
});
tv.onStartLaunchTargetLaunchAnimation(taskViewExitToAppDuration,
screenPinningRequested, postAnimationTrigger);
- } else if (currentTaskOccludesLaunchTarget) {
- // Animate this task out of view
- AnimationProps taskAnimation = new AnimationProps(
- taskViewExitToAppDuration, Interpolators.ALPHA_OUT,
- postAnimationTrigger.decrementOnAnimationEnd());
- postAnimationTrigger.increment();
-
- mTmpTransform.fillIn(tv);
- mTmpTransform.alpha = 0f;
- mTmpTransform.rect.offset(0, taskViewAffiliateGroupEnterOffset);
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
}
}
@@ -611,7 +564,7 @@
false /* ignoreTaskOverrides */, mTmpFinalTaskTransforms);
// Hide the front most task view until the scroll is complete
- Task frontMostTask = newStack.getStackFrontMostTask(false /* includeFreeform */);
+ Task frontMostTask = newStack.getStackFrontMostTask();
final TaskView frontMostTaskView = mStackView.getChildViewForTask(frontMostTask);
final TaskViewTransform frontMostTransform = mTmpFinalTaskTransforms.get(
stackTasks.indexOf(frontMostTask));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index eaa32ee..af95b3c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -147,75 +147,6 @@
}
/**
- * The various stack/freeform states.
- */
- public static class StackState {
-
- public static final StackState FREEFORM_ONLY = new StackState(1f, 255);
- public static final StackState STACK_ONLY = new StackState(0f, 0);
- public static final StackState SPLIT = new StackState(0.5f, 255);
-
- public final float freeformHeightPct;
- public final int freeformBackgroundAlpha;
-
- /**
- * @param freeformHeightPct the percentage of the stack height (not including paddings) to
- * allocate to the freeform workspace
- * @param freeformBackgroundAlpha the background alpha for the freeform workspace
- */
- private StackState(float freeformHeightPct, int freeformBackgroundAlpha) {
- this.freeformHeightPct = freeformHeightPct;
- this.freeformBackgroundAlpha = freeformBackgroundAlpha;
- }
-
- /**
- * Resolves the stack state for the layout given a task stack.
- */
- public static StackState getStackStateForStack(TaskStack stack) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- boolean hasFreeformWorkspaces = ssp.hasFreeformWorkspaceSupport();
- int freeformCount = stack.getFreeformTaskCount();
- int stackCount = stack.getStackTaskCount();
- if (hasFreeformWorkspaces && stackCount > 0 && freeformCount > 0) {
- return SPLIT;
- } else if (hasFreeformWorkspaces && freeformCount > 0) {
- return FREEFORM_ONLY;
- } else {
- return STACK_ONLY;
- }
- }
-
- /**
- * Computes the freeform and stack rect for this state.
- *
- * @param freeformRectOut the freeform rect to be written out
- * @param stackRectOut the stack rect, we only write out the top of the stack
- * @param taskStackBounds the full rect that the freeform rect can take up
- */
- public void computeRects(Rect freeformRectOut, Rect stackRectOut,
- Rect taskStackBounds, int topMargin, int freeformGap, int stackBottomOffset) {
- // The freeform height is the visible height (not including system insets) - padding
- // above freeform and below stack - gap between the freeform and stack
- int availableHeight = taskStackBounds.height() - topMargin - stackBottomOffset;
- int ffPaddedHeight = (int) (availableHeight * freeformHeightPct);
- int ffHeight = Math.max(0, ffPaddedHeight - freeformGap);
- freeformRectOut.set(taskStackBounds.left,
- taskStackBounds.top + topMargin,
- taskStackBounds.right,
- taskStackBounds.top + topMargin + ffHeight);
- stackRectOut.set(taskStackBounds.left,
- taskStackBounds.top,
- taskStackBounds.right,
- taskStackBounds.bottom);
- if (ffPaddedHeight > 0) {
- stackRectOut.top += ffPaddedHeight;
- } else {
- stackRectOut.top += topMargin;
- }
- }
- }
-
- /**
* @return True if we should use the grid layout.
*/
boolean useGridLayout() {
@@ -234,15 +165,11 @@
}
Context mContext;
- private StackState mState = StackState.SPLIT;
private TaskStackLayoutAlgorithmCallbacks mCb;
// The task bounds (untransformed) for layout. This rect is anchored at mTaskRoot.
@ViewDebug.ExportedProperty(category="recents")
public Rect mTaskRect = new Rect();
- // The freeform workspace bounds, inset by the top system insets and is a fixed height
- @ViewDebug.ExportedProperty(category="recents")
- public Rect mFreeformRect = new Rect();
// The stack bounds, inset from the top system insets, and runs to the bottom of the screen
@ViewDebug.ExportedProperty(category="recents")
public Rect mStackRect = new Rect();
@@ -268,10 +195,6 @@
private int mBaseBottomMargin;
private int mMinMargin;
- // The gap between the freeform and stack layouts
- @ViewDebug.ExportedProperty(category="recents")
- private int mFreeformStackGap;
-
// The initial offset that the focused task is from the top
@ViewDebug.ExportedProperty(category="recents")
private int mInitialTopOffset;
@@ -331,8 +254,6 @@
// The last computed task counts
@ViewDebug.ExportedProperty(category="recents")
int mNumStackTasks;
- @ViewDebug.ExportedProperty(category="recents")
- int mNumFreeformTasks;
// The min/max z translations
@ViewDebug.ExportedProperty(category="recents")
@@ -344,8 +265,6 @@
private SparseIntArray mTaskIndexMap = new SparseIntArray();
private SparseArray<Float> mTaskIndexOverrideMap = new SparseArray<>();
- // The freeform workspace layout
- FreeformWorkspaceLayoutAlgorithm mFreeformLayoutAlgorithm;
TaskGridLayoutAlgorithm mTaskGridLayoutAlgorithm;
TaskStackLowRamLayoutAlgorithm mTaskStackLowRamLayoutAlgorithm;
@@ -356,7 +275,6 @@
public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) {
mContext = context;
mCb = cb;
- mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
mTaskGridLayoutAlgorithm = new TaskGridLayoutAlgorithm(context);
mTaskStackLowRamLayoutAlgorithm = new TaskStackLowRamLayoutAlgorithm(context);
reloadOnConfigurationChange(context);
@@ -393,7 +311,6 @@
R.dimen.recents_layout_initial_bottom_offset_tablet,
R.dimen.recents_layout_initial_bottom_offset_tablet,
R.dimen.recents_layout_initial_bottom_offset_tablet);
- mFreeformLayoutAlgorithm.reloadOnConfigurationChange(context);
mTaskGridLayoutAlgorithm.reloadOnConfigurationChange(context);
mTaskStackLowRamLayoutAlgorithm.reloadOnConfigurationChange(context);
mMinMargin = res.getDimensionPixelSize(R.dimen.recents_layout_min_margin);
@@ -408,8 +325,6 @@
R.dimen.recents_layout_side_margin_tablet_xlarge,
R.dimen.recents_layout_side_margin_tablet);
mBaseBottomMargin = res.getDimensionPixelSize(R.dimen.recents_layout_bottom_margin);
- mFreeformStackGap =
- res.getDimensionPixelSize(R.dimen.recents_freeform_layout_bottom_margin);
mTitleBarHeight = getDimensionForDevice(mContext,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height,
@@ -462,8 +377,7 @@
* Computes the stack and task rects. The given task stack bounds already has the top/right
* insets and left/right padding already applied.
*/
- public void initialize(Rect displayRect, Rect windowRect, Rect taskStackBounds,
- StackState state) {
+ public void initialize(Rect displayRect, Rect windowRect, Rect taskStackBounds) {
Rect lastStackRect = new Rect(mStackRect);
int topMargin = getScaleForExtent(windowRect, displayRect, mBaseTopMargin, mMinMargin, HEIGHT);
@@ -474,10 +388,9 @@
mInitialBottomOffset = mBaseInitialBottomOffset;
// Compute the stack bounds
- mState = state;
mStackBottomOffset = mSystemInsets.bottom + bottomMargin;
- state.computeRects(mFreeformRect, mStackRect, taskStackBounds, topMargin,
- mFreeformStackGap, mStackBottomOffset);
+ mStackRect.set(taskStackBounds);
+ mStackRect.top += topMargin;
// The stack action button will take the full un-padded header space above the stack
mStackActionButtonRect.set(mStackRect.left, mStackRect.top - topMargin,
@@ -530,26 +443,20 @@
if (tasks.isEmpty()) {
mFrontMostTaskP = 0;
mMinScrollP = mMaxScrollP = mInitialScrollP = 0;
- mNumStackTasks = mNumFreeformTasks = 0;
+ mNumStackTasks = 0;
return;
}
- // Filter the set of freeform and stack tasks
- ArrayList<Task> freeformTasks = new ArrayList<>();
+ // Filter the set of stack tasks
ArrayList<Task> stackTasks = new ArrayList<>();
for (int i = 0; i < tasks.size(); i++) {
Task task = tasks.get(i);
if (ignoreTasksSet.contains(task.key)) {
continue;
}
- if (task.isFreeformTask()) {
- freeformTasks.add(task);
- } else {
- stackTasks.add(task);
- }
+ stackTasks.add(task);
}
mNumStackTasks = stackTasks.size();
- mNumFreeformTasks = freeformTasks.size();
// Put each of the tasks in the progress map at a fixed index (does not need to actually
// map to a scroll position, just by index)
@@ -559,11 +466,6 @@
mTaskIndexMap.put(task.key.id, i);
}
- // Update the freeform tasks
- if (!freeformTasks.isEmpty()) {
- mFreeformLayoutAlgorithm.update(freeformTasks, this);
- }
-
// Calculate the min/max/initial scroll
Task launchTask = stack.getLaunchTarget();
int launchTaskIndex = launchTask != null
@@ -582,7 +484,7 @@
} else {
mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
}
- } else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
+ } else if (mNumStackTasks == 1) {
// If there is one stack task, ignore the min/max/initial scroll positions
mMinScrollP = 0;
mMaxScrollP = 0;
@@ -794,13 +696,6 @@
}
/**
- * Returns the current stack state.
- */
- public StackState getStackState() {
- return mState;
- }
-
- /**
* Returns whether this stack layout has been initialized.
*/
public boolean isInitialized() {
@@ -825,62 +720,44 @@
return new VisibilityReport(1, 1);
}
- // Quick return when there are no stack tasks
- if (mNumStackTasks == 0) {
- return new VisibilityReport(mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0,
- mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0);
- }
-
// Otherwise, walk backwards in the stack and count the number of tasks and visible
- // thumbnails and add that to the total freeform task count
+ // thumbnails and add that to the total task count
TaskViewTransform tmpTransform = new TaskViewTransform();
Range currentRange = getInitialFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
currentRange.offset(mInitialScrollP);
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_view_header_height);
- int numVisibleTasks = mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0;
- int numVisibleThumbnails = mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 0) : 0;
+ int numVisibleTasks = 0;
+ int numVisibleThumbnails = 0;
float prevScreenY = Integer.MAX_VALUE;
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
- // Skip freeform
- if (task.isFreeformTask()) {
- continue;
- }
-
// Skip invisible
float taskProgress = getStackScrollForTask(task);
if (!currentRange.isInRange(taskProgress)) {
continue;
}
- boolean isFrontMostTaskInGroup = task.group == null || task.group.isFrontMostTask(task);
- if (isFrontMostTaskInGroup) {
- getStackTransform(taskProgress, taskProgress, mInitialScrollP, mFocusState,
- tmpTransform, null, false /* ignoreSingleTaskCase */,
- false /* forceUpdate */);
- float screenY = tmpTransform.rect.top;
- boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
- if (hasVisibleThumbnail) {
- numVisibleThumbnails++;
- numVisibleTasks++;
- prevScreenY = screenY;
- } else {
- // Once we hit the next front most task that does not have a visible thumbnail,
- // walk through remaining visible set
- for (int j = i; j >= 0; j--) {
- taskProgress = getStackScrollForTask(tasks.get(j));
- if (!currentRange.isInRange(taskProgress)) {
- break;
- }
- numVisibleTasks++;
- }
- break;
- }
- } else {
- // Affiliated task, no thumbnail
+ getStackTransform(taskProgress, taskProgress, mInitialScrollP, mFocusState,
+ tmpTransform, null, false /* ignoreSingleTaskCase */, false /* forceUpdate */);
+ float screenY = tmpTransform.rect.top;
+ boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
+ if (hasVisibleThumbnail) {
+ numVisibleThumbnails++;
numVisibleTasks++;
+ prevScreenY = screenY;
+ } else {
+ // Once we hit the next front most task that does not have a visible thumbnail,
+ // walk through remaining visible set
+ for (int j = i; j >= 0; j--) {
+ taskProgress = getStackScrollForTask(tasks.get(j));
+ if (!currentRange.isInRange(taskProgress)) {
+ break;
+ }
+ numVisibleTasks++;
+ }
+ break;
}
}
return new VisibilityReport(numVisibleTasks, numVisibleThumbnails);
@@ -906,10 +783,7 @@
public TaskViewTransform getStackTransform(Task task, float stackScroll, int focusState,
TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate,
boolean ignoreTaskOverrides) {
- if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
- mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
- return transformOut;
- } else if (useGridLayout()) {
+ if (useGridLayout()) {
int taskIndex = mTaskIndexMap.get(task.key.id);
int taskCount = mTaskIndexMap.size();
mTaskGridLayoutAlgorithm.getTransform(taskIndex, taskCount, transformOut, this);
@@ -1024,7 +898,7 @@
float z;
float dimAlpha;
float viewOutlineAlpha;
- if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1 && !ignoreSingleTaskCase) {
+ if (mNumStackTasks == 1 && !ignoreSingleTaskCase) {
// When there is exactly one task, then decouple the task from the stack and just move
// in screen space
float tmpP = (mMinScrollP - stackScroll) / mNumStackTasks;
@@ -1378,7 +1252,6 @@
writer.print("insets="); writer.print(Utilities.dumpRect(mSystemInsets));
writer.print(" stack="); writer.print(Utilities.dumpRect(mStackRect));
writer.print(" task="); writer.print(Utilities.dumpRect(mTaskRect));
- writer.print(" freeform="); writer.print(Utilities.dumpRect(mFreeformRect));
writer.print(" actionButton="); writer.print(Utilities.dumpRect(mStackActionButtonRect));
writer.println();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 3160ee0..fd29708 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -16,22 +16,15 @@
package com.android.systemui.recents.views;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Canvas;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.provider.Settings;
import android.util.ArrayMap;
@@ -83,13 +76,11 @@
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
-import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragStartInitializeDropTargetsEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
@@ -153,8 +144,6 @@
@ViewDebug.ExportedProperty(deepExport=true, prefix="touch_")
private TaskStackViewTouchHandler mTouchHandler;
private TaskStackAnimationHelper mAnimationHelper;
- private GradientDrawable mFreeformWorkspaceBackground;
- private ObjectAnimator mFreeformWorkspaceBackgroundAnimator;
private ViewPool<TaskView, Task> mViewPool;
private ArrayList<TaskView> mTaskViews = new ArrayList<>();
@@ -239,20 +228,6 @@
}
};
- // The drop targets for a task drag
- private DropTarget mFreeformWorkspaceDropTarget = new DropTarget() {
- @Override
- public boolean acceptsDrop(int x, int y, int width, int height, Rect insets,
- boolean isCurrentTarget) {
- // This drop target has a fixed bounds and should be checked last, so just fall through
- // if it is the current target
- if (!isCurrentTarget) {
- return mLayoutAlgorithm.mFreeformRect.contains(x, y);
- }
- return false;
- }
- };
-
private DropTarget mStackDropTarget = new DropTarget() {
@Override
public boolean acceptsDrop(int x, int y, int width, int height, Rect insets,
@@ -312,17 +287,6 @@
}
});
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- if (ssp.hasFreeformWorkspaceSupport()) {
- setWillNotDraw(false);
- }
-
- mFreeformWorkspaceBackground = (GradientDrawable) getContext().getDrawable(
- R.drawable.recents_freeform_workspace_bg);
- mFreeformWorkspaceBackground.setCallback(this);
- if (ssp.hasFreeformWorkspaceSupport()) {
- mFreeformWorkspaceBackground.setColor(
- getContext().getColor(R.color.recents_freeform_workspace_bg_color));
- }
}
@Override
@@ -359,12 +323,7 @@
readSystemFlags();
mTaskViewsClipDirty = true;
mUIDozeTrigger.stopDozing();
- if (isResumingFromVisible) {
- // Animate in the freeform workspace
- int ffBgAlpha = mLayoutAlgorithm.getStackState().freeformBackgroundAlpha;
- animateFreeformWorkspaceBackgroundAlpha(ffBgAlpha, new AnimationProps(150,
- Interpolators.FAST_OUT_SLOW_IN));
- } else {
+ if (!isResumingFromVisible) {
mStackScroller.reset();
mStableLayoutAlgorithm.reset();
mLayoutAlgorithm.reset();
@@ -387,7 +346,7 @@
// Only notify if we are already initialized, otherwise, everything will pick up all the
// new and old tasks when we next layout
- mStack.setTasks(getContext(), stack, allowNotifyStackChanges && isInitialized);
+ mStack.setTasks(stack, allowNotifyStackChanges && isInitialized);
}
/** Returns the task stack. */
@@ -422,23 +381,13 @@
/**
* Returns the front most task view.
- *
- * @param stackTasksOnly if set, will return the front most task view in the stack (by default
- * the front most task view will be freeform since they are placed above
- * stack tasks)
*/
- private TaskView getFrontMostTaskView(boolean stackTasksOnly) {
+ private TaskView getFrontMostTaskView() {
List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = taskViewCount - 1; i >= 0; i--) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
- if (stackTasksOnly && task.isFreeformTask()) {
- continue;
- }
- return tv;
+ if (taskViews.isEmpty()) {
+ return null;
}
- return null;
+ return taskViews.get(taskViews.size() - 1);
}
/**
@@ -500,8 +449,6 @@
* visible range includes all tasks at the target stack scroll. This is useful for ensure that
* all views necessary for a transition or animation will be visible at the start.
*
- * This call ignores freeform tasks.
- *
* @param taskTransforms The set of task view transforms to reuse, this list will be sized to
* match the size of {@param tasks}
* @param tasks The set of tasks for which to generate transforms
@@ -554,12 +501,6 @@
continue;
}
- // For freeform tasks, only calculate the stack transform and skip the calculation of
- // the visible stack indices
- if (task.isFreeformTask()) {
- continue;
- }
-
frontTransform = transform;
frontTransformAtTarget = transformAtTarget;
if (transform.visible) {
@@ -622,7 +563,7 @@
transform = mCurrentTaskTransforms.get(taskIndex);
}
- if (task.isFreeformTask() || (transform != null && transform.visible)) {
+ if (transform != null && transform.visible) {
mTmpTaskViewMap.put(task.key, tv);
} else {
if (mTouchExplorationEnabled && Utilities.isDescendentAccessibilityFocused(tv)) {
@@ -643,24 +584,20 @@
continue;
}
- // Skip the invisible non-freeform stack tasks
- if (!task.isFreeformTask() && !transform.visible) {
+ // Skip the invisible stack tasks
+ if (!transform.visible) {
continue;
}
TaskView tv = mTmpTaskViewMap.get(task.key);
if (tv == null) {
tv = mViewPool.pickUpViewFromPool(task, task);
- if (task.isFreeformTask()) {
- updateTaskViewToTransform(tv, transform, AnimationProps.IMMEDIATE);
+ if (transform.rect.top <= mLayoutAlgorithm.mStackRect.top) {
+ updateTaskViewToTransform(tv, mLayoutAlgorithm.getBackOfStackTransform(),
+ AnimationProps.IMMEDIATE);
} else {
- if (transform.rect.top <= mLayoutAlgorithm.mStackRect.top) {
- updateTaskViewToTransform(tv, mLayoutAlgorithm.getBackOfStackTransform(),
- AnimationProps.IMMEDIATE);
- } else {
- updateTaskViewToTransform(tv, mLayoutAlgorithm.getFrontOfStackTransform(),
- AnimationProps.IMMEDIATE);
- }
+ updateTaskViewToTransform(tv, mLayoutAlgorithm.getFrontOfStackTransform(),
+ AnimationProps.IMMEDIATE);
}
} else {
// Reattach it in the right z order
@@ -887,13 +824,6 @@
// Compute the min and max scroll values
mLayoutAlgorithm.update(mStack, mIgnoreTasks, launchState);
- // Update the freeform workspace background
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.hasFreeformWorkspaceSupport()) {
- mTmpRect.set(mLayoutAlgorithm.mFreeformRect);
- mFreeformWorkspaceBackground.setBounds(mTmpRect);
- }
-
if (boundScrollToNewMinMax) {
mStackScroller.boundScroll();
}
@@ -906,8 +836,7 @@
mWindowRect.set(mStableWindowRect);
mStackBounds.set(mStableStackBounds);
mLayoutAlgorithm.setSystemInsets(mStableLayoutAlgorithm.mSystemInsets);
- mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds,
- TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
+ mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds);
updateLayoutAlgorithm(true /* boundScroll */);
}
@@ -1028,21 +957,10 @@
if (focusedTask != null) {
if (stackTasksOnly) {
List<Task> tasks = mStack.getStackTasks();
- if (focusedTask.isFreeformTask()) {
- // Try and focus the front most stack task
- TaskView tv = getFrontMostTaskView(stackTasksOnly);
- if (tv != null) {
- newIndex = mStack.indexOfStackTask(tv.getTask());
- }
- } else {
- // Try the next task if it is a stack task
- int tmpNewIndex = newIndex + (forward ? -1 : 1);
- if (0 <= tmpNewIndex && tmpNewIndex < tasks.size()) {
- Task t = tasks.get(tmpNewIndex);
- if (!t.isFreeformTask()) {
- newIndex = tmpNewIndex;
- }
- }
+ // Try the next task if it is a stack task
+ int tmpNewIndex = newIndex + (forward ? -1 : 1);
+ if (0 <= tmpNewIndex && tmpNewIndex < tasks.size()) {
+ newIndex = tmpNewIndex;
}
} else {
// No restrictions, lets just move to the new task (looping forward/backwards if
@@ -1127,7 +1045,7 @@
return tv.getTask();
}
}
- TaskView frontTv = getFrontMostTaskView(true /* stackTasksOnly */);
+ TaskView frontTv = getFrontMostTaskView();
if (frontTv != null) {
return frontTv.getTask();
}
@@ -1278,10 +1196,8 @@
}
// Compute the rects in the stack algorithm
- mStableLayoutAlgorithm.initialize(mDisplayRect, mStableWindowRect, mStableStackBounds,
- TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
- mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds,
- TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
+ mStableLayoutAlgorithm.initialize(mDisplayRect, mStableWindowRect, mStableStackBounds);
+ mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds);
updateLayoutAlgorithm(false /* boundScroll */);
// If this is the first layout, then scroll to the front of the stack, then update the
@@ -1404,11 +1320,6 @@
// Setup the view for the enter animation
mAnimationHelper.prepareForEnterAnimation();
- // Animate in the freeform workspace
- int ffBgAlpha = mLayoutAlgorithm.getStackState().freeformBackgroundAlpha;
- animateFreeformWorkspaceBackgroundAlpha(ffBgAlpha, new AnimationProps(150,
- Interpolators.FAST_OUT_SLOW_IN));
-
// Set the task focused state without requesting view focus, and leave the focus animations
// until after the enter-animation
RecentsConfiguration config = Recents.getConfiguration();
@@ -1456,43 +1367,6 @@
return null;
}
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- // Draw the freeform workspace background
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.hasFreeformWorkspaceSupport()) {
- if (mFreeformWorkspaceBackground.getAlpha() > 0) {
- mFreeformWorkspaceBackground.draw(canvas);
- }
- }
- }
-
- @Override
- protected boolean verifyDrawable(Drawable who) {
- if (who == mFreeformWorkspaceBackground) {
- return true;
- }
- return super.verifyDrawable(who);
- }
-
- /**
- * Launches the freeform tasks.
- */
- public boolean launchFreeformTasks() {
- ArrayList<Task> tasks = mStack.getFreeformTasks();
- if (!tasks.isEmpty()) {
- Task frontTask = tasks.get(tasks.size() - 1);
- if (frontTask != null && frontTask.isFreeformTask()) {
- EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(frontTask),
- frontTask, null, false));
- return true;
- }
- }
- return false;
- }
-
/**** TaskStackCallbacks Implementation ****/
@Override
@@ -1671,8 +1545,7 @@
}
// Restore the action button visibility if it is the front most task view
- if (mScreenPinningEnabled && tv.getTask() ==
- mStack.getStackFrontMostTask(false /* includeFreeform */)) {
+ if (mScreenPinningEnabled && tv.getTask() == mStack.getStackFrontMostTask()) {
tv.showActionButton(false /* fadeIn */, 0 /* fadeInDuration */);
}
}
@@ -1688,7 +1561,6 @@
// If the doze trigger has already fired, then update the state for this task view
if (mUIDozeTrigger.isAsleep() ||
- Recents.getSystemServices().hasFreeformWorkspaceSupport() ||
useGridLayout() || Recents.getConfiguration().isLowRamDevice) {
tv.setNoUserInteractionState();
}
@@ -1820,7 +1692,7 @@
public final void onBusEvent(LaunchMostRecentTaskRequestEvent event) {
if (mStack.getTaskCount() > 0) {
- Task mostRecentTask = mStack.getStackFrontMostTask(true /* includeFreefromTasks */);
+ Task mostRecentTask = mStack.getStackFrontMostTask();
launchTask(mostRecentTask);
}
}
@@ -1891,11 +1763,6 @@
// Start the task animations
mAnimationHelper.startExitToHomeAnimation(event.animated, event.getAnimationTrigger());
- // Dismiss the freeform workspace background
- int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
- animateFreeformWorkspaceBackgroundAlpha(0, new AnimationProps(taskViewExitToHomeDuration,
- Interpolators.FAST_OUT_SLOW_IN));
-
// Dismiss the grid task view focus frame
if (mTaskViewFocusFrame != null) {
mTaskViewFocusFrame.moveGridTaskViewFocus(null);
@@ -2026,11 +1893,6 @@
// Ensure that the drag task is not animated
addIgnoreTask(event.task);
- if (event.task.isFreeformTask()) {
- // Animate to the front of the stack
- mStackScroller.animateScroll(mLayoutAlgorithm.mInitialScrollP, null);
- }
-
// Enlarge the dragged view slightly
float finalScale = event.taskView.getScaleX() * DRAG_SCALE_FACTOR;
mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
@@ -2042,14 +1904,6 @@
new AnimationProps(DRAG_SCALE_DURATION, Interpolators.FAST_OUT_SLOW_IN));
}
- public final void onBusEvent(DragStartInitializeDropTargetsEvent event) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.hasFreeformWorkspaceSupport()) {
- event.handler.registerDropTargetForCurrentDrag(mStackDropTarget);
- event.handler.registerDropTargetForCurrentDrag(mFreeformWorkspaceDropTarget);
- }
- }
-
public final void onBusEvent(DragDropTargetChangedEvent event) {
AnimationProps animation = new AnimationProps(SLOW_SYNC_STACK_DURATION,
Interpolators.FAST_OUT_SLOW_IN);
@@ -2069,8 +1923,7 @@
height, mDividerSize, systemInsets,
mLayoutAlgorithm, getResources(), mWindowRect));
mLayoutAlgorithm.setSystemInsets(systemInsets);
- mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds,
- TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
+ mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds);
updateLayoutAlgorithm(true /* boundScroll */);
ignoreTaskOverrides = true;
} else {
@@ -2092,32 +1945,6 @@
return;
}
- boolean isFreeformTask = event.task.isFreeformTask();
- boolean hasChangedWindowingMode =
- (!isFreeformTask && event.dropTarget == mFreeformWorkspaceDropTarget) ||
- (isFreeformTask && event.dropTarget == mStackDropTarget);
-
- if (hasChangedWindowingMode) {
- // Move the task to the right position in the stack (ie. the front of the stack if
- // freeform or the front of the stack if fullscreen). Note, we MUST move the tasks
- // before we update their stack ids, otherwise, the keys will have changed.
- if (event.dropTarget == mFreeformWorkspaceDropTarget) {
- mStack.setTaskWindowingMode(event.task, WINDOWING_MODE_FREEFORM);
- } else if (event.dropTarget == mStackDropTarget) {
- mStack.setTaskWindowingMode(event.task, WINDOWING_MODE_FULLSCREEN);
- }
- updateLayoutAlgorithm(true /* boundScroll */);
-
- // Move the task to the new stack in the system after the animation completes
- event.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.setTaskWindowingMode(event.task.key.id, event.task.key.windowingMode);
- }
- });
- }
-
// Restore the task, so that relayout will apply to it below
removeIgnoreTask(event.task);
@@ -2177,9 +2004,7 @@
// Add a runnable to the post animation ref counter to clear all the views
trigger.addLastDecrementRunnable(() -> {
// Start the dozer to trigger to trigger any UI that shows after a timeout
- if (!Recents.getSystemServices().hasFreeformWorkspaceSupport()) {
- mUIDozeTrigger.startDozing();
- }
+ mUIDozeTrigger.startDozing();
// Update the focused state here -- since we only set the focused task without
// requesting view focus in onFirstLayout(), actually request view focus and
@@ -2202,18 +2027,6 @@
mStackReloaded = false;
}
- public final void onBusEvent(UpdateFreeformTaskViewVisibilityEvent event) {
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
- if (task.isFreeformTask()) {
- tv.setVisibility(event.visible ? View.VISIBLE : View.INVISIBLE);
- }
- }
- }
-
public final void onBusEvent(final MultiWindowStateChangedEvent event) {
if (event.inMultiWindow || !event.showDeferredAnimation) {
setTasks(event.stack, true /* allowNotifyStackChanges */);
@@ -2315,27 +2128,6 @@
}
/**
- * Starts an alpha animation on the freeform workspace background.
- */
- private void animateFreeformWorkspaceBackgroundAlpha(int targetAlpha,
- AnimationProps animation) {
- if (mFreeformWorkspaceBackground.getAlpha() == targetAlpha) {
- return;
- }
-
- Utilities.cancelAnimationWithoutCallbacks(mFreeformWorkspaceBackgroundAnimator);
- mFreeformWorkspaceBackgroundAnimator = ObjectAnimator.ofInt(mFreeformWorkspaceBackground,
- Utilities.DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
- mFreeformWorkspaceBackgroundAnimator.setStartDelay(
- animation.getDuration(AnimationProps.ALPHA));
- mFreeformWorkspaceBackgroundAnimator.setDuration(
- animation.getDuration(AnimationProps.ALPHA));
- mFreeformWorkspaceBackgroundAnimator.setInterpolator(
- animation.getInterpolator(AnimationProps.ALPHA));
- mFreeformWorkspaceBackgroundAnimator.start();
- }
-
- /**
* Returns the insert index for the task in the current set of task views. If the given task
* is already in the task view list, then this method returns the insert index assuming it
* is first removed at the previous index.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 32a249c..1abaced 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -403,18 +403,6 @@
return;
}
- // If tapping on the freeform workspace background, just launch the first freeform task
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.hasFreeformWorkspaceSupport()) {
- Rect freeformRect = mSv.mLayoutAlgorithm.mFreeformRect;
- if (freeformRect.top <= y && y <= freeformRect.bottom) {
- if (mSv.launchFreeformTasks()) {
- // TODO: Animate Recents away as we launch the freeform tasks
- return;
- }
- }
- }
-
// The user intentionally tapped on the background, which is like a tap on the "desktop".
// Hide recents and transition to the launcher.
EventBus.getDefault().send(new HideRecentsEvent(false, true));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 9d63964..a75034a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,8 +16,6 @@
package com.android.systemui.recents.views;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
@@ -196,9 +194,7 @@
* Called from RecentsActivity when it is relaunched.
*/
void onReload(boolean isResumingFromVisible) {
- if (!Recents.getSystemServices().hasFreeformWorkspaceSupport()) {
- resetNoUserInteractionState();
- }
+ resetNoUserInteractionState();
if (!isResumingFromVisible) {
resetViewProperties();
}
@@ -415,9 +411,7 @@
* view.
*/
boolean shouldClipViewInStack() {
- // Never clip for freeform tasks or if invisible
- if (mTask.isFreeformTask() || getVisibility() != View.VISIBLE ||
- Recents.getConfiguration().isLowRamDevice) {
+ if (getVisibility() != View.VISIBLE || Recents.getConfiguration().isLowRamDevice) {
return false;
}
return mClipViewInStack;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 198ecae..c4e4e2e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -17,7 +17,6 @@
package com.android.systemui.recents.views;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -164,8 +163,6 @@
float mDimAlpha;
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
- Drawable mLightFreeformIcon;
- Drawable mDarkFreeformIcon;
Drawable mLightFullscreenIcon;
Drawable mDarkFullscreenIcon;
Drawable mLightInfoIcon;
@@ -215,8 +212,6 @@
mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);
- mLightFreeformIcon = context.getDrawable(R.drawable.recents_move_task_freeform_light);
- mDarkFreeformIcon = context.getDrawable(R.drawable.recents_move_task_freeform_dark);
mLightFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_light);
mDarkFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_dark);
mLightInfoIcon = context.getDrawable(R.drawable.recents_info_light);
@@ -249,9 +244,6 @@
mIconView.setOnLongClickListener(this);
mTitleView = findViewById(R.id.title);
mDismissButton = findViewById(R.id.dismiss_task);
- if (ssp.hasFreeformWorkspaceSupport()) {
- mMoveTaskButton = findViewById(R.id.move_task);
- }
onConfigurationChanged();
}
@@ -341,20 +333,6 @@
boolean showDismissIcon = true;
int rightInset = width - getMeasuredWidth();
- if (mTask != null && mTask.isFreeformTask()) {
- // For freeform tasks, we always show the app icon, and only show the title, move-task
- // icon, and the dismiss icon if there is room
- int appIconWidth = mIconView.getMeasuredWidth();
- int titleWidth = (int) mTitleView.getPaint().measureText(mTask.title);
- int dismissWidth = mDismissButton.getMeasuredWidth();
- int moveTaskWidth = mMoveTaskButton != null
- ? mMoveTaskButton.getMeasuredWidth()
- : 0;
- showTitle = width >= (appIconWidth + dismissWidth + moveTaskWidth + titleWidth);
- showMoveIcon = width >= (appIconWidth + dismissWidth + moveTaskWidth);
- showDismissIcon = width >= (appIconWidth + dismissWidth);
- }
-
mTitleView.setVisibility(showTitle ? View.VISIBLE : View.INVISIBLE);
if (mMoveTaskButton != null) {
mMoveTaskButton.setVisibility(showMoveIcon ? View.VISIBLE : View.INVISIBLE);
@@ -482,25 +460,6 @@
mDismissButton.setClickable(false);
((RippleDrawable) mDismissButton.getBackground()).setForceSoftware(true);
- // When freeform workspaces are enabled, then update the move-task button depending on the
- // current task
- if (mMoveTaskButton != null) {
- if (t.isFreeformTask()) {
- mTaskWindowingMode = WINDOWING_MODE_FULLSCREEN;
- mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor
- ? mLightFullscreenIcon
- : mDarkFullscreenIcon);
- } else {
- mTaskWindowingMode = WINDOWING_MODE_FREEFORM;
- mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor
- ? mLightFreeformIcon
- : mDarkFreeformIcon);
- }
- mMoveTaskButton.setOnClickListener(this);
- mMoveTaskButton.setClickable(false);
- ((RippleDrawable) mMoveTaskButton.getBackground()).setForceSoftware(true);
- }
-
if (Recents.getDebugFlags().isFastToggleRecentsEnabled()) {
if (mFocusTimerIndicator == null) {
mFocusTimerIndicator = (ProgressBar) Utilities.findViewStubById(this,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index a2190b3..d0ebc8d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -245,10 +245,6 @@
public void updateThumbnailMatrix() {
mThumbnailScale = 1f;
if (mBitmapShader != null && mThumbnailData != null) {
- // We consider this a stack task if it is not freeform (ie. has no bounds) or has been
- // dragged into the stack from the freeform workspace
- boolean isStackTask = !mTask.isFreeformTask() || mTask.bounds == null;
- int xOffset, yOffset = 0;
if (mTaskViewRect.isEmpty()) {
// If we haven't measured , skip the thumbnail drawing and only draw the background
// color
@@ -266,7 +262,7 @@
mThumbnailScale = (float) (mTaskViewRect.height() - mTitleBarHeight)
/ (float) mThumbnailRect.height();
}
- } else if (isStackTask) {
+ } else {
float invThumbnailScale = 1f / mFullscreenThumbnailScale;
if (mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT) {
if (mThumbnailData.orientation == Configuration.ORIENTATION_PORTRAIT) {
@@ -283,12 +279,6 @@
// Otherwise, scale the screenshot to fit 1:1 in the current orientation
mThumbnailScale = invThumbnailScale;
}
- } else {
- // Otherwise, if this is a freeform task with task bounds, then scale the thumbnail
- // to fit the entire bitmap into the task bounds
- mThumbnailScale = Math.min(
- (float) mTaskViewRect.width() / mThumbnailRect.width(),
- (float) mTaskViewRect.height() / mThumbnailRect.height());
}
mMatrix.setTranslate(-mThumbnailData.insets.left * mFullscreenThumbnailScale,
-mThumbnailData.insets.top * mFullscreenThumbnailScale);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 397f24e..c9dbe2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -59,7 +59,7 @@
public boolean visible = false;
- // This is a window-space rect used for positioning the task in the stack and freeform workspace
+ // This is a window-space rect used for positioning the task in the stack
public RectF rect = new RectF();
/**
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 7699bb9..9211e3f 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -16,6 +16,10 @@
package com.android.systemui.shortcut;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.os.UserHandle.USER_CURRENT;
+
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.ActivityManager;
import android.app.IActivityManager;
@@ -102,11 +106,10 @@
// If there is no window docked, we dock the top-most window.
Recents recents = getComponent(Recents.class);
int dockMode = (shortcutCode == SC_DOCK_LEFT)
- ? ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
- : ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+ ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+ : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
List<ActivityManager.RecentTaskInfo> taskList =
- SystemServicesProxy.getInstance(mContext).getRecentTasks(1,
- UserHandle.USER_CURRENT, false, new ArraySet<>());
+ SystemServicesProxy.getInstance(mContext).getRecentTasks(1, USER_CURRENT);
recents.showRecentApps(
false /* triggeredFromAltTab */,
false /* fromHome */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 966e789..6c5f4b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -36,6 +36,7 @@
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Property;
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.NotificationHeaderView;
@@ -174,6 +175,11 @@
private boolean mShowNoBackground;
private ExpandableNotificationRow mNotificationParent;
private OnExpandClickListener mOnExpandClickListener;
+
+ // Listener will be called when receiving a long click event.
+ // Use #setLongPressPosition to optionally assign positional data with the long press.
+ private LongPressListener mLongPressListener;
+
private boolean mGroupExpansionChanging;
/**
@@ -788,6 +794,10 @@
mOnExpandClickListener = onExpandClickListener;
}
+ public void setLongPressListener(LongPressListener longPressListener) {
+ mLongPressListener = longPressListener;
+ }
+
@Override
public void setOnClickListener(@Nullable OnClickListener l) {
super.setOnClickListener(l);
@@ -1338,6 +1348,47 @@
}
}
+ private void doLongClickCallback() {
+ doLongClickCallback(getWidth() / 2, getHeight() / 2);
+ }
+
+ public void doLongClickCallback(int x, int y) {
+ createMenu();
+ MenuItem menuItem = getProvider().getLongpressMenuItem(mContext);
+ if (mLongPressListener != null && menuItem != null) {
+ mLongPressListener.onLongPress(this, x, y, menuItem);
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (KeyEvent.isConfirmKey(keyCode)) {
+ event.startTracking();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (KeyEvent.isConfirmKey(keyCode)) {
+ if (!event.isCanceled()) {
+ performClick();
+ }
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ if (KeyEvent.isConfirmKey(keyCode)) {
+ doLongClickCallback();
+ return true;
+ }
+ return false;
+ }
+
public void resetTranslation() {
if (mTranslateAnim != null) {
mTranslateAnim.cancel();
@@ -2205,6 +2256,7 @@
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
if (canViewBeDismissed()) {
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
}
@@ -2244,6 +2296,9 @@
case AccessibilityNodeInfo.ACTION_EXPAND:
mExpandClickListener.onClick(this);
return true;
+ case AccessibilityNodeInfo.ACTION_LONG_CLICK:
+ doLongClickCallback();
+ return true;
}
return false;
}
@@ -2332,4 +2387,15 @@
protected void setChildrenContainer(NotificationChildrenContainer childrenContainer) {
mChildrenContainer = childrenContainer;
}
+
+ /**
+ * Equivalent to View.OnLongClickListener with coordinates
+ */
+ public interface LongPressListener {
+ /**
+ * Equivalent to {@link View.OnLongClickListener#onLongClick(View)} with coordinates
+ * @return whether the longpress was handled
+ */
+ boolean onLongPress(View v, int x, int y, MenuItem item);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 59d3e0a..2ad881f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -44,6 +44,7 @@
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
@@ -247,11 +248,12 @@
}
/**
- * Returns the {@link com.android.systemui.SwipeHelper.LongPressListener} that will be
- * triggered when a notification card is long-pressed.
+ * Returns the
+ * {@link com.android.systemui.statusbar.ExpandableNotificationRow.LongPressListener} that will
+ * be triggered when a notification card is long-pressed.
*/
@Override
- protected SwipeHelper.LongPressListener getNotificationLongClicker() {
+ protected ExpandableNotificationRow.LongPressListener getNotificationLongClicker() {
// For the automative use case, we do not want to the user to be able to interact with
// a notification other than a regular click. As a result, just return null for the
// long click listener.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 7b11ace..af03440 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -704,7 +704,7 @@
mInitialHeightOnTouch = mQsExpansionHeight;
mQsTracking = true;
mIntercepting = false;
- mNotificationStackScroller.removeLongPressCallback();
+ mNotificationStackScroller.cancelLongPress();
}
break;
case MotionEvent.ACTION_POINTER_UP:
@@ -740,7 +740,7 @@
mInitialTouchY = y;
mInitialTouchX = x;
mIntercepting = false;
- mNotificationStackScroller.removeLongPressCallback();
+ mNotificationStackScroller.cancelLongPress();
return true;
}
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 9c837ed..b0ce577 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -639,12 +639,17 @@
}
private Intent getTaskIntent(int taskId, int userId) {
- List<ActivityManager.RecentTaskInfo> tasks = mContext.getSystemService(ActivityManager.class)
- .getRecentTasksForUser(NUM_TASKS_FOR_INSTANT_APP_INFO, 0, userId);
- for (int i = 0; i < tasks.size(); i++) {
- if (tasks.get(i).id == taskId) {
- return tasks.get(i).baseIntent;
+ try {
+ final List<ActivityManager.RecentTaskInfo> tasks =
+ ActivityManager.getService().getRecentTasks(
+ NUM_TASKS_FOR_INSTANT_APP_INFO, 0, userId).getList();
+ for (int i = 0; i < tasks.size(); i++) {
+ if (tasks.get(i).id == taskId) {
+ return tasks.get(i).baseIntent;
+ }
}
+ } catch (RemoteException e) {
+ // Fall through
}
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 54be857..9f03954 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -160,7 +160,6 @@
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
-import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
@@ -4838,7 +4837,7 @@
@Override
public void onTouchSlopExceeded() {
- mStackScroller.removeLongPressCallback();
+ mStackScroller.cancelLongPress();
mStackScroller.checkSnoozeLeavebehind();
}
@@ -5470,7 +5469,7 @@
@Override
public void onDoubleTap(float screenX, float screenY) {
- if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
+ if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
&& mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2);
float viewX = screenX - mTmpInt2[0];
@@ -5882,8 +5881,7 @@
List<ActivityManager.RecentTaskInfo> recentTask = null;
try {
recentTask = ActivityManager.getService().getRecentTasks(1,
- ActivityManager.RECENT_WITH_EXCLUDED
- | ActivityManager.RECENT_INCLUDE_PROFILES,
+ ActivityManager.RECENT_WITH_EXCLUDED,
mCurrentUserId).getList();
} catch (RemoteException e) {
// Abandon hope activity manager not running.
@@ -6296,14 +6294,15 @@
true /* removeControls */, x, y, true /* resetMenu */);
}
- protected SwipeHelper.LongPressListener getNotificationLongClicker() {
- return new SwipeHelper.LongPressListener() {
+ protected ExpandableNotificationRow.LongPressListener getNotificationLongClicker() {
+ return new ExpandableNotificationRow.LongPressListener() {
@Override
public boolean onLongPress(View v, final int x, final int y,
MenuItem item) {
if (!(v instanceof ExpandableNotificationRow)) {
return false;
}
+
if (v.getWindowToken() == null) {
Log.e(TAG, "Trying to show notification guts, but not attached to window");
return false;
@@ -6318,7 +6317,7 @@
closeAndSaveGuts(false /* removeLeavebehind */, false /* force */,
true /* removeControls */, -1 /* x */, -1 /* y */,
true /* resetMenu */);
- return false;
+ return true;
}
bindGuts(row, item);
NotificationGuts guts = row.getGuts();
@@ -6598,6 +6597,7 @@
row.setRemoteViewClickHandler(mOnClickHandler);
row.setInflationCallback(this);
row.setSecureStateProvider(this::isKeyguardCurrentlySecure);
+ row.setLongPressListener(getNotificationLongClicker());
// Get the app name.
// Note that Notification.Builder#bindHeaderAppName has similar logic
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 75532d9..1e14626 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -240,7 +240,7 @@
* motion.
*/
private int mMaxScrollAfterExpand;
- private SwipeHelper.LongPressListener mLongPressListener;
+ private ExpandableNotificationRow.LongPressListener mLongPressListener;
private NotificationMenuRowPlugin mCurrMenuRow;
private View mTranslatingParentView;
@@ -410,7 +410,6 @@
mExpandHelper.setEventSource(this);
mExpandHelper.setScrollAdapter(this);
mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, this, getContext());
- mSwipeHelper.setLongPressListener(mLongPressListener);
mStackScrollAlgorithm = createStackScrollAlgorithm(context);
initView(context);
mFalsingManager = FalsingManager.getInstance(context);
@@ -884,8 +883,7 @@
return firstChild != null ? firstChild.getMinHeight() : mCollapsedSize;
}
- public void setLongPressListener(SwipeHelper.LongPressListener listener) {
- mSwipeHelper.setLongPressListener(listener);
+ public void setLongPressListener(ExpandableNotificationRow.LongPressListener listener) {
mLongPressListener = listener;
}
@@ -1175,7 +1173,7 @@
if (v instanceof ExpandableNotificationRow) {
((ExpandableNotificationRow) v).setUserLocked(userLocked);
}
- removeLongPressCallback();
+ cancelLongPress();
requestDisallowInterceptTouchEvent(true);
}
@@ -2581,7 +2579,7 @@
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
super.requestDisallowInterceptTouchEvent(disallowIntercept);
if (disallowIntercept) {
- mSwipeHelper.removeLongPressCallback();
+ cancelLongPress();
}
}
@@ -3302,7 +3300,7 @@
mIsBeingDragged = isDragged;
if (isDragged) {
requestDisallowInterceptTouchEvent(true);
- removeLongPressCallback();
+ cancelLongPress();
}
}
@@ -3310,7 +3308,7 @@
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (!hasWindowFocus) {
- removeLongPressCallback();
+ cancelLongPress();
}
}
@@ -3324,7 +3322,7 @@
@Override
public void requestDisallowLongPress() {
- removeLongPressCallback();
+ cancelLongPress();
}
@Override
@@ -3332,8 +3330,8 @@
mDisallowDismissInThisMotion = true;
}
- public void removeLongPressCallback() {
- mSwipeHelper.removeLongPressCallback();
+ public void cancelLongPress() {
+ mSwipeHelper.cancelLongPress();
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java
index 767e124..4564c8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/model/HighResThumbnailLoaderTest.java
@@ -60,7 +60,7 @@
MockitoAnnotations.initMocks(this);
mLoader = new HighResThumbnailLoader(mMockSystemServicesProxy, Looper.getMainLooper(),
false);
- mTask.key = new TaskKey(0, WINDOWING_MODE_UNDEFINED, null, 0, 0, 0);
+ mTask.key = new TaskKey(0, WINDOWING_MODE_UNDEFINED, null, 0, 0);
when(mMockSystemServicesProxy.getTaskThumbnail(anyInt(), anyBoolean()))
.thenReturn(mThumbnailData);
mLoader.setVisible(true);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 4834f38..8e88359 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -4666,8 +4666,39 @@
DIALOG_CLEAR_ADB_KEYS = 1223;
// Open: Settings > Developer options > Quick setting tile config
+ // CATEGORY: SETTINGS
+ // OS: P
DEVELOPMENT_QS_TILE_CONFIG = 1224;
+ // OPEN: Settings > Developer options > Store logger data persistently on device > Info dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_LOG_PERSIST = 1225;
+
+ // ACTION: DND Settings > Priority only allows > Alarms toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ALLOW_ALARMS = 1226;
+
+ // ACTION: DND Settings > Priority only allows > Media toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ALLOW_MEDIA = 1227;
+
+ // An autofill service explicitly defined which view should commit the autofill context
+ // Package: Package of app that is autofilled
+ // OS: P
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ AUTOFILL_EXPLICIT_SAVE_TRIGGER_DEFINITION = 1228;
+
+ // The autofill context was commited when the user clicked a view explicitly marked by the
+ // service as committing it
+ // Package: Package of app that is autofilled
+ // OS: P
+ AUTOFILL_SAVE_EXPLICITLY_TRIGGERED = 1229;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index a6aaaa67..51afada 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -71,7 +71,6 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.storage.StorageManager;
import android.service.appwidget.AppWidgetServiceDumpProto;
import android.service.appwidget.WidgetProto;
import android.text.TextUtils;
@@ -159,7 +158,9 @@
// Bump if the stored widgets need to be upgraded.
private static final int CURRENT_VERSION = 1;
- private static final AtomicLong REQUEST_COUNTER = new AtomicLong();
+ // Every widget update request is associated which an increasing sequence number. This is
+ // used to verify which request has successfully been received by the host.
+ private static final AtomicLong UPDATE_COUNTER = new AtomicLong();
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -814,9 +815,9 @@
Host host = lookupOrAddHostLocked(id);
host.callbacks = callbacks;
+ long updateSequenceNo = UPDATE_COUNTER.incrementAndGet();
int N = appWidgetIds.length;
ArrayList<PendingHostUpdate> outUpdates = new ArrayList<>(N);
-
LongSparseArray<PendingHostUpdate> updatesMap = new LongSparseArray<>();
for (int i = 0; i < N; i++) {
if (host.getPendingUpdatesForId(appWidgetIds[i], updatesMap)) {
@@ -828,6 +829,8 @@
}
}
}
+ // Reset the update counter once all the updates have been calculated
+ host.lastWidgetUpdateSequenceNo = updateSequenceNo;
return new ParceledListSlice<>(outUpdates);
}
}
@@ -1914,9 +1917,9 @@
// method with a wrong id. In that case, ignore the call.
return;
}
- long requestId = REQUEST_COUNTER.incrementAndGet();
+ long requestId = UPDATE_COUNTER.incrementAndGet();
if (widget != null) {
- widget.updateRequestIds.put(viewId, requestId);
+ widget.updateSequenceNos.put(viewId, requestId);
}
if (widget == null || widget.host == null || widget.host.zombie
|| widget.host.callbacks == null || widget.provider == null
@@ -1941,7 +1944,7 @@
int appWidgetId, int viewId, long requestId) {
try {
callbacks.viewDataChanged(appWidgetId, viewId);
- host.lastWidgetUpdateRequestId = requestId;
+ host.lastWidgetUpdateSequenceNo = requestId;
} catch (RemoteException re) {
// It failed; remove the callback. No need to prune because
// we know that this host is still referenced by this instance.
@@ -1988,9 +1991,9 @@
}
private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
- long requestId = REQUEST_COUNTER.incrementAndGet();
+ long requestId = UPDATE_COUNTER.incrementAndGet();
if (widget != null) {
- widget.updateRequestIds.put(ID_VIEWS_UPDATE, requestId);
+ widget.updateSequenceNos.put(ID_VIEWS_UPDATE, requestId);
}
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
@@ -2013,7 +2016,7 @@
int appWidgetId, RemoteViews views, long requestId) {
try {
callbacks.updateAppWidget(appWidgetId, views);
- host.lastWidgetUpdateRequestId = requestId;
+ host.lastWidgetUpdateSequenceNo = requestId;
} catch (RemoteException re) {
synchronized (mLock) {
Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -2023,11 +2026,11 @@
}
private void scheduleNotifyProviderChangedLocked(Widget widget) {
- long requestId = REQUEST_COUNTER.incrementAndGet();
+ long requestId = UPDATE_COUNTER.incrementAndGet();
if (widget != null) {
// When the provider changes, reset everything else.
- widget.updateRequestIds.clear();
- widget.updateRequestIds.append(ID_PROVIDER_CHANGED, requestId);
+ widget.updateSequenceNos.clear();
+ widget.updateSequenceNos.append(ID_PROVIDER_CHANGED, requestId);
}
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
@@ -2050,7 +2053,7 @@
int appWidgetId, AppWidgetProviderInfo info, long requestId) {
try {
callbacks.providerChanged(appWidgetId, info);
- host.lastWidgetUpdateRequestId = requestId;
+ host.lastWidgetUpdateSequenceNo = requestId;
} catch (RemoteException re) {
synchronized (mLock){
Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -3887,7 +3890,11 @@
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
int tag = TAG_UNDEFINED; // for use while saving state (the index)
- long lastWidgetUpdateRequestId; // request id for the last update successfully sent
+ // Sequence no for the last update successfully sent. This is updated whenever a
+ // widget update is successfully sent to the host callbacks. As all new/undelivered updates
+ // will have sequenceNo greater than this, all those updates will be sent when the host
+ // callbacks are attached again.
+ long lastWidgetUpdateSequenceNo;
public int getUserId() {
return UserHandle.getUserId(id.uid);
@@ -3914,18 +3921,18 @@
*/
public boolean getPendingUpdatesForId(int appWidgetId,
LongSparseArray<PendingHostUpdate> outUpdates) {
- long updateRequestId = lastWidgetUpdateRequestId;
+ long updateSequenceNo = lastWidgetUpdateSequenceNo;
int N = widgets.size();
for (int i = 0; i < N; i++) {
Widget widget = widgets.get(i);
if (widget.appWidgetId == appWidgetId) {
outUpdates.clear();
- for (int j = widget.updateRequestIds.size() - 1; j >= 0; j--) {
- long requestId = widget.updateRequestIds.valueAt(j);
- if (requestId <= updateRequestId) {
+ for (int j = widget.updateSequenceNos.size() - 1; j >= 0; j--) {
+ long requestId = widget.updateSequenceNos.valueAt(j);
+ if (requestId <= updateSequenceNo) {
continue;
}
- int id = widget.updateRequestIds.keyAt(j);
+ int id = widget.updateSequenceNos.keyAt(j);
final PendingHostUpdate update;
switch (id) {
case ID_PROVIDER_CHANGED:
@@ -4021,8 +4028,8 @@
RemoteViews maskedViews;
Bundle options;
Host host;
- // Request ids for various operations
- SparseLongArray updateRequestIds = new SparseLongArray(2);
+ // Map of request type to updateSequenceNo.
+ SparseLongArray updateSequenceNos = new SparseLongArray(2);
@Override
public String toString() {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index ed00ffe..3c12d67 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -495,7 +495,7 @@
notifyUnavailableToClient(false);
}
synchronized (mLock) {
- processResponseLocked(response, requestFlags);
+ processResponseLocked(response, null, requestFlags);
}
final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
@@ -762,13 +762,21 @@
}
final Parcelable result = data.getParcelable(AutofillManager.EXTRA_AUTHENTICATION_RESULT);
- if (sDebug) Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result);
+ final Bundle newClientState = data.getBundle(AutofillManager.EXTRA_CLIENT_STATE);
+ if (sDebug) {
+ Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result
+ + ", clientState=" + newClientState);
+ }
if (result instanceof FillResponse) {
writeLog(MetricsEvent.AUTOFILL_AUTHENTICATED);
- replaceResponseLocked(authenticatedResponse, (FillResponse) result);
+ replaceResponseLocked(authenticatedResponse, (FillResponse) result, newClientState);
} else if (result instanceof Dataset) {
if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) {
writeLog(MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
+ if (newClientState != null) {
+ if (sDebug) Slog.d(TAG, "Updating client state from auth dataset");
+ mClientState = newClientState;
+ }
final Dataset dataset = (Dataset) result;
authenticatedResponse.getDatasets().set(datasetIdx, dataset);
autoFill(requestId, datasetIdx, dataset, false);
@@ -1491,8 +1499,14 @@
ArraySet<AutofillId> trackedViews = null;
boolean saveOnAllViewsInvisible = false;
+ boolean saveOnFinish = true;
final SaveInfo saveInfo = response.getSaveInfo();
+ final AutofillId saveTriggerId;
if (saveInfo != null) {
+ saveTriggerId = saveInfo.getTriggerId();
+ if (saveTriggerId != null) {
+ writeLog(MetricsEvent.AUTOFILL_EXPLICIT_SAVE_TRIGGER_DEFINITION);
+ }
saveOnAllViewsInvisible =
(saveInfo.getFlags() & SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE) != 0;
@@ -1509,6 +1523,12 @@
Collections.addAll(trackedViews, saveInfo.getOptionalIds());
}
}
+ if ((saveInfo.getFlags() & SaveInfo.FLAG_DONT_SAVE_ON_FINISH) != 0) {
+ saveOnFinish = false;
+ }
+
+ } else {
+ saveTriggerId = null;
}
// Must also track that are part of datasets, otherwise the FillUI won't be hidden when
@@ -1533,17 +1553,18 @@
try {
if (sVerbose) {
- Slog.v(TAG, "updateTrackedIdsLocked(): " + trackedViews + " => " + fillableIds);
+ Slog.v(TAG, "updateTrackedIdsLocked(): " + trackedViews + " => " + fillableIds
+ + " (triggering on " + saveTriggerId + ")");
}
mClient.setTrackedViews(id, toArray(trackedViews), saveOnAllViewsInvisible,
- toArray(fillableIds));
+ saveOnFinish, toArray(fillableIds), saveTriggerId);
} catch (RemoteException e) {
Slog.w(TAG, "Cannot set tracked ids", e);
}
}
private void replaceResponseLocked(@NonNull FillResponse oldResponse,
- @NonNull FillResponse newResponse) {
+ @NonNull FillResponse newResponse, @Nullable Bundle newClientState) {
// Disassociate view states with the old response
setViewStatesLocked(oldResponse, ViewState.STATE_INITIAL, true);
// Move over the id
@@ -1551,7 +1572,7 @@
// Replace the old response
mResponses.put(newResponse.getRequestId(), newResponse);
// Now process the new response
- processResponseLocked(newResponse, 0);
+ processResponseLocked(newResponse, newClientState, 0);
}
private void processNullResponseLocked(int flags) {
@@ -1565,7 +1586,8 @@
removeSelf();
}
- private void processResponseLocked(@NonNull FillResponse newResponse, int flags) {
+ private void processResponseLocked(@NonNull FillResponse newResponse,
+ @Nullable Bundle newClientState, int flags) {
// Make sure we are hiding the UI which will be shown
// only if handling the current response requires it.
mUi.hideAll(this);
@@ -1573,14 +1595,15 @@
final int requestId = newResponse.getRequestId();
if (sVerbose) {
Slog.v(TAG, "processResponseLocked(): mCurrentViewId=" + mCurrentViewId
- + ",flags=" + flags + ", reqId=" + requestId + ", resp=" + newResponse);
+ + ",flags=" + flags + ", reqId=" + requestId + ", resp=" + newResponse
+ + ",newClientState=" + newClientState);
}
if (mResponses == null) {
mResponses = new SparseArray<>(4);
}
mResponses.put(requestId, newResponse);
- mClientState = newResponse.getClientState();
+ mClientState = newClientState != null ? newClientState : newResponse.getClientState();
setViewStatesLocked(newResponse, ViewState.STATE_FILLABLE, false);
updateTrackedIdsLocked();
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index eabe21f..f9213aa 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -319,7 +319,6 @@
boolean mProvisioned;
boolean mAutoRestore;
PowerManager.WakeLock mWakelock;
- HandlerThread mHandlerThread;
BackupHandler mBackupHandler;
PendingIntent mRunBackupIntent, mRunInitIntent;
BroadcastReceiver mRunBackupReceiver, mRunInitReceiver;
@@ -409,43 +408,37 @@
// Called through the trampoline from onUnlockUser(), then we buck the work
// off to the background thread to keep the unlock time down.
public void unlockSystemUser() {
- mBackupHandler.post(() -> {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init");
- sInstance.initialize(UserHandle.USER_SYSTEM);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
- // Migrate legacy setting
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
- if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
+ // Migrate legacy setting
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
+ if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
+ if (DEBUG) {
+ Slog.i(TAG, "Backup enable apparently not migrated");
+ }
+ final ContentResolver r = sInstance.mContext.getContentResolver();
+ final int enableState = Settings.Secure.getIntForUser(r,
+ Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
+ if (enableState >= 0) {
if (DEBUG) {
- Slog.i(TAG, "Backup enable apparently not migrated");
+ Slog.i(TAG, "Migrating enable state " + (enableState != 0));
}
- final ContentResolver r = sInstance.mContext.getContentResolver();
- final int enableState = Settings.Secure.getIntForUser(r,
- Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
- if (enableState >= 0) {
- if (DEBUG) {
- Slog.i(TAG, "Migrating enable state " + (enableState != 0));
- }
- writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
- Settings.Secure.putStringForUser(r,
- Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
- } else {
- if (DEBUG) {
- Slog.i(TAG, "Backup not yet configured; retaining null enable state");
- }
+ writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
+ Settings.Secure.putStringForUser(r,
+ Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "Backup not yet configured; retaining null enable state");
}
}
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
- try {
- sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
- } catch (RemoteException e) {
- // can't happen; it's a local object
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- });
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
+ try {
+ sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
+ } catch (RemoteException e) {
+ // can't happen; it's a local object
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
class ProvisionedObserver extends ContentObserver {
@@ -1220,7 +1213,7 @@
// ----- Main service implementation -----
- public BackupManagerService(Context context, Trampoline parent) {
+ public BackupManagerService(Context context, Trampoline parent, HandlerThread backupThread) {
mContext = context;
mPackageManager = context.getPackageManager();
mPackageManagerBinder = AppGlobals.getPackageManager();
@@ -1233,9 +1226,7 @@
mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
// spin up the backup/restore handler thread
- mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
- mHandlerThread.start();
- mBackupHandler = new BackupHandler(mHandlerThread.getLooper());
+ mBackupHandler = new BackupHandler(backupThread.getLooper());
// Set up our bookkeeping
final ContentResolver resolver = context.getContentResolver();
@@ -1360,7 +1351,7 @@
if (DEBUG) Slog.v(TAG, "Starting with transport " + currentTransport);
mTransportManager = new TransportManager(context, transportWhitelist, currentTransport,
- mTransportBoundListener, mHandlerThread.getLooper());
+ mTransportBoundListener, backupThread.getLooper());
mTransportManager.registerAllTransports();
// Now that we know about valid backup participants, parse any
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index f298065..20f2369 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -237,7 +237,6 @@
private boolean mProvisioned;
private boolean mAutoRestore;
private PowerManager.WakeLock mWakelock;
- private HandlerThread mHandlerThread;
private BackupHandler mBackupHandler;
private PendingIntent mRunBackupIntent;
private PendingIntent mRunInitIntent;
@@ -556,43 +555,37 @@
// Called through the trampoline from onUnlockUser(), then we buck the work
// off to the background thread to keep the unlock time down.
public void unlockSystemUser() {
- mBackupHandler.post(() -> {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init");
- sInstance.initialize(UserHandle.USER_SYSTEM);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
- // Migrate legacy setting
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
- if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
+ // Migrate legacy setting
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
+ if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
+ if (DEBUG) {
+ Slog.i(TAG, "Backup enable apparently not migrated");
+ }
+ final ContentResolver r = sInstance.mContext.getContentResolver();
+ final int enableState = Settings.Secure.getIntForUser(r,
+ Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
+ if (enableState >= 0) {
if (DEBUG) {
- Slog.i(TAG, "Backup enable apparently not migrated");
+ Slog.i(TAG, "Migrating enable state " + (enableState != 0));
}
- final ContentResolver r = sInstance.mContext.getContentResolver();
- final int enableState = Settings.Secure.getIntForUser(r,
- Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
- if (enableState >= 0) {
- if (DEBUG) {
- Slog.i(TAG, "Migrating enable state " + (enableState != 0));
- }
- writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
- Settings.Secure.putStringForUser(r,
- Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
- } else {
- if (DEBUG) {
- Slog.i(TAG, "Backup not yet configured; retaining null enable state");
- }
+ writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
+ Settings.Secure.putStringForUser(r,
+ Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "Backup not yet configured; retaining null enable state");
}
}
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
- try {
- sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
- } catch (RemoteException e) {
- // can't happen; it's a local object
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- });
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
+ try {
+ sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
+ } catch (RemoteException e) {
+ // can't happen; it's a local object
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
// Bookkeeping of in-flight operations for timeout etc. purposes. The operation
@@ -729,7 +722,8 @@
// ----- Main service implementation -----
- public RefactoredBackupManagerService(Context context, Trampoline parent) {
+ public RefactoredBackupManagerService(Context context, Trampoline parent,
+ HandlerThread backupThread) {
mContext = context;
mPackageManager = context.getPackageManager();
mPackageManagerBinder = AppGlobals.getPackageManager();
@@ -742,9 +736,7 @@
mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
// spin up the backup/restore handler thread
- mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
- mHandlerThread.start();
- mBackupHandler = new BackupHandler(this, mHandlerThread.getLooper());
+ mBackupHandler = new BackupHandler(this, backupThread.getLooper());
// Set up our bookkeeping
final ContentResolver resolver = context.getContentResolver();
@@ -824,7 +816,7 @@
if (DEBUG) Slog.v(TAG, "Starting with transport " + currentTransport);
mTransportManager = new TransportManager(context, transportWhitelist, currentTransport,
- mTransportBoundListener, mHandlerThread.getLooper());
+ mTransportBoundListener, backupThread.getLooper());
mTransportManager.registerAllTransports();
// Now that we know about valid backup participants, parse any
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 9739e38..9847edf 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -28,11 +28,15 @@
import android.content.Intent;
import android.os.Binder;
import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
@@ -75,6 +79,8 @@
final boolean mGlobalDisable;
volatile BackupManagerServiceInterface mService;
+ private HandlerThread mHandlerThread;
+
public Trampoline(Context context) {
mContext = context;
mGlobalDisable = isBackupDisabled();
@@ -111,11 +117,11 @@
}
protected BackupManagerServiceInterface createRefactoredBackupManagerService() {
- return new RefactoredBackupManagerService(mContext, this);
+ return new RefactoredBackupManagerService(mContext, this, mHandlerThread);
}
protected BackupManagerServiceInterface createBackupManagerService() {
- return new BackupManagerService(mContext, this);
+ return new BackupManagerService(mContext, this, mHandlerThread);
}
// internal control API
@@ -140,10 +146,21 @@
}
void unlockSystemUser() {
- BackupManagerServiceInterface svc = mService;
- if (svc != null) {
- svc.unlockSystemUser();
- }
+ mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
+ mHandlerThread.start();
+
+ Handler h = new Handler(mHandlerThread.getLooper());
+ h.post(() -> {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init");
+ initialize(UserHandle.USER_SYSTEM);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
+ BackupManagerServiceInterface svc = mService;
+ Slog.i(TAG, "Unlocking system user; mService=" + mService);
+ if (svc != null) {
+ svc.unlockSystemUser();
+ }
+ });
}
public void setBackupServiceActive(final int userHandle, boolean makeActive) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 5106c8d..6d9c977 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -35,6 +35,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.hardware.health.V2_0.HealthInfo;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.BatteryProperties;
@@ -118,8 +119,8 @@
private final Object mLock = new Object();
- private BatteryProperties mBatteryProps;
- private final BatteryProperties mLastBatteryProps = new BatteryProperties();
+ private HealthInfo mHealthInfo;
+ private final HealthInfo mLastHealthInfo = new HealthInfo();
private boolean mBatteryLevelCritical;
private int mLastBatteryStatus;
private int mLastBatteryHealth;
@@ -251,16 +252,16 @@
private boolean isPoweredLocked(int plugTypeSet) {
// assume we are powered if battery state is unknown so
// the "stay on while plugged in" option will work.
- if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
+ if (mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
return true;
}
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mBatteryProps.chargerAcOnline) {
+ if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mHealthInfo.legacy.chargerAcOnline) {
return true;
}
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mBatteryProps.chargerUsbOnline) {
+ if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mHealthInfo.legacy.chargerUsbOnline) {
return true;
}
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mBatteryProps.chargerWirelessOnline) {
+ if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mHealthInfo.legacy.chargerWirelessOnline) {
return true;
}
return false;
@@ -277,15 +278,15 @@
* (becomes <= mLowBatteryWarningLevel).
*/
return !plugged
- && mBatteryProps.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
- && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel
+ && mHealthInfo.legacy.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
+ && mHealthInfo.legacy.batteryLevel <= mLowBatteryWarningLevel
&& (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
}
private void shutdownIfNoPowerLocked() {
// shut down gracefully if our battery is critically low and we are not powered.
// wait until the system has booted before attempting to display the shutdown dialog.
- if (mBatteryProps.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
+ if (mHealthInfo.legacy.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -306,7 +307,7 @@
// shut down gracefully if temperature is too high (> 68.0C by default)
// wait until the system has booted before attempting to display the
// shutdown dialog.
- if (mBatteryProps.batteryTemperature > mShutdownBatteryTemperature) {
+ if (mHealthInfo.legacy.batteryTemperature > mShutdownBatteryTemperature) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -326,25 +327,66 @@
private void update(BatteryProperties props) {
synchronized (mLock) {
if (!mUpdatesStopped) {
- mBatteryProps = props;
+ mHealthInfo = new HealthInfo();
+ copy(mHealthInfo, props);
// Process the new values.
processValuesLocked(false);
} else {
- mLastBatteryProps.set(props);
+ copy(mLastHealthInfo, props);
}
}
}
+ private static void copy(HealthInfo dst, HealthInfo src) {
+ dst.legacy.chargerAcOnline = src.legacy.chargerAcOnline;
+ dst.legacy.chargerUsbOnline = src.legacy.chargerUsbOnline;
+ dst.legacy.chargerWirelessOnline = src.legacy.chargerWirelessOnline;
+ dst.legacy.maxChargingCurrent = src.legacy.maxChargingCurrent;
+ dst.legacy.maxChargingVoltage = src.legacy.maxChargingVoltage;
+ dst.legacy.batteryStatus = src.legacy.batteryStatus;
+ dst.legacy.batteryHealth = src.legacy.batteryHealth;
+ dst.legacy.batteryPresent = src.legacy.batteryPresent;
+ dst.legacy.batteryLevel = src.legacy.batteryLevel;
+ dst.legacy.batteryVoltage = src.legacy.batteryVoltage;
+ dst.legacy.batteryTemperature = src.legacy.batteryTemperature;
+ dst.legacy.batteryCurrent = src.legacy.batteryCurrent;
+ dst.legacy.batteryCycleCount = src.legacy.batteryCycleCount;
+ dst.legacy.batteryFullCharge = src.legacy.batteryFullCharge;
+ dst.legacy.batteryChargeCounter = src.legacy.batteryChargeCounter;
+ dst.legacy.batteryTechnology = src.legacy.batteryTechnology;
+ dst.batteryCurrentAverage = src.batteryCurrentAverage;
+ dst.batteryCapacity = src.batteryCapacity;
+ dst.energyCounter = src.energyCounter;
+ }
+
+ // TODO(b/62229583): remove this function when BatteryProperties are completely replaced.
+ private static void copy(HealthInfo dst, BatteryProperties src) {
+ dst.legacy.chargerAcOnline = src.chargerAcOnline;
+ dst.legacy.chargerUsbOnline = src.chargerUsbOnline;
+ dst.legacy.chargerWirelessOnline = src.chargerWirelessOnline;
+ dst.legacy.maxChargingCurrent = src.maxChargingCurrent;
+ dst.legacy.maxChargingVoltage = src.maxChargingVoltage;
+ dst.legacy.batteryStatus = src.batteryStatus;
+ dst.legacy.batteryHealth = src.batteryHealth;
+ dst.legacy.batteryPresent = src.batteryPresent;
+ dst.legacy.batteryLevel = src.batteryLevel;
+ dst.legacy.batteryVoltage = src.batteryVoltage;
+ dst.legacy.batteryTemperature = src.batteryTemperature;
+ dst.legacy.batteryFullCharge = src.batteryFullCharge;
+ dst.legacy.batteryChargeCounter = src.batteryChargeCounter;
+ dst.legacy.batteryTechnology = src.batteryTechnology;
+ }
+
private void processValuesLocked(boolean force) {
boolean logOutlier = false;
long dischargeDuration = 0;
- mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
- if (mBatteryProps.chargerAcOnline) {
+ mBatteryLevelCritical = (mHealthInfo.legacy.batteryLevel <= mCriticalBatteryLevel);
+ if (mHealthInfo.legacy.chargerAcOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
- } else if (mBatteryProps.chargerUsbOnline) {
+ } else if (mHealthInfo.legacy.chargerUsbOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
- } else if (mBatteryProps.chargerWirelessOnline) {
+ } else if (mHealthInfo.legacy.chargerWirelessOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
} else {
mPlugType = BATTERY_PLUGGED_NONE;
@@ -352,30 +394,17 @@
if (DEBUG) {
Slog.d(TAG, "Processing new values: "
- + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
- + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
- + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
- + ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent
- + ", maxChargingVoltage" + mBatteryProps.maxChargingVoltage
- + ", batteryStatus=" + mBatteryProps.batteryStatus
- + ", batteryHealth=" + mBatteryProps.batteryHealth
- + ", batteryPresent=" + mBatteryProps.batteryPresent
- + ", batteryLevel=" + mBatteryProps.batteryLevel
- + ", batteryTechnology=" + mBatteryProps.batteryTechnology
- + ", batteryVoltage=" + mBatteryProps.batteryVoltage
- + ", batteryChargeCounter=" + mBatteryProps.batteryChargeCounter
- + ", batteryFullCharge=" + mBatteryProps.batteryFullCharge
- + ", batteryTemperature=" + mBatteryProps.batteryTemperature
+ + "info=" + mHealthInfo
+ ", mBatteryLevelCritical=" + mBatteryLevelCritical
+ ", mPlugType=" + mPlugType);
}
// Let the battery stats keep track of the current level.
try {
- mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
- mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
- mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter,
- mBatteryProps.batteryFullCharge);
+ mBatteryStats.setBatteryState(mHealthInfo.legacy.batteryStatus, mHealthInfo.legacy.batteryHealth,
+ mPlugType, mHealthInfo.legacy.batteryLevel, mHealthInfo.legacy.batteryTemperature,
+ mHealthInfo.legacy.batteryVoltage, mHealthInfo.legacy.batteryChargeCounter,
+ mHealthInfo.legacy.batteryFullCharge);
} catch (RemoteException e) {
// Should never happen.
}
@@ -383,16 +412,16 @@
shutdownIfNoPowerLocked();
shutdownIfOverTempLocked();
- if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus ||
- mBatteryProps.batteryHealth != mLastBatteryHealth ||
- mBatteryProps.batteryPresent != mLastBatteryPresent ||
- mBatteryProps.batteryLevel != mLastBatteryLevel ||
+ if (force || (mHealthInfo.legacy.batteryStatus != mLastBatteryStatus ||
+ mHealthInfo.legacy.batteryHealth != mLastBatteryHealth ||
+ mHealthInfo.legacy.batteryPresent != mLastBatteryPresent ||
+ mHealthInfo.legacy.batteryLevel != mLastBatteryLevel ||
mPlugType != mLastPlugType ||
- mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
- mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
- mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent ||
- mBatteryProps.maxChargingVoltage != mLastMaxChargingVoltage ||
- mBatteryProps.batteryChargeCounter != mLastChargeCounter ||
+ mHealthInfo.legacy.batteryVoltage != mLastBatteryVoltage ||
+ mHealthInfo.legacy.batteryTemperature != mLastBatteryTemperature ||
+ mHealthInfo.legacy.maxChargingCurrent != mLastMaxChargingCurrent ||
+ mHealthInfo.legacy.maxChargingVoltage != mLastMaxChargingVoltage ||
+ mHealthInfo.legacy.batteryChargeCounter != mLastChargeCounter ||
mInvalidCharger != mLastInvalidCharger)) {
if (mPlugType != mLastPlugType) {
@@ -401,33 +430,33 @@
// There's no value in this data unless we've discharged at least once and the
// battery level has changed; so don't log until it does.
- if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) {
+ if (mDischargeStartTime != 0 && mDischargeStartLevel != mHealthInfo.legacy.batteryLevel) {
dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
logOutlier = true;
EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
- mDischargeStartLevel, mBatteryProps.batteryLevel);
+ mDischargeStartLevel, mHealthInfo.legacy.batteryLevel);
// make sure we see a discharge event before logging again
mDischargeStartTime = 0;
}
} else if (mPlugType == BATTERY_PLUGGED_NONE) {
// charging -> discharging or we just powered up
mDischargeStartTime = SystemClock.elapsedRealtime();
- mDischargeStartLevel = mBatteryProps.batteryLevel;
+ mDischargeStartLevel = mHealthInfo.legacy.batteryLevel;
}
}
- if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
- mBatteryProps.batteryHealth != mLastBatteryHealth ||
- mBatteryProps.batteryPresent != mLastBatteryPresent ||
+ if (mHealthInfo.legacy.batteryStatus != mLastBatteryStatus ||
+ mHealthInfo.legacy.batteryHealth != mLastBatteryHealth ||
+ mHealthInfo.legacy.batteryPresent != mLastBatteryPresent ||
mPlugType != mLastPlugType) {
EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
- mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
- mPlugType, mBatteryProps.batteryTechnology);
+ mHealthInfo.legacy.batteryStatus, mHealthInfo.legacy.batteryHealth, mHealthInfo.legacy.batteryPresent ? 1 : 0,
+ mPlugType, mHealthInfo.legacy.batteryTechnology);
}
- if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
+ if (mHealthInfo.legacy.batteryLevel != mLastBatteryLevel) {
// Don't do this just from voltage or temperature changes, that is
// too noisy.
EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
- mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
+ mHealthInfo.legacy.batteryLevel, mHealthInfo.legacy.batteryVoltage, mHealthInfo.legacy.batteryTemperature);
}
if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
mPlugType == BATTERY_PLUGGED_NONE) {
@@ -440,16 +469,16 @@
if (!mBatteryLevelLow) {
// Should we now switch in to low battery mode?
if (mPlugType == BATTERY_PLUGGED_NONE
- && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) {
+ && mHealthInfo.legacy.batteryLevel <= mLowBatteryWarningLevel) {
mBatteryLevelLow = true;
}
} else {
// Should we now switch out of low battery mode?
if (mPlugType != BATTERY_PLUGGED_NONE) {
mBatteryLevelLow = false;
- } else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
+ } else if (mHealthInfo.legacy.batteryLevel >= mLowBatteryCloseWarningLevel) {
mBatteryLevelLow = false;
- } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {
+ } else if (force && mHealthInfo.legacy.batteryLevel >= mLowBatteryWarningLevel) {
// If being forced, the previous state doesn't matter, we will just
// absolutely check to see if we are now above the warning level.
mBatteryLevelLow = false;
@@ -496,7 +525,7 @@
}
});
} else if (mSentLowBatteryBroadcast &&
- mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
+ mHealthInfo.legacy.batteryLevel >= mLowBatteryCloseWarningLevel) {
mSentLowBatteryBroadcast = false;
final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -522,16 +551,16 @@
logOutlierLocked(dischargeDuration);
}
- mLastBatteryStatus = mBatteryProps.batteryStatus;
- mLastBatteryHealth = mBatteryProps.batteryHealth;
- mLastBatteryPresent = mBatteryProps.batteryPresent;
- mLastBatteryLevel = mBatteryProps.batteryLevel;
+ mLastBatteryStatus = mHealthInfo.legacy.batteryStatus;
+ mLastBatteryHealth = mHealthInfo.legacy.batteryHealth;
+ mLastBatteryPresent = mHealthInfo.legacy.batteryPresent;
+ mLastBatteryLevel = mHealthInfo.legacy.batteryLevel;
mLastPlugType = mPlugType;
- mLastBatteryVoltage = mBatteryProps.batteryVoltage;
- mLastBatteryTemperature = mBatteryProps.batteryTemperature;
- mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent;
- mLastMaxChargingVoltage = mBatteryProps.maxChargingVoltage;
- mLastChargeCounter = mBatteryProps.batteryChargeCounter;
+ mLastBatteryVoltage = mHealthInfo.legacy.batteryVoltage;
+ mLastBatteryTemperature = mHealthInfo.legacy.batteryTemperature;
+ mLastMaxChargingCurrent = mHealthInfo.legacy.maxChargingCurrent;
+ mLastMaxChargingVoltage = mHealthInfo.legacy.maxChargingVoltage;
+ mLastChargeCounter = mHealthInfo.legacy.batteryChargeCounter;
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
}
@@ -543,38 +572,26 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
- int icon = getIconLocked(mBatteryProps.batteryLevel);
+ int icon = getIconLocked(mHealthInfo.legacy.batteryLevel);
intent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
- intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
- intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
- intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
- intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel);
+ intent.putExtra(BatteryManager.EXTRA_STATUS, mHealthInfo.legacy.batteryStatus);
+ intent.putExtra(BatteryManager.EXTRA_HEALTH, mHealthInfo.legacy.batteryHealth);
+ intent.putExtra(BatteryManager.EXTRA_PRESENT, mHealthInfo.legacy.batteryPresent);
+ intent.putExtra(BatteryManager.EXTRA_LEVEL, mHealthInfo.legacy.batteryLevel);
intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
- intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage);
- intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature);
- intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology);
+ intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.legacy.batteryVoltage);
+ intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.legacy.batteryTemperature);
+ intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mHealthInfo.legacy.batteryTechnology);
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
- intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent);
- intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE, mBatteryProps.maxChargingVoltage);
- intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mBatteryProps.batteryChargeCounter);
+ intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mHealthInfo.legacy.maxChargingCurrent);
+ intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE, mHealthInfo.legacy.maxChargingVoltage);
+ intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.legacy.batteryChargeCounter);
if (DEBUG) {
- Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
- ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
- ", health:" + mBatteryProps.batteryHealth +
- ", present:" + mBatteryProps.batteryPresent +
- ", voltage: " + mBatteryProps.batteryVoltage +
- ", temperature: " + mBatteryProps.batteryTemperature +
- ", technology: " + mBatteryProps.batteryTechnology +
- ", AC powered:" + mBatteryProps.chargerAcOnline +
- ", USB powered:" + mBatteryProps.chargerUsbOnline +
- ", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
- ", icon:" + icon + ", invalid charger:" + mInvalidCharger +
- ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent +
- ", maxChargingVoltage:" + mBatteryProps.maxChargingVoltage +
- ", chargeCounter:" + mBatteryProps.batteryChargeCounter);
+ Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. scale:" + BATTERY_SCALE
+ + ", info:" + mHealthInfo.toString());
}
mHandler.post(new Runnable() {
@@ -635,14 +652,14 @@
long durationThreshold = Long.parseLong(durationThresholdString);
int dischargeThreshold = Integer.parseInt(dischargeThresholdString);
if (duration <= durationThreshold &&
- mDischargeStartLevel - mBatteryProps.batteryLevel >= dischargeThreshold) {
+ mDischargeStartLevel - mHealthInfo.legacy.batteryLevel >= dischargeThreshold) {
// If the discharge cycle is bad enough we want to know about it.
logBatteryStatsLocked();
}
if (DEBUG) Slog.v(TAG, "duration threshold: " + durationThreshold +
" discharge threshold: " + dischargeThreshold);
if (DEBUG) Slog.v(TAG, "duration: " + duration + " discharge: " +
- (mDischargeStartLevel - mBatteryProps.batteryLevel));
+ (mDischargeStartLevel - mHealthInfo.legacy.batteryLevel));
} catch (NumberFormatException e) {
Slog.e(TAG, "Invalid DischargeThresholds GService string: " +
durationThresholdString + " or " + dischargeThresholdString);
@@ -651,14 +668,14 @@
}
private int getIconLocked(int level) {
- if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
+ if (mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
return com.android.internal.R.drawable.stat_sys_battery_charge;
- } else if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
+ } else if (mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
return com.android.internal.R.drawable.stat_sys_battery;
- } else if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
- || mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
+ } else if (mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
+ || mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
- && mBatteryProps.batteryLevel >= 100) {
+ && mHealthInfo.legacy.batteryLevel >= 100) {
return com.android.internal.R.drawable.stat_sys_battery_charge;
} else {
return com.android.internal.R.drawable.stat_sys_battery;
@@ -720,11 +737,11 @@
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
if (!mUpdatesStopped) {
- mLastBatteryProps.set(mBatteryProps);
+ copy(mLastHealthInfo, mHealthInfo);
}
- mBatteryProps.chargerAcOnline = false;
- mBatteryProps.chargerUsbOnline = false;
- mBatteryProps.chargerWirelessOnline = false;
+ mHealthInfo.legacy.chargerAcOnline = false;
+ mHealthInfo.legacy.chargerUsbOnline = false;
+ mHealthInfo.legacy.chargerWirelessOnline = false;
long ident = Binder.clearCallingIdentity();
try {
mUpdatesStopped = true;
@@ -751,30 +768,30 @@
}
try {
if (!mUpdatesStopped) {
- mLastBatteryProps.set(mBatteryProps);
+ copy(mLastHealthInfo, mHealthInfo);
}
boolean update = true;
switch (key) {
case "present":
- mBatteryProps.batteryPresent = Integer.parseInt(value) != 0;
+ mHealthInfo.legacy.batteryPresent = Integer.parseInt(value) != 0;
break;
case "ac":
- mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
+ mHealthInfo.legacy.chargerAcOnline = Integer.parseInt(value) != 0;
break;
case "usb":
- mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
+ mHealthInfo.legacy.chargerUsbOnline = Integer.parseInt(value) != 0;
break;
case "wireless":
- mBatteryProps.chargerWirelessOnline = Integer.parseInt(value) != 0;
+ mHealthInfo.legacy.chargerWirelessOnline = Integer.parseInt(value) != 0;
break;
case "status":
- mBatteryProps.batteryStatus = Integer.parseInt(value);
+ mHealthInfo.legacy.batteryStatus = Integer.parseInt(value);
break;
case "level":
- mBatteryProps.batteryLevel = Integer.parseInt(value);
+ mHealthInfo.legacy.batteryLevel = Integer.parseInt(value);
break;
case "temp":
- mBatteryProps.batteryTemperature = Integer.parseInt(value);
+ mHealthInfo.legacy.batteryTemperature = Integer.parseInt(value);
break;
case "invalid":
mInvalidCharger = Integer.parseInt(value);
@@ -806,7 +823,7 @@
try {
if (mUpdatesStopped) {
mUpdatesStopped = false;
- mBatteryProps.set(mLastBatteryProps);
+ copy(mHealthInfo, mLastHealthInfo);
processValuesFromShellLocked(pw, opts);
}
} finally {
@@ -833,20 +850,20 @@
if (mUpdatesStopped) {
pw.println(" (UPDATES STOPPED -- use 'reset' to restart)");
}
- pw.println(" AC powered: " + mBatteryProps.chargerAcOnline);
- pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline);
- pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline);
- pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent);
- pw.println(" Max charging voltage: " + mBatteryProps.maxChargingVoltage);
- pw.println(" Charge counter: " + mBatteryProps.batteryChargeCounter);
- pw.println(" status: " + mBatteryProps.batteryStatus);
- pw.println(" health: " + mBatteryProps.batteryHealth);
- pw.println(" present: " + mBatteryProps.batteryPresent);
- pw.println(" level: " + mBatteryProps.batteryLevel);
+ pw.println(" AC powered: " + mHealthInfo.legacy.chargerAcOnline);
+ pw.println(" USB powered: " + mHealthInfo.legacy.chargerUsbOnline);
+ pw.println(" Wireless powered: " + mHealthInfo.legacy.chargerWirelessOnline);
+ pw.println(" Max charging current: " + mHealthInfo.legacy.maxChargingCurrent);
+ pw.println(" Max charging voltage: " + mHealthInfo.legacy.maxChargingVoltage);
+ pw.println(" Charge counter: " + mHealthInfo.legacy.batteryChargeCounter);
+ pw.println(" status: " + mHealthInfo.legacy.batteryStatus);
+ pw.println(" health: " + mHealthInfo.legacy.batteryHealth);
+ pw.println(" present: " + mHealthInfo.legacy.batteryPresent);
+ pw.println(" level: " + mHealthInfo.legacy.batteryLevel);
pw.println(" scale: " + BATTERY_SCALE);
- pw.println(" voltage: " + mBatteryProps.batteryVoltage);
- pw.println(" temperature: " + mBatteryProps.batteryTemperature);
- pw.println(" technology: " + mBatteryProps.batteryTechnology);
+ pw.println(" voltage: " + mHealthInfo.legacy.batteryVoltage);
+ pw.println(" temperature: " + mHealthInfo.legacy.batteryTemperature);
+ pw.println(" technology: " + mHealthInfo.legacy.batteryTechnology);
} else {
Shell shell = new Shell();
shell.exec(mBinderService, null, fd, null, args, null, new ResultReceiver(null));
@@ -860,25 +877,25 @@
synchronized (mLock) {
proto.write(BatteryServiceDumpProto.ARE_UPDATES_STOPPED, mUpdatesStopped);
int batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_NONE;
- if (mBatteryProps.chargerAcOnline) {
+ if (mHealthInfo.legacy.chargerAcOnline) {
batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_AC;
- } else if (mBatteryProps.chargerUsbOnline) {
+ } else if (mHealthInfo.legacy.chargerUsbOnline) {
batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_USB;
- } else if (mBatteryProps.chargerWirelessOnline) {
+ } else if (mHealthInfo.legacy.chargerWirelessOnline) {
batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_WIRELESS;
}
proto.write(BatteryServiceDumpProto.PLUGGED, batteryPluggedValue);
- proto.write(BatteryServiceDumpProto.MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent);
- proto.write(BatteryServiceDumpProto.MAX_CHARGING_VOLTAGE, mBatteryProps.maxChargingVoltage);
- proto.write(BatteryServiceDumpProto.CHARGE_COUNTER, mBatteryProps.batteryChargeCounter);
- proto.write(BatteryServiceDumpProto.STATUS, mBatteryProps.batteryStatus);
- proto.write(BatteryServiceDumpProto.HEALTH, mBatteryProps.batteryHealth);
- proto.write(BatteryServiceDumpProto.IS_PRESENT, mBatteryProps.batteryPresent);
- proto.write(BatteryServiceDumpProto.LEVEL, mBatteryProps.batteryLevel);
+ proto.write(BatteryServiceDumpProto.MAX_CHARGING_CURRENT, mHealthInfo.legacy.maxChargingCurrent);
+ proto.write(BatteryServiceDumpProto.MAX_CHARGING_VOLTAGE, mHealthInfo.legacy.maxChargingVoltage);
+ proto.write(BatteryServiceDumpProto.CHARGE_COUNTER, mHealthInfo.legacy.batteryChargeCounter);
+ proto.write(BatteryServiceDumpProto.STATUS, mHealthInfo.legacy.batteryStatus);
+ proto.write(BatteryServiceDumpProto.HEALTH, mHealthInfo.legacy.batteryHealth);
+ proto.write(BatteryServiceDumpProto.IS_PRESENT, mHealthInfo.legacy.batteryPresent);
+ proto.write(BatteryServiceDumpProto.LEVEL, mHealthInfo.legacy.batteryLevel);
proto.write(BatteryServiceDumpProto.SCALE, BATTERY_SCALE);
- proto.write(BatteryServiceDumpProto.VOLTAGE, mBatteryProps.batteryVoltage);
- proto.write(BatteryServiceDumpProto.TEMPERATURE, mBatteryProps.batteryTemperature);
- proto.write(BatteryServiceDumpProto.TECHNOLOGY, mBatteryProps.batteryTechnology);
+ proto.write(BatteryServiceDumpProto.VOLTAGE, mHealthInfo.legacy.batteryVoltage);
+ proto.write(BatteryServiceDumpProto.TEMPERATURE, mHealthInfo.legacy.batteryTemperature);
+ proto.write(BatteryServiceDumpProto.TECHNOLOGY, mHealthInfo.legacy.batteryTechnology);
}
proto.flush();
}
@@ -911,8 +928,8 @@
* Synchronize on BatteryService.
*/
public void updateLightsLocked() {
- final int level = mBatteryProps.batteryLevel;
- final int status = mBatteryProps.batteryStatus;
+ final int level = mHealthInfo.legacy.batteryLevel;
+ final int status = mHealthInfo.legacy.batteryStatus;
if (level < mLowBatteryWarningLevel) {
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
// Solid red when battery is charging
@@ -985,7 +1002,7 @@
@Override
public int getBatteryLevel() {
synchronized (mLock) {
- return mBatteryProps.batteryLevel;
+ return mHealthInfo.legacy.batteryLevel;
}
}
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 40499c9..119c9df 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -38,6 +38,8 @@
import android.content.Intent;
import android.content.IntentFilter;
+import android.util.proto.ProtoOutputStream;
+
import com.android.internal.util.FastPrintWriter;
/**
@@ -279,6 +281,31 @@
return printedSomething;
}
+ void writeProtoMap(ProtoOutputStream proto, long fieldId, ArrayMap<String, F[]> map) {
+ int N = map.size();
+ for (int mapi = 0; mapi < N; mapi++) {
+ long token = proto.start(fieldId);
+ proto.write(IntentResolverProto.ArrayMapEntry.KEY, map.keyAt(mapi));
+ for (F f : map.valueAt(mapi)) {
+ if (f != null) {
+ proto.write(IntentResolverProto.ArrayMapEntry.VALUES, f.toString());
+ }
+ }
+ proto.end(token);
+ }
+ }
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ writeProtoMap(proto, IntentResolverProto.FULL_MIME_TYPES, mTypeToFilter);
+ writeProtoMap(proto, IntentResolverProto.BASE_MIME_TYPES, mBaseTypeToFilter);
+ writeProtoMap(proto, IntentResolverProto.WILD_MIME_TYPES, mWildTypeToFilter);
+ writeProtoMap(proto, IntentResolverProto.SCHEMES, mSchemeToFilter);
+ writeProtoMap(proto, IntentResolverProto.NON_DATA_ACTIONS, mActionToFilter);
+ writeProtoMap(proto, IntentResolverProto.MIME_TYPED_ACTIONS, mTypedActionToFilter);
+ proto.end(token);
+ }
+
public boolean dump(PrintWriter out, String title, String prefix, String packageName,
boolean printFilter, boolean collapseDuplicates) {
String innerPrefix = prefix + " ";
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 8bcbfbe..8839cfc 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -16,9 +16,6 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.getStackIdForWindowingMode;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -213,7 +210,11 @@
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
// TODO: Should be okay to have stacks with with undefined windowing mode long term, but
// have to set them to something for now due to logic that depending on them.
- windowingMode = WINDOWING_MODE_FULLSCREEN;
+ windowingMode = getWindowingMode(); // Put in current display's windowing mode
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ // Else fullscreen for now...
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
+ }
}
final boolean inSplitScreenMode = hasSplitScreenStack();
@@ -228,24 +229,7 @@
windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
- int stackId = INVALID_STACK_ID;
- if (mDisplayId == DEFAULT_DISPLAY && (activityType == ACTIVITY_TYPE_STANDARD
- || activityType == ACTIVITY_TYPE_UNDEFINED)) {
- // TODO: Will be removed once we are no longer using static stack ids.
- stackId = getStackIdForWindowingMode(windowingMode);
- if (stackId == INVALID_STACK_ID) {
- // Whatever...put in fullscreen stack for now.
- stackId = FULLSCREEN_WORKSPACE_STACK_ID;
- }
- final T stack = getStack(stackId);
- if (stack != null) {
- return stack;
- }
- }
-
- if (stackId == INVALID_STACK_ID) {
- stackId = mSupervisor.getNextStackId();
- }
+ final int stackId = mSupervisor.getNextStackId();
final T stack = createStackUnchecked(windowingMode, activityType, stackId, onTop);
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 3a9bf12..ceb2ad6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -59,7 +59,6 @@
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_IDLE = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_IMMERSIVE = DEBUG_ALL || false;
- static final boolean DEBUG_LOCKSCREEN = DEBUG_ALL || false;
static final boolean DEBUG_LOCKTASK = DEBUG_ALL || false;
static final boolean DEBUG_LRU = DEBUG_ALL || false;
static final boolean DEBUG_MU = DEBUG_ALL || false;
@@ -74,10 +73,10 @@
static final boolean DEBUG_PROVIDER = DEBUG_ALL || false;
static final boolean DEBUG_PSS = DEBUG_ALL || false;
static final boolean DEBUG_RECENTS = DEBUG_ALL || false;
+ static final boolean DEBUG_RECENTS_TRIM_TASKS = DEBUG_RECENTS || false;
static final boolean DEBUG_RELEASE = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_RESULTS = DEBUG_ALL || false;
static final boolean DEBUG_SAVED_STATE = DEBUG_ALL_ACTIVITIES || false;
- static final boolean DEBUG_SCREENSHOTS = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_SERVICE = DEBUG_ALL || false;
static final boolean DEBUG_FOREGROUND_SERVICE = DEBUG_ALL || false;
static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false;
@@ -85,7 +84,6 @@
static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
static final boolean DEBUG_TASKS = DEBUG_ALL || false;
- static final boolean DEBUG_THUMBNAILS = DEBUG_ALL || false;
static final boolean DEBUG_TRANSITION = DEBUG_ALL || false;
static final boolean DEBUG_UID_OBSERVERS = DEBUG_ALL || false;
static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
@@ -105,7 +103,6 @@
static final String POSTFIX_FOCUS = (APPEND_CATEGORY_NAME) ? "_Focus" : "";
static final String POSTFIX_IDLE = (APPEND_CATEGORY_NAME) ? "_Idle" : "";
static final String POSTFIX_IMMERSIVE = (APPEND_CATEGORY_NAME) ? "_Immersive" : "";
- static final String POSTFIX_LOCKSCREEN = (APPEND_CATEGORY_NAME) ? "_LockScreen" : "";
static final String POSTFIX_LOCKTASK = (APPEND_CATEGORY_NAME) ? "_LockTask" : "";
static final String POSTFIX_LRU = (APPEND_CATEGORY_NAME) ? "_LRU" : "";
static final String POSTFIX_MU = "_MU";
@@ -122,7 +119,6 @@
static final String POSTFIX_RELEASE = (APPEND_CATEGORY_NAME) ? "_Release" : "";
static final String POSTFIX_RESULTS = (APPEND_CATEGORY_NAME) ? "_Results" : "";
static final String POSTFIX_SAVED_STATE = (APPEND_CATEGORY_NAME) ? "_SavedState" : "";
- static final String POSTFIX_SCREENSHOTS = (APPEND_CATEGORY_NAME) ? "_Screenshots" : "";
static final String POSTFIX_SERVICE = (APPEND_CATEGORY_NAME) ? "_Service" : "";
static final String POSTFIX_SERVICE_EXECUTING =
(APPEND_CATEGORY_NAME) ? "_ServiceExecuting" : "";
@@ -130,13 +126,11 @@
static final String POSTFIX_STATES = (APPEND_CATEGORY_NAME) ? "_States" : "";
static final String POSTFIX_SWITCH = (APPEND_CATEGORY_NAME) ? "_Switch" : "";
static final String POSTFIX_TASKS = (APPEND_CATEGORY_NAME) ? "_Tasks" : "";
- static final String POSTFIX_THUMBNAILS = (APPEND_CATEGORY_NAME) ? "_Thumbnails" : "";
static final String POSTFIX_TRANSITION = (APPEND_CATEGORY_NAME) ? "_Transition" : "";
static final String POSTFIX_UID_OBSERVERS = (APPEND_CATEGORY_NAME)
? "_UidObservers" : "";
static final String POSTFIX_URI_PERMISSION = (APPEND_CATEGORY_NAME) ? "_UriPermission" : "";
static final String POSTFIX_USER_LEAVING = (APPEND_CATEGORY_NAME) ? "_UserLeaving" : "";
static final String POSTFIX_VISIBILITY = (APPEND_CATEGORY_NAME) ? "_Visibility" : "";
- static final String POSTFIX_VISIBLE_BEHIND = (APPEND_CATEGORY_NAME) ? "_VisibleBehind" : "";
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 26401a7..5e10ada 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -27,18 +27,10 @@
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
-import static android.app.ActivityManager.StackId.isStaticStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
@@ -57,6 +49,9 @@
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.os.Build.VERSION_CODES.N;
+import static android.os.IServiceManager.DUMP_PRIORITY_CRITICAL;
+import static android.os.IServiceManager.DUMP_PRIORITY_HIGH;
+import static android.os.IServiceManager.DUMP_PRIORITY_NORMAL;
import static android.os.Process.BLUETOOTH_UID;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.FIRST_ISOLATED_UID;
@@ -137,7 +132,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROVIDER;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
@@ -403,6 +397,9 @@
import com.android.server.ThreadPriorityBooster;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.am.proto.ActivityManagerServiceProto;
+import com.android.server.am.proto.BroadcastProto;
+import com.android.server.am.proto.StickyBroadcastProto;
import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.pm.Installer;
@@ -738,9 +735,6 @@
doDump(fd, pw, new String[] {"associations"});
}
doDump(fd, pw, new String[] {"processes"});
- doDump(fd, pw, new String[] {"-v", "all"});
- doDump(fd, pw, new String[] {"service", "all"});
- doDump(fd, pw, new String[] {"provider", "all"});
}
@Override
@@ -1739,9 +1733,6 @@
*/
private boolean mUserIsMonkey;
- /** Flag whether the device has a Recents UI */
- boolean mHasRecents;
-
/** The dimensions of the thumbnails in the Recents UI. */
int mThumbnailWidth;
int mThumbnailHeight;
@@ -2112,7 +2103,8 @@
String text = mContext.getString(R.string.heavy_weight_notification,
context.getApplicationInfo().loadLabel(context.getPackageManager()));
Notification notification =
- new Notification.Builder(context, SystemNotificationChannels.DEVELOPER)
+ new Notification.Builder(context,
+ SystemNotificationChannels.HEAVY_WEIGHT_APP)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setWhen(0)
.setOngoing(true)
@@ -2146,7 +2138,7 @@
}
try {
inm.cancelNotificationWithTag("android", null,
- SystemMessage.NOTE_HEAVY_WEIGHT_NOTIFICATION, msg.arg1);
+ SystemMessage.NOTE_HEAVY_WEIGHT_NOTIFICATION, msg.arg1);
} catch (RuntimeException e) {
Slog.w(ActivityManagerService.TAG,
"Error canceling notification for service", e);
@@ -2504,13 +2496,16 @@
public void setSystemProcess() {
try {
- ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
+ ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
+ DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_NORMAL);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
- ServiceManager.addService("meminfo", new MemBinder(this));
+ ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
+ DUMP_PRIORITY_HIGH | DUMP_PRIORITY_NORMAL);
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
- ServiceManager.addService("cpuinfo", new CpuBinder(this));
+ ServiceManager.addService("cpuinfo", new CpuBinder(this),
+ /* allowIsolated= */ false, DUMP_PRIORITY_CRITICAL);
}
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
@@ -2785,6 +2780,7 @@
new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
mActivityStarter = new ActivityStarter(this, mStackSupervisor);
mRecentTasks = new RecentTasks(this, mStackSupervisor);
+ mStackSupervisor.setRecentTasks(mRecentTasks);
mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);
mProcessCpuThread = new Thread("CpuTracker") {
@@ -3242,11 +3238,12 @@
// stack implementation changes in the future, keep in mind that the use of the fullscreen
// stack is a means to move the activity to the main display and a moveActivityToDisplay()
// option would be a better choice here.
- if (r.requestedVrComponent != null && r.getStackId() >= FIRST_DYNAMIC_STACK_ID) {
+ if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
+ " to main stack for VR");
- setTaskWindowingMode(r.getTask().taskId,
- WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
+ final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getOrCreateStack(
+ WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
+ moveTaskToStack(r.getTask().taskId, stack.mStackId, true /* toTop */);
}
mHandler.sendMessage(
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
@@ -5096,11 +5093,12 @@
}
synchronized(this) {
- if (mHeavyWeightProcess == null) {
+ final ProcessRecord proc = mHeavyWeightProcess;
+ if (proc == null) {
return;
}
- ArrayList<ActivityRecord> activities = new ArrayList<>(mHeavyWeightProcess.activities);
+ ArrayList<ActivityRecord> activities = new ArrayList<>(proc.activities);
for (int i = 0; i < activities.size(); i++) {
ActivityRecord r = activities.get(i);
if (!r.finishing && r.isInStackLocked()) {
@@ -5110,7 +5108,7 @@
}
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
- mHeavyWeightProcess.userId, 0));
+ proc.userId, 0));
mHeavyWeightProcess = null;
}
}
@@ -5964,16 +5962,7 @@
if (appInfo != null) {
forceStopPackageLocked(packageName, appInfo.uid, "clear data");
- // Remove all tasks match the cleared application package and user
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- final TaskRecord tr = mRecentTasks.get(i);
- final String taskPackageName =
- tr.getBaseIntent().getComponent().getPackageName();
- if (tr.userId != resolvedUserId) continue;
- if (!taskPackageName.equals(packageName)) continue;
- mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
- REMOVE_FROM_RECENTS);
- }
+ mRecentTasks.removeTasksByPackageName(packageName, resolvedUserId);
}
}
@@ -6554,7 +6543,7 @@
}
// Clean-up disabled tasks
- cleanupDisabledPackageTasksLocked(packageName, disabledClasses, userId);
+ mRecentTasks.cleanupDisabledPackageTasksLocked(packageName, disabledClasses, userId);
// Clean-up disabled services.
mServices.bringDownDisabledPackageServicesLocked(
@@ -8085,8 +8074,8 @@
}
private boolean isInPictureInPictureMode(ActivityRecord r) {
- if (r == null || r.getStack() == null || !r.getStack().isPinnedStack() ||
- r.getStack().isInStackLocked(r) == null) {
+ if (r == null || r.getStack() == null || !r.inPinnedWindowingMode()
+ || r.getStack().isInStackLocked(r) == null) {
return false;
}
@@ -8180,7 +8169,7 @@
// Only update the saved args from the args that are set
r.pictureInPictureArgs.copyOnlySet(params);
- if (r.getStack().getStackId() == PINNED_STACK_ID) {
+ if (r.inPinnedWindowingMode()) {
// If the activity is already in picture-in-picture, update the pinned stack now
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP
@@ -9801,35 +9790,12 @@
public List<IBinder> getAppTasks(String callingPackage) {
int callingUid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
-
- synchronized(this) {
- ArrayList<IBinder> list = new ArrayList<IBinder>();
- try {
- if (DEBUG_ALL) Slog.v(TAG, "getAppTasks");
-
- final int N = mRecentTasks.size();
- for (int i = 0; i < N; i++) {
- TaskRecord tr = mRecentTasks.get(i);
- // Skip tasks that do not match the caller. We don't need to verify
- // callingPackage, because we are also limiting to callingUid and know
- // that will limit to the correct security sandbox.
- if (tr.effectiveUid != callingUid) {
- continue;
- }
- Intent intent = tr.getBaseIntent();
- if (intent == null ||
- !callingPackage.equals(intent.getComponent().getPackageName())) {
- continue;
- }
- ActivityManager.RecentTaskInfo taskInfo =
- createRecentTaskInfoFromTaskRecord(tr);
- AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
- list.add(taskImpl.asBinder());
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
+ try {
+ synchronized(this) {
+ return mRecentTasks.getAppTasksList(callingUid, callingPackage);
}
- return list;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@@ -9852,58 +9818,6 @@
return list;
}
- /**
- * Creates a new RecentTaskInfo from a TaskRecord.
- */
- private ActivityManager.RecentTaskInfo createRecentTaskInfoFromTaskRecord(TaskRecord tr) {
- // Update the task description to reflect any changes in the task stack
- tr.updateTaskDescription();
-
- // Compose the recent task info
- ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
- rti.id = tr.getTopActivity() == null ? INVALID_TASK_ID : tr.taskId;
- rti.persistentId = tr.taskId;
- rti.baseIntent = new Intent(tr.getBaseIntent());
- rti.origActivity = tr.origActivity;
- rti.realActivity = tr.realActivity;
- rti.description = tr.lastDescription;
- rti.stackId = tr.getStackId();
- rti.userId = tr.userId;
- rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
- rti.firstActiveTime = tr.firstActiveTime;
- rti.lastActiveTime = tr.lastActiveTime;
- rti.affiliatedTaskId = tr.mAffiliatedTaskId;
- rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
- rti.numActivities = 0;
- if (tr.mBounds != null) {
- rti.bounds = new Rect(tr.mBounds);
- }
- rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
- rti.resizeMode = tr.mResizeMode;
- rti.configuration.setTo(tr.getConfiguration());
-
- ActivityRecord base = null;
- ActivityRecord top = null;
- ActivityRecord tmp;
-
- for (int i = tr.mActivities.size() - 1; i >= 0; --i) {
- tmp = tr.mActivities.get(i);
- if (tmp.finishing) {
- continue;
- }
- base = tmp;
- if (top == null || (top.state == ActivityState.INITIALIZING)) {
- top = base;
- }
- rti.numActivities++;
- }
-
- rti.baseActivity = (base != null) ? base.intent.getComponent() : null;
- rti.topActivity = (top != null) ? top.intent.getComponent() : null;
-
- return rti;
- }
-
private boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
boolean allowed = checkPermission(android.Manifest.permission.REAL_GET_TASKS,
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
@@ -9937,118 +9851,15 @@
final int callingUid = Binder.getCallingUid();
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
false, ALLOW_FULL_ONLY, "getRecentTasks", null);
+ final boolean allowed = isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
+ callingUid);
+ final boolean detailed = checkCallingPermission(
+ android.Manifest.permission.GET_DETAILED_TASKS)
+ == PackageManager.PERMISSION_GRANTED;
- final boolean includeProfiles = (flags & ActivityManager.RECENT_INCLUDE_PROFILES) != 0;
- final boolean withExcluded = (flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0;
synchronized (this) {
- final boolean allowed = isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
+ return mRecentTasks.getRecentTasks(maxNum, flags, allowed, detailed, userId,
callingUid);
- final boolean detailed = checkCallingPermission(
- android.Manifest.permission.GET_DETAILED_TASKS)
- == PackageManager.PERMISSION_GRANTED;
-
- if (!isUserRunning(userId, ActivityManager.FLAG_AND_UNLOCKED)) {
- Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
- return ParceledListSlice.emptyList();
- }
- mRecentTasks.loadUserRecentsLocked(userId);
-
- final int recentsCount = mRecentTasks.size();
- ArrayList<ActivityManager.RecentTaskInfo> res =
- new ArrayList<>(maxNum < recentsCount ? maxNum : recentsCount);
-
- final Set<Integer> includedUsers;
- if (includeProfiles) {
- includedUsers = mUserController.getProfileIds(userId);
- } else {
- includedUsers = new HashSet<>();
- }
- includedUsers.add(Integer.valueOf(userId));
-
- for (int i = 0; i < recentsCount && maxNum > 0; i++) {
- TaskRecord tr = mRecentTasks.get(i);
- // Only add calling user or related users recent tasks
- if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
- continue;
- }
-
- if (tr.realActivitySuspended) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, activity suspended: " + tr);
- continue;
- }
-
- // Return the entry if desired by the caller. We always return
- // the first entry, because callers always expect this to be the
- // foreground app. We may filter others if the caller has
- // not supplied RECENT_WITH_EXCLUDED and there is some reason
- // we should exclude the entry.
-
- if (i == 0
- || withExcluded
- || (tr.intent == null)
- || ((tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
- == 0)) {
- if (!allowed) {
- // If the caller doesn't have the GET_TASKS permission, then only
- // allow them to see a small subset of tasks -- their own and home.
- if (!tr.isActivityTypeHome() && tr.effectiveUid != callingUid) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not allowed: " + tr);
- continue;
- }
- }
- final ActivityStack stack = tr.getStack();
- if ((flags & ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS) != 0) {
- if (stack != null && stack.isHomeOrRecentsStack()) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, home or recents stack task: " + tr);
- continue;
- }
- }
- if ((flags & ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK) != 0) {
- if (stack != null && stack.isDockedStack() && stack.topTask() == tr) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, top task in docked stack: " + tr);
- continue;
- }
- }
- if ((flags & ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS) != 0) {
- if (stack != null && stack.isPinnedStack()) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, pinned stack task: " + tr);
- continue;
- }
- }
- if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
- // Don't include auto remove tasks that are finished or finishing.
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, auto-remove without activity: " + tr);
- continue;
- }
- if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0
- && !tr.isAvailable) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, unavail real act: " + tr);
- continue;
- }
-
- if (!tr.mUserSetupComplete) {
- // Don't include task launched while user is not done setting-up.
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, user setup not complete: " + tr);
- continue;
- }
-
- ActivityManager.RecentTaskInfo rti = createRecentTaskInfoFromTaskRecord(tr);
- if (!detailed) {
- rti.baseIntent.replaceExtras((Bundle)null);
- }
-
- res.add(rti);
- maxNum--;
- }
- }
- return new ParceledListSlice<>(res);
}
}
@@ -10120,23 +9931,10 @@
TaskRecord task = new TaskRecord(this,
mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
ainfo, intent, description);
-
- int trimIdx = mRecentTasks.trimForTaskLocked(task, false);
- if (trimIdx >= 0) {
- // If this would have caused a trim, then we'll abort because that
- // means it would be added at the end of the list but then just removed.
+ if (!mRecentTasks.addToBottom(task)) {
return INVALID_TASK_ID;
}
-
- final int N = mRecentTasks.size();
- if (N >= (ActivityManager.getMaxRecentTasksStatic()-1)) {
- final TaskRecord tr = mRecentTasks.remove(N - 1);
- tr.removedFromRecents();
- }
-
- task.inRecents = true;
- mRecentTasks.add(task);
- r.getStack().addTask(task, false, "addAppTask");
+ r.getStack().addTask(task, !ON_TOP, "addAppTask");
// TODO: Send the thumbnail to WM to store it.
@@ -10352,38 +10150,6 @@
mWindowManager.executeAppTransition();
}
- private void removeTasksByPackageNameLocked(String packageName, int userId) {
- // Remove all tasks with activities in the specified package from the list of recent tasks
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- TaskRecord tr = mRecentTasks.get(i);
- if (tr.userId != userId) continue;
-
- ComponentName cn = tr.intent.getComponent();
- if (cn != null && cn.getPackageName().equals(packageName)) {
- // If the package name matches, remove the task.
- mStackSupervisor.removeTaskByIdLocked(tr.taskId, true, REMOVE_FROM_RECENTS);
- }
- }
- }
-
- private void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses,
- int userId) {
-
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- TaskRecord tr = mRecentTasks.get(i);
- if (userId != UserHandle.USER_ALL && tr.userId != userId) {
- continue;
- }
-
- ComponentName cn = tr.intent.getComponent();
- final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
- && (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
- if (sameComponent) {
- mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS);
- }
- }
- }
-
@Override
public void removeStack(int stackId) {
enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
@@ -10610,7 +10376,7 @@
}
final ActivityStack stack = r.getStack();
- if (stack == null || stack.mStackId != FREEFORM_WORKSPACE_STACK_ID) {
+ if (stack == null || !stack.inFreeformWindowingMode()) {
throw new IllegalStateException(
"exitFreeformMode: You can only go fullscreen from freeform.");
}
@@ -10678,27 +10444,20 @@
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
+ " to stackId=" + stackId + " toTop=" + toTop);
- if (stackId == DOCKED_STACK_ID) {
- mWindowManager.setDockedStackCreateState(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
- null /* initialBounds */);
- }
- ActivityStack stack = mStackSupervisor.getStack(stackId);
+ final ActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
- if (!isStaticStack(stackId)) {
- throw new IllegalStateException(
- "moveTaskToStack: No stack for stackId=" + stackId);
- }
- final ActivityDisplay display = task.getStack().getDisplay();
- final int windowingMode =
- getWindowingModeForStackId(stackId, display.hasSplitScreenStack());
- stack = display.getOrCreateStack(windowingMode,
- task.getStack().getActivityType(), toTop);
+ throw new IllegalStateException(
+ "moveTaskToStack: No stack for stackId=" + stackId);
}
if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException("moveTaskToStack: Attempt to move task "
+ taskId + " to stack " + stackId);
}
+ if (stack.inSplitScreenPrimaryWindowingMode()) {
+ mWindowManager.setDockedStackCreateState(
+ DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
+ }
task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
"moveTaskToStack");
} finally {
@@ -10770,7 +10529,7 @@
final ActivityStack stack =
mStackSupervisor.getDefaultDisplay().getSplitScreenStack();
if (toTop) {
- mStackSupervisor.resizeStackLocked(stack.mStackId, null /* destBounds */,
+ mStackSupervisor.resizeStackLocked(stack, null /* destBounds */,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
true /* preserveWindows */, true /* allowResizeInDockedMode */,
!DEFER_RESUME);
@@ -10863,7 +10622,12 @@
stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds,
animationDuration, false /* fromFullscreen */);
} else {
- mStackSupervisor.resizeStackLocked(stackId, destBounds, null /* tempTaskBounds */,
+ final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ if (stack == null) {
+ Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
+ return;
+ }
+ mStackSupervisor.resizeStackLocked(stack, destBounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, preserveWindows,
allowResizeInDockedMode, !DEFER_RESUME);
}
@@ -14150,7 +13914,6 @@
// Load resources only after the current configuration has been set.
final Resources res = mContext.getResources();
- mHasRecents = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
mThumbnailWidth = res.getDimensionPixelSize(
com.android.internal.R.dimen.thumbnail_width);
mThumbnailHeight = res.getDimensionPixelSize(
@@ -15109,10 +14872,31 @@
long origId = Binder.clearCallingIdentity();
if (useProto) {
- //TODO: Options when dumping proto
final ProtoOutputStream proto = new ProtoOutputStream(fd);
- synchronized (this) {
- writeActivitiesToProtoLocked(proto);
+ String cmd = opti < args.length ? args[opti] : "";
+ opti++;
+
+ if ("activities".equals(cmd) || "a".equals(cmd)) {
+ // output proto is ActivityStackSupervisorProto
+ synchronized (this) {
+ writeActivitiesToProtoLocked(proto);
+ }
+ } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
+ // output proto is BroadcastProto
+ synchronized (this) {
+ writeBroadcastsToProtoLocked(proto);
+ }
+ } else {
+ // default option, dump everything, output is ActivityManagerServiceProto
+ synchronized (this) {
+ long activityToken = proto.start(ActivityManagerServiceProto.ACTIVITIES);
+ writeActivitiesToProtoLocked(proto);
+ proto.end(activityToken);
+
+ long broadcastToken = proto.start(ActivityManagerServiceProto.BROADCASTS);
+ writeBroadcastsToProtoLocked(proto);
+ proto.end(broadcastToken);
+ }
}
proto.flush();
Binder.restoreCallingIdentity(origId);
@@ -15138,7 +14922,9 @@
}
} else if ("recents".equals(cmd) || "r".equals(cmd)) {
synchronized (this) {
- dumpRecentsLocked(fd, pw, args, opti, true, dumpPackage);
+ if (mRecentTasks != null) {
+ mRecentTasks.dump(pw, true /* dumpAll */, dumpPackage);
+ }
}
} else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
String[] newArgs;
@@ -15359,7 +15145,9 @@
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+ if (mRecentTasks != null) {
+ mRecentTasks.dump(pw, dumpAll, dumpPackage);
+ }
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
@@ -15429,7 +15217,9 @@
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+ if (mRecentTasks != null) {
+ mRecentTasks.dump(pw, dumpAll, dumpPackage);
+ }
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
@@ -15463,7 +15253,8 @@
}
private void writeActivitiesToProtoLocked(ProtoOutputStream proto) {
- mStackSupervisor.writeToProto(proto, ACTIVITIES);
+ // The output proto of "activity --proto activities" is ActivityStackSupervisorProto
+ mStackSupervisor.writeToProto(proto);
}
private void dumpLastANRLocked(PrintWriter pw) {
@@ -15515,42 +15306,6 @@
}
}
- void dumpRecentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll, String dumpPackage) {
- pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
-
- boolean printedAnything = false;
-
- if (mRecentTasks != null && mRecentTasks.size() > 0) {
- boolean printedHeader = false;
-
- final int N = mRecentTasks.size();
- for (int i=0; i<N; i++) {
- TaskRecord tr = mRecentTasks.get(i);
- if (dumpPackage != null) {
- if (tr.realActivity == null ||
- !dumpPackage.equals(tr.realActivity.getPackageName())) {
- continue;
- }
- }
- if (!printedHeader) {
- pw.println(" Recent tasks:");
- printedHeader = true;
- printedAnything = true;
- }
- pw.print(" * Recent #"); pw.print(i); pw.print(": ");
- pw.println(tr);
- if (dumpAll) {
- mRecentTasks.get(i).dump(pw, " ");
- }
- }
- }
-
- if (!printedAnything) {
- pw.println(" (nothing)");
- }
- }
-
void dumpAssociationsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
pw.println("ACTIVITY MANAGER ASSOCIATIONS (dumpsys activity associations)");
@@ -16377,6 +16132,40 @@
}
}
+ void writeBroadcastsToProtoLocked(ProtoOutputStream proto) {
+ if (mRegisteredReceivers.size() > 0) {
+ Iterator it = mRegisteredReceivers.values().iterator();
+ while (it.hasNext()) {
+ ReceiverList r = (ReceiverList)it.next();
+ r.writeToProto(proto, BroadcastProto.RECEIVER_LIST);
+ }
+ }
+ mReceiverResolver.writeToProto(proto, BroadcastProto.RECEIVER_RESOLVER);
+ for (BroadcastQueue q : mBroadcastQueues) {
+ q.writeToProto(proto, BroadcastProto.BROADCAST_QUEUE);
+ }
+ for (int user=0; user<mStickyBroadcasts.size(); user++) {
+ long token = proto.start(BroadcastProto.STICKY_BROADCASTS);
+ proto.write(StickyBroadcastProto.USER, mStickyBroadcasts.keyAt(user));
+ for (Map.Entry<String, ArrayList<Intent>> ent
+ : mStickyBroadcasts.valueAt(user).entrySet()) {
+ long actionToken = proto.start(StickyBroadcastProto.ACTIONS);
+ proto.write(StickyBroadcastProto.StickyAction.NAME, ent.getKey());
+ for (Intent intent : ent.getValue()) {
+ intent.writeToProto(proto, StickyBroadcastProto.StickyAction.INTENTS,
+ false, true, true, false);
+ }
+ proto.end(actionToken);
+ }
+ proto.end(token);
+ }
+
+ long handlerToken = proto.start(BroadcastProto.HANDLER);
+ proto.write(BroadcastProto.MainHandler.HANDLER, mHandler.toString());
+ mHandler.getLooper().writeToProto(proto, BroadcastProto.MainHandler.LOOPER);
+ proto.end(handlerToken);
+ }
+
void dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
boolean needSep = false;
@@ -19365,7 +19154,7 @@
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(ssp, userId, true);
- removeTasksByPackageNameLocked(ssp, userId);
+ mRecentTasks.removeTasksByPackageName(ssp, userId);
mServices.forceStopPackageLocked(ssp, userId);
@@ -20702,9 +20491,10 @@
/** Helper method that requests bounds from WM and applies them to stack. */
private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
final Rect newStackBounds = new Rect();
- mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration(newStackBounds);
+ final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ stack.getBoundsForNewConfiguration(newStackBounds);
mStackSupervisor.resizeStackLocked(
- stackId, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
+ stack, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
}
@@ -24372,125 +24162,6 @@
}
/**
- * An implementation of IAppTask, that allows an app to manage its own tasks via
- * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that
- * only the process that calls getAppTasks() can call the AppTask methods.
- */
- class AppTaskImpl extends IAppTask.Stub {
- private int mTaskId;
- private int mCallingUid;
-
- public AppTaskImpl(int taskId, int callingUid) {
- mTaskId = taskId;
- mCallingUid = callingUid;
- }
-
- private void checkCaller() {
- if (mCallingUid != Binder.getCallingUid()) {
- throw new SecurityException("Caller " + mCallingUid
- + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
- }
- }
-
- @Override
- public void finishAndRemoveTask() {
- checkCaller();
-
- synchronized (ActivityManagerService.this) {
- long origId = Binder.clearCallingIdentity();
- try {
- // We remove the task from recents to preserve backwards
- if (!mStackSupervisor.removeTaskByIdLocked(mTaskId, false,
- REMOVE_FROM_RECENTS)) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-
- @Override
- public ActivityManager.RecentTaskInfo getTaskInfo() {
- checkCaller();
-
- synchronized (ActivityManagerService.this) {
- long origId = Binder.clearCallingIdentity();
- try {
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- return createRecentTaskInfoFromTaskRecord(tr);
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-
- @Override
- public void moveToFront() {
- checkCaller();
- // Will bring task to front if it already has a root activity.
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- mStackSupervisor.startActivityFromRecentsInner(mTaskId, null);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- @Override
- public int startActivity(IBinder whoThread, String callingPackage,
- Intent intent, String resolvedType, Bundle bOptions) {
- checkCaller();
-
- int callingUser = UserHandle.getCallingUserId();
- TaskRecord tr;
- IApplicationThread appThread;
- synchronized (ActivityManagerService.this) {
- tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- appThread = IApplicationThread.Stub.asInterface(whoThread);
- if (appThread == null) {
- throw new IllegalArgumentException("Bad app thread " + appThread);
- }
- }
- return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
- resolvedType, null, null, null, null, 0, 0, null, null,
- null, bOptions, false, callingUser, tr, "AppTaskImpl");
- }
-
- @Override
- public void setExcludeFromRecents(boolean exclude) {
- checkCaller();
-
- synchronized (ActivityManagerService.this) {
- long origId = Binder.clearCallingIdentity();
- try {
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- Intent intent = tr.getBaseIntent();
- if (exclude) {
- intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- } else {
- intent.setFlags(intent.getFlags()
- & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
- }
-
- /**
* Kill processes for the user with id userId and that depend on the package named packageName
*/
@Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 4c93423..f03d2d5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -73,10 +73,8 @@
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityManager.RESIZE_MODE_USER;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
@@ -86,15 +84,6 @@
public static final String NO_CLASS_ERROR_CODE = "Error type 3";
private static final String SHELL_PACKAGE_NAME = "com.android.shell";
- // Is the object moving in a positive direction?
- private static final boolean MOVING_FORWARD = true;
- // Is the object moving in the horizontal plan?
- private static final boolean MOVING_HORIZONTALLY = true;
- // Is the object current point great then its target point?
- private static final boolean GREATER_THAN_TARGET = true;
- // Amount we reduce the stack size by when testing a task re-size.
- private static final int STACK_BOUNDS_INSET = 10;
-
// IPC interface to activity manager -- don't need to do additional security checks.
final IActivityManager mInterface;
@@ -1944,8 +1933,6 @@
return runStackInfo(pw);
case "move-top-activity-to-pinned-stack":
return runMoveTopActivityToPinnedStack(pw);
- case "size-docked-stack-test":
- return runStackSizeDockedStackTest(pw);
case "remove":
return runStackRemove(pw);
default:
@@ -2143,89 +2130,6 @@
return 0;
}
- int runStackSizeDockedStackTest(PrintWriter pw) throws RemoteException {
- final PrintWriter err = getErrPrintWriter();
- final int stepSize = Integer.parseInt(getNextArgRequired());
- final String side = getNextArgRequired();
- final String delayStr = getNextArg();
- final int delayMs = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
-
- ActivityManager.StackInfo info = mInterface.getStackInfo(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
- if (info == null) {
- err.println("Docked stack doesn't exist");
- return -1;
- }
- if (info.bounds == null) {
- err.println("Docked stack doesn't have a bounds");
- return -1;
- }
- Rect bounds = info.bounds;
-
- final boolean horizontalGrowth = "l".equals(side) || "r".equals(side);
- final int changeSize = (horizontalGrowth ? bounds.width() : bounds.height()) / 2;
- int currentPoint;
- switch (side) {
- case "l":
- currentPoint = bounds.left;
- break;
- case "r":
- currentPoint = bounds.right;
- break;
- case "t":
- currentPoint = bounds.top;
- break;
- case "b":
- currentPoint = bounds.bottom;
- break;
- default:
- err.println("Unknown growth side: " + side);
- return -1;
- }
-
- final int startPoint = currentPoint;
- final int minPoint = currentPoint - changeSize;
- final int maxPoint = currentPoint + changeSize;
-
- int maxChange;
- pw.println("Shrinking docked stack side=" + side);
- pw.flush();
- while (currentPoint > minPoint) {
- maxChange = Math.min(stepSize, currentPoint - minPoint);
- currentPoint -= maxChange;
- setBoundsSide(bounds, side, currentPoint);
- int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
- if (res < 0) {
- return res;
- }
- }
-
- pw.println("Growing docked stack side=" + side);
- pw.flush();
- while (currentPoint < maxPoint) {
- maxChange = Math.min(stepSize, maxPoint - currentPoint);
- currentPoint += maxChange;
- setBoundsSide(bounds, side, currentPoint);
- int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
- if (res < 0) {
- return res;
- }
- }
-
- pw.println("Back to Original size side=" + side);
- pw.flush();
- while (currentPoint > startPoint) {
- maxChange = Math.min(stepSize, currentPoint - startPoint);
- currentPoint -= maxChange;
- setBoundsSide(bounds, side, currentPoint);
- int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
- if (res < 0) {
- return res;
- }
- }
- return 0;
- }
-
void setBoundsSide(Rect bounds, String side, int value) {
switch (side) {
case "l":
@@ -2687,10 +2591,6 @@
pw.println(" Change docked stack to <LEFT,TOP,RIGHT,BOTTOM>");
pw.println(" and supplying temporary different task bounds indicated by");
pw.println(" <TASK_LEFT,TOP,RIGHT,BOTTOM>");
- pw.println(" size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]");
- pw.println(" Test command for sizing docked stack by");
- pw.println(" <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom");
- pw.println(" applying the optional [DELAY_MS] between each step.");
pw.println(" move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
pw.println(" Moves the top activity from");
pw.println(" <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the");
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index fdcb8c6..93c0f77 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -5,6 +5,7 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -127,7 +128,7 @@
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
break;
- case WINDOW_STATE_FREEFORM:
+ case WINDOWING_MODE_FREEFORM:
mWindowState = WINDOW_STATE_FREEFORM;
break;
default:
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 7b0b942..f544d37 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -17,9 +17,7 @@
package com.android.server.am;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
import static android.app.ActivityOptions.ANIM_CUSTOM;
@@ -661,8 +659,7 @@
return;
}
- final boolean inPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID) &&
- (targetStackBounds != null);
+ final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
// Picture-in-picture mode changes also trigger a multi-window mode change as well, so
// update that here in order
@@ -684,10 +681,6 @@
}
}
- boolean isFreeform() {
- return task != null && task.getStackId() == FREEFORM_WORKSPACE_STACK_ID;
- }
-
@Override
protected int getChildCount() {
// {@link ActivityRecord} is a leaf node and has no children.
@@ -948,7 +941,7 @@
// update the initial multi-window modes so that the callbacks are scheduled correctly when
// the user leaves that mode.
mLastReportedMultiWindowMode = !task.mFullscreen;
- mLastReportedPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID);
+ mLastReportedPictureInPictureMode = inPinnedWindowingMode();
}
void removeWindowContainer() {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 1940ca2..3d3bae3 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -16,27 +16,25 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.activityTypeToString;
+import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
-
import static android.view.Display.INVALID_DISPLAY;
+
import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
import static com.android.server.am.ActivityDisplay.POSITION_TOP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
@@ -100,16 +98,19 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityController;
import android.app.ResultInfo;
+import android.app.WindowConfiguration;
+import android.app.WindowConfiguration.ActivityType;
+import android.app.WindowConfiguration.WindowingMode;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -192,10 +193,6 @@
// finished destroying itself.
private static final int DESTROY_TIMEOUT = 10 * 1000;
- // How long until we reset a task when the user returns to it. Currently
- // disabled.
- private static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
-
// Set to false to disable the preview that is shown while a new activity
// is being started.
private static final boolean SHOW_APP_STARTING_PREVIEW = true;
@@ -352,12 +349,11 @@
private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
private final Rect mTmpRect2 = new Rect();
+ private final Point mTmpSize = new Point();
/** Run all ActivityStacks through this */
protected final ActivityStackSupervisor mStackSupervisor;
- private final LaunchingTaskPositioner mTaskPositioner;
-
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
@@ -460,8 +456,6 @@
mWindowManager = mService.mWindowManager;
mStackId = stackId;
mCurrentUser = mService.mUserController.getCurrentUserId();
- mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
- ? new LaunchingTaskPositioner() : null;
mTmpRect2.setEmpty();
setWindowingMode(windowingMode);
setActivityType(activityType);
@@ -502,14 +496,11 @@
mDisplayId = activityDisplay.mDisplayId;
mBounds = bounds != null ? new Rect(bounds) : null;
mFullscreen = mBounds == null;
- if (mTaskPositioner != null) {
- mTaskPositioner.setDisplay(activityDisplay.mDisplay);
- mTaskPositioner.configure(mBounds);
- }
+
onParentChanged();
activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
- if (mStackId == DOCKED_STACK_ID) {
+ if (inSplitScreenPrimaryWindowingMode()) {
// If we created a docked stack we want to resize it so it resizes all other stacks
// in the system.
mStackSupervisor.resizeDockedStackLocked(
@@ -533,9 +524,6 @@
display.removeChild(this);
}
mDisplayId = INVALID_DISPLAY;
- if (mTaskPositioner != null) {
- mTaskPositioner.reset();
- }
}
/** Removes the stack completely. Also calls WindowManager to do the same on its side. */
@@ -639,9 +627,6 @@
void setBounds(Rect bounds) {
mBounds = mFullscreen ? null : new Rect(bounds);
- if (mTaskPositioner != null) {
- mTaskPositioner.configure(bounds);
- }
}
ActivityRecord topRunningActivityLocked() {
@@ -818,14 +803,6 @@
return isActivityTypeHome() || isActivityTypeRecents();
}
- final boolean isDockedStack() {
- return mStackId == DOCKED_STACK_ID;
- }
-
- final boolean isPinnedStack() {
- return mStackId == PINNED_STACK_ID;
- }
-
final boolean isOnHomeDisplay() {
return mDisplayId == DEFAULT_DISPLAY;
}
@@ -1505,9 +1482,9 @@
* needed. A stack is considered translucent if it don't contain a visible or
* starting (about to be visible) activity that is fullscreen (opaque).
* @param starting The currently starting activity or null if there is none.
- * @param stackBehindId The id of the stack directly behind this one.
+ * @param stackBehind The stack directly behind this one.
*/
- private boolean isStackTranslucent(ActivityRecord starting, int stackBehindId) {
+ private boolean isStackTranslucent(ActivityRecord starting, ActivityStack stackBehind) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -1532,7 +1509,6 @@
return false;
}
- final ActivityStack stackBehind = mStackSupervisor.getStack(stackBehindId);
final boolean stackBehindHomeOrRecent = stackBehind != null
&& stackBehind.isHomeOrRecentsStack();
if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()
@@ -1579,7 +1555,6 @@
// Check position and visibility of this stack relative to the front stack on its display.
final ActivityStack topStack = getTopStackOnDisplay();
- final int topStackId = topStack.mStackId;
final int windowingMode = getWindowingMode();
final int activityType = getActivityType();
@@ -1587,7 +1562,7 @@
// If the assistant stack is focused and translucent, then the docked stack is always
// visible
if (topStack.isActivityTypeAssistant()) {
- return topStack.isStackTranslucent(starting, DOCKED_STACK_ID);
+ return topStack.isStackTranslucent(starting, this);
}
return true;
}
@@ -1612,18 +1587,16 @@
}
final ActivityStack stackBehindTop = (stackBehindTopIndex >= 0)
? displayStacks.get(stackBehindTopIndex) : null;
- int stackBehindTopId = INVALID_STACK_ID;
int stackBehindTopWindowingMode = WINDOWING_MODE_UNDEFINED;
int stackBehindTopActivityType = ACTIVITY_TYPE_UNDEFINED;
if (stackBehindTop != null) {
- stackBehindTopId = stackBehindTop.mStackId;
stackBehindTopWindowingMode = stackBehindTop.getWindowingMode();
stackBehindTopActivityType = stackBehindTop.getActivityType();
}
final boolean alwaysOnTop = topStack.getWindowConfiguration().isAlwaysOnTop();
if (topStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || alwaysOnTop) {
- if (stackIndex == stackBehindTopIndex) {
+ if (this == stackBehindTop) {
// Stacks directly behind the docked or pinned stack are always visible.
return true;
} else if (alwaysOnTop && stackIndex == stackBehindTopIndex - 1) {
@@ -1632,14 +1605,13 @@
if (stackBehindTopWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
return true;
} else if (stackBehindTopActivityType == ACTIVITY_TYPE_ASSISTANT) {
- return displayStacks.get(stackBehindTopIndex).isStackTranslucent(
- starting, mStackId);
+ return stackBehindTop.isStackTranslucent(starting, this);
}
}
}
if (topStack.isBackdropToTranslucentActivity()
- && topStack.isStackTranslucent(starting, stackBehindTopId)) {
+ && topStack.isStackTranslucent(starting, stackBehindTop)) {
// Stacks behind the fullscreen or assistant stack with a translucent activity are
// always visible so they can act as a backdrop to the translucent activity.
// For example, dialog activities
@@ -1657,9 +1629,9 @@
}
}
- if (StackId.isStaticStack(mStackId)
- || isHomeOrRecentsStack() || isActivityTypeAssistant()) {
- // Visibility of any static stack should have been determined by the conditions above.
+ if (isOnHomeDisplay()) {
+ // Visibility of any stack on default display should have been determined by the
+ // conditions above.
return false;
}
@@ -1675,7 +1647,7 @@
return false;
}
- if (!stack.isStackTranslucent(starting, INVALID_STACK_ID)) {
+ if (!stack.isStackTranslucent(starting, null /* stackBehind */)) {
return false;
}
}
@@ -1801,7 +1773,8 @@
makeInvisible(r);
}
}
- if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ final int windowingMode = getWindowingMode();
+ if (windowingMode == WINDOWING_MODE_FREEFORM) {
// The visibility of tasks and the activities they contain in freeform stack are
// determined individually unlike other stacks where the visibility or fullscreen
// status of an activity in a previous task affects other.
@@ -1816,7 +1789,8 @@
// show activities in the next application stack behind them vs. another
// task in the home stack like recents.
behindFullscreenActivity = true;
- } else if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
+ } else if (windowingMode == WINDOWING_MODE_FULLSCREEN
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Skipping after task=" + task
+ " returning to non-application type=" + task.getTaskToReturnTo());
// Once we reach a fullscreen stack task that has a running activity and should
@@ -1852,6 +1826,32 @@
}
/**
+ * Returns true if this stack should be resized to match the bounds specified by
+ * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack.
+ */
+ boolean resizeStackWithLaunchBounds() {
+ return inPinnedWindowingMode();
+ }
+
+ /**
+ * Returns true if we try to maintain focus in the current stack when the top activity finishes.
+ */
+ private boolean keepFocusInStackIfPossible() {
+ final int windowingMode = getWindowingMode();
+ return windowingMode == WINDOWING_MODE_FREEFORM
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_PINNED;
+ }
+
+ /**
+ * Returns true if the top task in the task is allowed to return home when finished and
+ * there are other tasks in the stack.
+ */
+ boolean allowTopTaskToReturnHome() {
+ return !inPinnedWindowingMode();
+ }
+
+ /**
* @return the top most visible activity that wants to dismiss Keyguard
*/
ActivityRecord getTopDismissingKeyguardActivity() {
@@ -1867,7 +1867,7 @@
*/
boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
boolean isTop) {
- final boolean isInPinnedStack = r.getStack().getStackId() == PINNED_STACK_ID;
+ final boolean isInPinnedStack = r.inPinnedWindowingMode();
final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing(
mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked();
@@ -2165,7 +2165,7 @@
mResumedActivity = r;
r.state = ActivityState.RESUMED;
mService.setResumedActivityUncheckLocked(r, reason);
- mStackSupervisor.addRecentActivity(r);
+ mStackSupervisor.mRecentTasks.add(r.getTask());
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
@@ -2617,7 +2617,7 @@
private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
ActivityOptions options, String reason) {
- if ((!mFullscreen || !isOnHomeDisplay()) && adjustFocusToNextFocusableStackLocked(reason)) {
+ if (adjustFocusToNextFocusableStackLocked(reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen or is on a secondary display (with no home
// stack).
@@ -2746,9 +2746,8 @@
// make underlying task focused when this one will be finished.
int returnToType = isLastTaskOverHome
? task.getTaskToReturnTo() : ACTIVITY_TYPE_STANDARD;
- if (fromHomeOrRecents && StackId.allowTopTaskToReturnHome(mStackId)) {
- returnToType = topTask == null
- ? ACTIVITY_TYPE_HOME : topTask.getActivityType();
+ if (fromHomeOrRecents && allowTopTaskToReturnHome()) {
+ returnToType = topTask == null ? ACTIVITY_TYPE_HOME : topTask.getActivityType();
}
task.setTaskToReturnTo(returnToType);
}
@@ -2901,7 +2900,7 @@
// Ensure the caller has requested not to trigger auto-enter PiP
return false;
}
- if (pipCandidate == null || pipCandidate.getStackId() == PINNED_STACK_ID) {
+ if (pipCandidate == null || pipCandidate.inPinnedWindowingMode()) {
// Ensure that we do not trigger entering PiP an activity on the pinned stack
return false;
}
@@ -3186,15 +3185,8 @@
final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
ActivityRecord newActivity) {
- boolean forceReset =
+ final boolean forceReset =
(newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
- if (ACTIVITY_INACTIVE_RESET_TIME > 0
- && taskTop.getTask().getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
- if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
- forceReset = true;
- }
- }
-
final TaskRecord task = taskTop.getTask();
/** False until we evaluate the TaskRecord associated with taskTop. Switches to true
@@ -3291,7 +3283,7 @@
final String myReason = reason + " adjustFocus";
if (next != r) {
- if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) {
+ if (next != null && keepFocusInStackIfPossible() && isFocusable()) {
// For freeform, docked, and pinned stacks we always keep the focus within the
// stack as long as there is a running activity.
return;
@@ -3757,7 +3749,7 @@
if (mode == FINISH_IMMEDIATELY
|| (prevState == ActivityState.PAUSED
- && (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
+ && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
|| finishingActivityInNonFocusedStack
|| prevState == STOPPING
|| prevState == STOPPED
@@ -4464,7 +4456,9 @@
// Don't refocus if invisible to current user
final ActivityRecord top = tr.getTopActivity();
if (top == null || !top.okToShowLocked()) {
- mStackSupervisor.addRecentActivity(top);
+ if (top != null) {
+ mStackSupervisor.mRecentTasks.add(top.getTask());
+ }
ActivityOptions.abort(options);
return;
}
@@ -4571,8 +4565,8 @@
mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
}
- if (mStackId == PINNED_STACK_ID) {
- mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
+ if (inPinnedWindowingMode()) {
+ mStackSupervisor.removeStackLocked(mStackId);
return true;
}
@@ -4687,7 +4681,7 @@
for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
final TaskRecord task = mTaskHistory.get(i);
if (task.isResizeable()) {
- if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ if (inFreeformWindowingMode()) {
// For freeform stack we don't adjust the size of the tasks to match that
// of the stack, but we do try to make sure the tasks are still contained
// with the bounds of the stack.
@@ -4889,7 +4883,7 @@
if (focusedStack && topTask) {
// Give the latest time to ensure foreground task can be sorted
// at the first, because lastActiveTime of creating task is 0.
- ci.lastActiveTime = System.currentTimeMillis();
+ ci.lastActiveTime = SystemClock.elapsedRealtime();
topTask = false;
}
@@ -5069,7 +5063,7 @@
if (task.autoRemoveFromRecents() || isVoiceSession) {
// Task creator asked to remove this when done, or this task was a voice
// interaction, so it should not remain on the recent tasks list.
- mStackSupervisor.removeTaskFromRecents(task);
+ mStackSupervisor.mRecentTasks.remove(task);
}
task.removeWindowContainer();
@@ -5097,7 +5091,7 @@
task.setStack(null);
// Notify if a task from the pinned stack is being removed (or moved depending on the mode)
- if (mStackId == PINNED_STACK_ID) {
+ if (inPinnedWindowingMode()) {
mService.mTaskChangeNotificationController.notifyActivityUnpinned();
}
}
@@ -5120,10 +5114,12 @@
}
boolean layoutTaskInStack(TaskRecord task, ActivityInfo.WindowLayout windowLayout) {
- if (mTaskPositioner == null) {
+ if (!task.inFreeformWindowingMode()) {
return false;
}
- mTaskPositioner.updateDefaultBounds(task, mTaskHistory, windowLayout);
+ mStackSupervisor.getLaunchingTaskPositioner()
+ .updateDefaultBounds(task, mTaskHistory, windowLayout);
+
return true;
}
@@ -5248,7 +5244,9 @@
@Override
public String toString() {
return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
- + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
+ + " stackId=" + mStackId + " type=" + activityTypeToString(getActivityType())
+ + " mode=" + windowingModeToString(getWindowingMode()) + ", "
+ + mTaskHistory.size() + " tasks}";
}
void onLockTaskPackagesUpdatedLocked() {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index da2827a..2fd8c7f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -21,11 +21,7 @@
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
@@ -35,10 +31,13 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.activityTypeToString;
+import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
@@ -47,6 +46,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.TYPE_VIRTUAL;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
@@ -86,12 +86,13 @@
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
+import static com.android.server.am.proto.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.proto.ActivityStackSupervisorProto.DISPLAYS;
import static com.android.server.am.proto.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
import static com.android.server.am.proto.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
import static com.android.server.am.proto.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
+
import static java.lang.Integer.MAX_VALUE;
import android.Manifest;
@@ -102,7 +103,6 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerInternal.SleepToken;
import android.app.ActivityOptions;
@@ -176,7 +176,8 @@
import java.util.List;
import java.util.Set;
-public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
+public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
+ RecentTasks.Callbacks {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_IDLE = TAG + POSTFIX_IDLE;
@@ -286,7 +287,7 @@
final ActivityManagerService mService;
- private RecentTasks mRecentTasks;
+ RecentTasks mRecentTasks;
final ActivityStackSupervisorHandler mHandler;
@@ -294,8 +295,10 @@
WindowManagerService mWindowManager;
DisplayManager mDisplayManager;
+ LaunchingTaskPositioner mTaskPositioner = new LaunchingTaskPositioner();
+
/** Counter for next free stack ID to use for dynamic activity stacks. */
- private int mNextFreeStackId = FIRST_DYNAMIC_STACK_ID;
+ private int mNextFreeStackId = 0;
/**
* Maps the task identifier that activities are currently being started in to the userId of the
@@ -576,6 +579,7 @@
void setRecentTasks(RecentTasks recentTasks) {
mRecentTasks = recentTasks;
+ mRecentTasks.registerCallback(this);
}
/**
@@ -749,7 +753,7 @@
// Otherwise, check the recent tasks and return if we find it there and we are not restoring
// the task from recents
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
- final TaskRecord task = mRecentTasks.taskForIdLocked(id);
+ final TaskRecord task = mRecentTasks.getTask(id);
if (task == null) {
if (DEBUG_RECENTS) {
@@ -858,7 +862,7 @@
// [u*MAX_TASK_IDS_PER_USER, (u+1)*MAX_TASK_IDS_PER_USER-1], so if MAX_TASK_IDS_PER_USER
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = nextTaskIdForUser(currentTaskId, userId);
- while (mRecentTasks.taskIdTakenForUserLocked(candidateTaskId, userId)
+ while (mRecentTasks.containsTaskId(candidateTaskId, userId)
|| anyTaskForIdLocked(
candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
candidateTaskId = nextTaskIdForUser(candidateTaskId, userId);
@@ -2105,8 +2109,8 @@
// moveTaskToStackUncheckedLocked() should already placed the task on top,
// still need moveTaskToFrontLocked() below for any transition settings.
}
- if (StackId.resizeStackWithLaunchBounds(stack.mStackId)) {
- resizeStackLocked(stack.mStackId, bounds, null /* tempTaskBounds */,
+ if (stack.resizeStackWithLaunchBounds()) {
+ resizeStackLocked(stack, bounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, !DEFER_RESUME);
} else {
@@ -2139,6 +2143,10 @@
|| mService.mSupportsFreeformWindowManagement;
}
+ LaunchingTaskPositioner getLaunchingTaskPositioner() {
+ return mTaskPositioner;
+ }
+
protected <T extends ActivityStack> T getStack(int stackId) {
for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
final T stack = mActivityDisplays.valueAt(i).getStack(stackId);
@@ -2417,7 +2425,7 @@
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return r.supportsSplitScreenWindowingMode();
}
- if (StackId.isDynamicStack(stack.mStackId)) {
+ if (!stack.isOnHomeDisplay()) {
return r.canBeLaunchedOnDisplay(displayId);
}
Slog.e(TAG, "isValidLaunchStack: Unexpected stack=" + stack);
@@ -2511,18 +2519,15 @@
return null;
}
- void resizeStackLocked(int stackId, Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds,
- boolean preserveWindows, boolean allowResizeInDockedMode, boolean deferResume) {
- if (stackId == DOCKED_STACK_ID) {
+ void resizeStackLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
+ Rect tempTaskInsetBounds, boolean preserveWindows, boolean allowResizeInDockedMode,
+ boolean deferResume) {
+
+ if (stack.inSplitScreenPrimaryWindowingMode()) {
resizeDockedStackLocked(bounds, tempTaskBounds, tempTaskInsetBounds, null, null,
preserveWindows, deferResume);
return;
}
- final ActivityStack stack = getStack(stackId);
- if (stack == null) {
- Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
- return;
- }
final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenStack();
if (!allowResizeInDockedMode
@@ -2532,7 +2537,7 @@
return;
}
- Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId);
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stack.mStackId);
mWindowManager.deferSurfaceLayout();
try {
if (stack.supportsSplitScreenWindowingMode()) {
@@ -2584,8 +2589,7 @@
/**
* TODO: This should just change the windowing mode and resize vs. actually moving task around.
- * Can do that once we are no longer using static stack ids. Specially when
- * {@link ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} is removed.
+ * Can do that once we are no longer using static stack ids.
*/
private void moveTasksToFullscreenStackInSurfaceTransaction(ActivityStack fromStack,
int toDisplayId, boolean onTop) {
@@ -2606,7 +2610,7 @@
if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
continue;
}
- resizeStackLocked(otherStack.mStackId, null, null, null, PRESERVE_WINDOWS,
+ resizeStackLocked(otherStack, null, null, null, PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, DEFER_RESUME);
}
@@ -2744,7 +2748,7 @@
tempRect /* outStackBounds */,
otherTaskRect /* outTempTaskBounds */, true /* ignoreVisibility */);
- resizeStackLocked(current.mStackId, !tempRect.isEmpty() ? tempRect : null,
+ resizeStackLocked(current, !tempRect.isEmpty() ? tempRect : null,
!otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds,
tempOtherTaskInsetBounds, preserveWindows,
true /* allowResizeInDockedMode */, deferResume);
@@ -2892,23 +2896,9 @@
return false;
}
- void addRecentActivity(ActivityRecord r) {
- if (r == null) {
- return;
- }
- final TaskRecord task = r.getTask();
- mRecentTasks.addLocked(task);
- task.touchActiveTime();
- }
-
- void removeTaskFromRecents(TaskRecord task) {
- mRecentTasks.remove(task);
- task.removedFromRecents();
- }
-
void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess, boolean removeFromRecents) {
if (removeFromRecents) {
- removeTaskFromRecents(tr);
+ mRecentTasks.remove(tr);
}
ComponentName component = tr.getBaseIntent().getComponent();
if (component == null) {
@@ -2979,8 +2969,7 @@
int getNextStackId() {
while (true) {
- if (mNextFreeStackId >= FIRST_DYNAMIC_STACK_ID
- && getStack(mNextFreeStackId) == null) {
+ if (getStack(mNextFreeStackId) == null) {
break;
}
mNextFreeStackId++;
@@ -2989,7 +2978,8 @@
}
/**
- * Restores a recent task to a stack
+ * Called to restore the state of the task into the stack that it's supposed to go into.
+ *
* @param task The recent task to be restored.
* @param aOptions The activity options to use for restoration.
* @return true if the task has been restored successfully.
@@ -3020,6 +3010,22 @@
return true;
}
+ @Override
+ public void onRecentTaskAdded(TaskRecord task) {
+ task.touchActiveTime();
+ }
+
+ @Override
+ public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed) {
+ if (wasTrimmed) {
+ // Task was trimmed from the recent tasks list -- remove the active task record as well
+ // since the user won't really be able to go back to it
+ removeTaskByIdLocked(task.taskId, false /* killProcess */,
+ false /* removeFromRecents */);
+ }
+ task.removedFromRecents();
+ }
+
/**
* Move stack with all its existing content to specified display.
* @param stackId Id of stack to move.
@@ -3160,7 +3166,7 @@
// Resize the pinned stack to match the current size of the task the activity we are
// going to be moving is currently contained in. We do this to have the right starting
// animation bounds for the pinned stack to the desired bounds the caller wants.
- resizeStackLocked(PINNED_STACK_ID, task.mBounds, null /* tempTaskBounds */,
+ resizeStackLocked(stack, task.mBounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, !DEFER_RESUME);
@@ -3500,7 +3506,7 @@
final ActivityStack stack = task.getStack();
r.mLaunchTaskBehind = false;
- mRecentTasks.addLocked(task);
+ mRecentTasks.add(task);
mService.mTaskChangeNotificationController.notifyTaskStackChanged();
r.setVisibility(false);
@@ -3653,7 +3659,7 @@
// Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
// also cause all tasks to be moved to the fullscreen stack at a position that is
// appropriate.
- removeStackLocked(PINNED_STACK_ID);
+ removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
mUserStackInFront.put(mCurrentUser, focusStackId);
final int restoreStackId = mUserStackInFront.get(userId, mHomeStack.mStackId);
@@ -3811,8 +3817,7 @@
mService.mLockTaskController.dump(pw, prefix);
}
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
+ public void writeToProto(ProtoOutputStream proto) {
super.writeToProto(proto, CONFIGURATION_CONTAINER);
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
@@ -3828,7 +3833,6 @@
} else {
proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
}
- proto.end(token);
}
/**
@@ -3896,7 +3900,9 @@
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
pw.println();
- pw.println(" Stack #" + stack.mStackId + ":");
+ pw.println(" Stack #" + stack.mStackId
+ + ": type=" + activityTypeToString(getActivityType())
+ + " mode=" + windowingModeToString(getWindowingMode()));
pw.println(" mFullscreen=" + stack.mFullscreen);
pw.println(" isSleeping=" + stack.shouldSleepActivities());
pw.println(" mBounds=" + stack.mBounds);
@@ -4315,8 +4321,8 @@
// The task landed on an inappropriate display somehow, move it to the default
// display.
// TODO(multi-display): Find proper stack for the task on the default display.
- mService.moveTaskToStack(task.taskId, FULLSCREEN_WORKSPACE_STACK_ID,
- true /* toTop */);
+ mService.setTaskWindowingMode(task.taskId,
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
launchOnSecondaryDisplayFailed = true;
} else {
// The task might have landed on a display different from requested.
@@ -4402,7 +4408,7 @@
void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, ActivityStack prevStack) {
final ActivityStack stack = task.getStack();
if (prevStack == null || prevStack == stack
- || (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
+ || (!prevStack.inPinnedWindowingMode() && !stack.inPinnedWindowingMode())) {
return;
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index d444c66..cceb576 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -26,11 +26,6 @@
import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.ActivityManager.StackId;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.isDynamicStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -610,15 +605,19 @@
mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
}
- int startedActivityStackId = INVALID_STACK_ID;
+ ActivityStack startedActivityStack = null;
final ActivityStack currentStack = r.getStack();
if (currentStack != null) {
- startedActivityStackId = currentStack.mStackId;
+ startedActivityStack = currentStack;
} else if (mTargetStack != null) {
- startedActivityStackId = targetStack.mStackId;
+ startedActivityStack = targetStack;
}
- if (startedActivityStackId == DOCKED_STACK_ID) {
+ if (startedActivityStack == null) {
+ return;
+ }
+
+ if (startedActivityStack.inSplitScreenPrimaryWindowingMode()) {
final ActivityStack homeStack = mSupervisor.getDefaultDisplay().getStack(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
@@ -634,14 +633,14 @@
boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
- if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
- || result == START_DELIVERED_TO_TOP || clearedTask)) {
+ if (startedActivityStack.inPinnedWindowingMode()
+ && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
+ || clearedTask)) {
// The activity was already running in the pinned stack so it wasn't started, but either
// brought to the front or the new intent was delivered to it since it was already in
// front. Notify anyone interested in this piece of information.
mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
clearedTask);
- return;
}
}
@@ -1240,8 +1239,8 @@
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
- } else {
- mSupervisor.addRecentActivity(mStartActivity);
+ } else if (mStartActivity != null) {
+ mSupervisor.mRecentTasks.add(mStartActivity.getTask());
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
@@ -1427,7 +1426,7 @@
// in any task/stack, however it could launch other activities like ResolverActivity,
// and we want those to stay in the original task.
if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
- && mSourceRecord.isFreeform()) {
+ && mSourceRecord.inFreeformWindowingMode()) {
mAddingToTask = true;
}
}
@@ -2001,9 +2000,9 @@
return;
}
- final int stackId = task.getStackId();
- if (StackId.resizeStackWithLaunchBounds(stackId)) {
- mService.resizeStack(stackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
+ final ActivityStack stack = task.getStack();
+ if (stack != null && stack.resizeStackWithLaunchBounds()) {
+ mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
} else {
task.updateOverrideConfiguration(bounds);
}
@@ -2119,7 +2118,7 @@
mSupervisor.getStacksOnDefaultDisplay();
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
stack = homeDisplayStacks.get(stackNdx);
- if (isDynamicStack(stack.mStackId)) {
+ if (!stack.isOnHomeDisplay()) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting focused stack=" + stack);
return stack;
@@ -2138,7 +2137,6 @@
private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
final ActivityStack focusedStack = mSupervisor.mFocusedStack;
final boolean canUseFocusedStack;
- final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
if (focusedStack.isActivityTypeAssistant()) {
canUseFocusedStack = r.isActivityTypeAssistant();
} else {
@@ -2161,7 +2159,7 @@
default:
// Dynamic stacks behave similarly to the fullscreen stack and can contain any
// resizeable task.
- canUseFocusedStack = isDynamicStack(focusedStackId)
+ canUseFocusedStack = !focusedStack.isOnHomeDisplay()
&& r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
}
}
@@ -2205,7 +2203,7 @@
return mSupervisor.mFocusedStack;
}
- if (parentStack != null && parentStack.isDockedStack()) {
+ if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
// If parent was in docked stack, the natural place to launch another activity
// will be fullscreen, so it can appear alongside the docked window.
final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
diff --git a/services/core/java/com/android/server/am/AppTaskImpl.java b/services/core/java/com/android/server/am/AppTaskImpl.java
new file mode 100644
index 0000000..a4e2e70
--- /dev/null
+++ b/services/core/java/com/android/server/am/AppTaskImpl.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2017 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.am;
+
+import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
+
+import android.app.ActivityManager;
+import android.app.IAppTask;
+import android.app.IApplicationThread;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.UserHandle;
+
+/**
+ * An implementation of IAppTask, that allows an app to manage its own tasks via
+ * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that
+ * only the process that calls getAppTasks() can call the AppTask methods.
+ */
+class AppTaskImpl extends IAppTask.Stub {
+ private ActivityManagerService mService;
+
+ private int mTaskId;
+ private int mCallingUid;
+
+ public AppTaskImpl(ActivityManagerService service, int taskId, int callingUid) {
+ mService = service;
+ mTaskId = taskId;
+ mCallingUid = callingUid;
+ }
+
+ private void checkCaller() {
+ if (mCallingUid != Binder.getCallingUid()) {
+ throw new SecurityException("Caller " + mCallingUid
+ + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
+ }
+ }
+
+ @Override
+ public void finishAndRemoveTask() {
+ checkCaller();
+
+ synchronized (mService) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ // We remove the task from recents to preserve backwards
+ if (!mService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false,
+ REMOVE_FROM_RECENTS)) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
+ public ActivityManager.RecentTaskInfo getTaskInfo() {
+ checkCaller();
+
+ synchronized (mService) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ return RecentTasks.createRecentTaskInfo(tr);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
+ public void moveToFront() {
+ checkCaller();
+ // Will bring task to front if it already has a root activity.
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ mService.mStackSupervisor.startActivityFromRecentsInner(mTaskId, null);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ @Override
+ public int startActivity(IBinder whoThread, String callingPackage,
+ Intent intent, String resolvedType, Bundle bOptions) {
+ checkCaller();
+
+ int callingUser = UserHandle.getCallingUserId();
+ TaskRecord tr;
+ IApplicationThread appThread;
+ synchronized (mService) {
+ tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ appThread = IApplicationThread.Stub.asInterface(whoThread);
+ if (appThread == null) {
+ throw new IllegalArgumentException("Bad app thread " + appThread);
+ }
+ }
+ return mService.mActivityStarter.startActivityMayWait(appThread, -1, callingPackage,
+ intent, resolvedType, null, null, null, null, 0, 0, null, null,
+ null, bOptions, false, callingUser, tr, "AppTaskImpl");
+ }
+
+ @Override
+ public void setExcludeFromRecents(boolean exclude) {
+ checkCaller();
+
+ synchronized (mService) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ Intent intent = tr.getBaseIntent();
+ if (exclude) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ } else {
+ intent.setFlags(intent.getFlags()
+ & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/am/BroadcastFilter.java b/services/core/java/com/android/server/am/BroadcastFilter.java
index f96b06f..7ff227f 100644
--- a/services/core/java/com/android/server/am/BroadcastFilter.java
+++ b/services/core/java/com/android/server/am/BroadcastFilter.java
@@ -19,6 +19,9 @@
import android.content.IntentFilter;
import android.util.PrintWriterPrinter;
import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.am.proto.BroadcastFilterProto;
import java.io.PrintWriter;
@@ -44,27 +47,38 @@
instantApp = _instantApp;
visibleToInstantApp = _visibleToInstantApp;
}
-
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ super.writeToProto(proto, BroadcastFilterProto.INTENT_FILTER);
+ if (requiredPermission != null) {
+ proto.write(BroadcastFilterProto.REQUIRED_PERMISSION, requiredPermission);
+ }
+ proto.write(BroadcastFilterProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this)));
+ proto.write(BroadcastFilterProto.OWNING_USER_ID, owningUserId);
+ proto.end(token);
+ }
+
public void dump(PrintWriter pw, String prefix) {
dumpInReceiverList(pw, new PrintWriterPrinter(pw), prefix);
receiverList.dumpLocal(pw, prefix);
}
-
+
public void dumpBrief(PrintWriter pw, String prefix) {
dumpBroadcastFilterState(pw, prefix);
}
-
+
public void dumpInReceiverList(PrintWriter pw, Printer pr, String prefix) {
super.dump(pr, prefix);
dumpBroadcastFilterState(pw, prefix);
}
-
+
void dumpBroadcastFilterState(PrintWriter pw, String prefix) {
if (requiredPermission != null) {
pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
}
}
-
+
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("BroadcastFilter{");
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index d835454..c62cc38 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -51,9 +51,12 @@
import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import static com.android.server.am.ActivityManagerDebugConfig.*;
+import com.android.server.am.proto.BroadcastQueueProto;
+
/**
* BROADCASTS
*
@@ -1585,6 +1588,55 @@
&& (mPendingBroadcast == null);
}
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ proto.write(BroadcastQueueProto.QUEUE_NAME, mQueueName);
+ int N;
+ N = mParallelBroadcasts.size();
+ for (int i = N - 1; i >= 0; i--) {
+ mParallelBroadcasts.get(i).writeToProto(proto, BroadcastQueueProto.PARALLEL_BROADCASTS);
+ }
+ N = mOrderedBroadcasts.size();
+ for (int i = N - 1; i >= 0; i--) {
+ mOrderedBroadcasts.get(i).writeToProto(proto, BroadcastQueueProto.ORDERED_BROADCASTS);
+ }
+ if (mPendingBroadcast != null) {
+ mPendingBroadcast.writeToProto(proto, BroadcastQueueProto.PENDING_BROADCAST);
+ }
+
+ int lastIndex = mHistoryNext;
+ int ringIndex = lastIndex;
+ do {
+ // increasing index = more recent entry, and we want to print the most
+ // recent first and work backwards, so we roll through the ring backwards.
+ ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_HISTORY);
+ BroadcastRecord r = mBroadcastHistory[ringIndex];
+ if (r != null) {
+ r.writeToProto(proto, BroadcastQueueProto.HISTORICAL_BROADCASTS);
+ }
+ } while (ringIndex != lastIndex);
+
+ lastIndex = ringIndex = mSummaryHistoryNext;
+ do {
+ ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_SUMMARY_HISTORY);
+ Intent intent = mBroadcastSummaryHistory[ringIndex];
+ if (intent == null) {
+ continue;
+ }
+ long summaryToken = proto.start(BroadcastQueueProto.HISTORICAL_BROADCASTS_SUMMARY);
+ intent.writeToProto(proto, BroadcastQueueProto.BroadcastSummary.INTENT,
+ false, true, true, false);
+ proto.write(BroadcastQueueProto.BroadcastSummary.ENQUEUE_CLOCK_TIME_MS,
+ mSummaryHistoryEnqueueTime[ringIndex]);
+ proto.write(BroadcastQueueProto.BroadcastSummary.DISPATCH_CLOCK_TIME_MS,
+ mSummaryHistoryDispatchTime[ringIndex]);
+ proto.write(BroadcastQueueProto.BroadcastSummary.FINISH_CLOCK_TIME_MS,
+ mSummaryHistoryFinishTime[ringIndex]);
+ proto.end(summaryToken);
+ } while (ringIndex != lastIndex);
+ proto.end(token);
+ }
+
final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 6bc0744..5b3b2a8 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -30,6 +30,9 @@
import android.os.UserHandle;
import android.util.PrintWriterPrinter;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.am.proto.BroadcastRecordProto;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -331,9 +334,17 @@
return didSomething;
}
+ @Override
public String toString() {
return "BroadcastRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " u" + userId + " " + intent.getAction() + "}";
}
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ proto.write(BroadcastRecordProto.USER_ID, userId);
+ proto.write(BroadcastRecordProto.INTENT_ACTION, intent.getAction());
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 5c48f90..ba541e6 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -16,7 +16,6 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
index d652341..0dc73e9 100644
--- a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
+++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
@@ -24,8 +24,8 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Slog;
-import android.view.Display;
import android.view.Gravity;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
@@ -64,43 +64,11 @@
private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2;
private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3;
- private boolean mDefaultStartBoundsConfigurationSet = false;
private final Rect mAvailableRect = new Rect();
private final Rect mTmpProposal = new Rect();
private final Rect mTmpOriginal = new Rect();
- private int mDefaultFreeformStartX;
- private int mDefaultFreeformStartY;
- private int mDefaultFreeformWidth;
- private int mDefaultFreeformHeight;
- private int mDefaultFreeformStepHorizontal;
- private int mDefaultFreeformStepVertical;
- private int mDisplayWidth;
- private int mDisplayHeight;
-
- void setDisplay(Display display) {
- Point size = new Point();
- display.getSize(size);
- mDisplayWidth = size.x;
- mDisplayHeight = size.y;
- }
-
- void configure(Rect stackBounds) {
- if (stackBounds == null) {
- mAvailableRect.set(0, 0, mDisplayWidth, mDisplayHeight);
- } else {
- mAvailableRect.set(stackBounds);
- }
- int width = mAvailableRect.width();
- int height = mAvailableRect.height();
- mDefaultFreeformStartX = mAvailableRect.left + width / MARGIN_SIZE_DENOMINATOR;
- mDefaultFreeformStartY = mAvailableRect.top + height / MARGIN_SIZE_DENOMINATOR;
- mDefaultFreeformWidth = width / WINDOW_SIZE_DENOMINATOR;
- mDefaultFreeformHeight = height / WINDOW_SIZE_DENOMINATOR;
- mDefaultFreeformStepHorizontal = Math.max(width / STEP_DENOMINATOR, MINIMAL_STEP);
- mDefaultFreeformStepVertical = Math.max(height / STEP_DENOMINATOR, MINIMAL_STEP);
- mDefaultStartBoundsConfigurationSet = true;
- }
+ private final Point mDisplaySize = new Point();
/**
* Tries to set task's bound in a way that it won't collide with any other task. By colliding
@@ -114,104 +82,154 @@
*/
void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks,
@Nullable ActivityInfo.WindowLayout windowLayout) {
- if (!mDefaultStartBoundsConfigurationSet) {
- return;
- }
+ updateAvailableRect(task, mAvailableRect);
+
if (windowLayout == null) {
- positionCenter(task, tasks, mDefaultFreeformWidth, mDefaultFreeformHeight);
+ positionCenter(task, tasks, mAvailableRect, getFreeformWidth(mAvailableRect),
+ getFreeformHeight(mAvailableRect));
return;
}
- int width = getFinalWidth(windowLayout);
- int height = getFinalHeight(windowLayout);
+ int width = getFinalWidth(windowLayout, mAvailableRect);
+ int height = getFinalHeight(windowLayout, mAvailableRect);
int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
if (verticalGravity == Gravity.TOP) {
if (horizontalGravity == Gravity.RIGHT) {
- positionTopRight(task, tasks, width, height);
+ positionTopRight(task, tasks, mAvailableRect, width, height);
} else {
- positionTopLeft(task, tasks, width, height);
+ positionTopLeft(task, tasks, mAvailableRect, width, height);
}
} else if (verticalGravity == Gravity.BOTTOM) {
if (horizontalGravity == Gravity.RIGHT) {
- positionBottomRight(task, tasks, width, height);
+ positionBottomRight(task, tasks, mAvailableRect, width, height);
} else {
- positionBottomLeft(task, tasks, width, height);
+ positionBottomLeft(task, tasks, mAvailableRect, width, height);
}
} else {
// Some fancy gravity setting that we don't support yet. We just put the activity in the
// center.
Slog.w(TAG, "Received unsupported gravity: " + windowLayout.gravity
+ ", positioning in the center instead.");
- positionCenter(task, tasks, width, height);
+ positionCenter(task, tasks, mAvailableRect, width, height);
}
}
- private int getFinalWidth(ActivityInfo.WindowLayout windowLayout) {
- int width = mDefaultFreeformWidth;
+ private void updateAvailableRect(TaskRecord task, Rect availableRect) {
+ final Rect stackBounds = task.getStack().mBounds;
+
+ if (stackBounds != null) {
+ availableRect.set(stackBounds);
+ } else {
+ task.getStack().getDisplay().mDisplay.getSize(mDisplaySize);
+ availableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
+ }
+ }
+
+ @VisibleForTesting
+ static int getFreeformStartLeft(Rect bounds) {
+ return bounds.left + bounds.width() / MARGIN_SIZE_DENOMINATOR;
+ }
+
+ @VisibleForTesting
+ static int getFreeformStartTop(Rect bounds) {
+ return bounds.top + bounds.height() / MARGIN_SIZE_DENOMINATOR;
+ }
+
+ @VisibleForTesting
+ static int getFreeformWidth(Rect bounds) {
+ return bounds.width() / WINDOW_SIZE_DENOMINATOR;
+ }
+
+ @VisibleForTesting
+ static int getFreeformHeight(Rect bounds) {
+ return bounds.height() / WINDOW_SIZE_DENOMINATOR;
+ }
+
+ @VisibleForTesting
+ static int getHorizontalStep(Rect bounds) {
+ return Math.max(bounds.width() / STEP_DENOMINATOR, MINIMAL_STEP);
+ }
+
+ @VisibleForTesting
+ static int getVerticalStep(Rect bounds) {
+ return Math.max(bounds.height() / STEP_DENOMINATOR, MINIMAL_STEP);
+ }
+
+
+
+ private int getFinalWidth(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
+ int width = getFreeformWidth(availableRect);
if (windowLayout.width > 0) {
width = windowLayout.width;
}
if (windowLayout.widthFraction > 0) {
- width = (int) (mAvailableRect.width() * windowLayout.widthFraction);
+ width = (int) (availableRect.width() * windowLayout.widthFraction);
}
return width;
}
- private int getFinalHeight(ActivityInfo.WindowLayout windowLayout) {
- int height = mDefaultFreeformHeight;
+ private int getFinalHeight(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
+ int height = getFreeformHeight(availableRect);
if (windowLayout.height > 0) {
height = windowLayout.height;
}
if (windowLayout.heightFraction > 0) {
- height = (int) (mAvailableRect.height() * windowLayout.heightFraction);
+ height = (int) (availableRect.height() * windowLayout.heightFraction);
}
return height;
}
- private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mAvailableRect.left, mAvailableRect.bottom - height,
- mAvailableRect.left + width, mAvailableRect.bottom);
- position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
+ private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ mTmpProposal.set(availableRect.left, availableRect.bottom - height,
+ availableRect.left + width, availableRect.bottom);
+ position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
+ SHIFT_POLICY_HORIZONTAL_RIGHT);
}
- private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.bottom - height,
- mAvailableRect.right, mAvailableRect.bottom);
- position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
+ private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ mTmpProposal.set(availableRect.right - width, availableRect.bottom - height,
+ availableRect.right, availableRect.bottom);
+ position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
+ SHIFT_POLICY_HORIZONTAL_LEFT);
}
- private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mAvailableRect.left, mAvailableRect.top,
- mAvailableRect.left + width, mAvailableRect.top + height);
- position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
+ private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ mTmpProposal.set(availableRect.left, availableRect.top,
+ availableRect.left + width, availableRect.top + height);
+ position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
+ SHIFT_POLICY_HORIZONTAL_RIGHT);
}
- private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.top,
- mAvailableRect.right, mAvailableRect.top + height);
- position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
+ private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ mTmpProposal.set(availableRect.right - width, availableRect.top,
+ availableRect.right, availableRect.top + height);
+ position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
+ SHIFT_POLICY_HORIZONTAL_LEFT);
}
- private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mDefaultFreeformStartX, mDefaultFreeformStartY,
- mDefaultFreeformStartX + width, mDefaultFreeformStartY + height);
- position(task, tasks, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN);
+ private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ final int defaultFreeformLeft = getFreeformStartLeft(availableRect);
+ final int defaultFreeformTop = getFreeformStartTop(availableRect);
+ mTmpProposal.set(defaultFreeformLeft, defaultFreeformTop,
+ defaultFreeformLeft + width, defaultFreeformTop + height);
+ position(task, tasks, availableRect, mTmpProposal, ALLOW_RESTART,
+ SHIFT_POLICY_DIAGONAL_DOWN);
}
- private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect proposal,
- boolean allowRestart, int shiftPolicy) {
+ private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect,
+ Rect proposal, boolean allowRestart, int shiftPolicy) {
mTmpOriginal.set(proposal);
boolean restarted = false;
while (boundsConflict(proposal, tasks)) {
// Unfortunately there is already a task at that spot, so we need to look for some
// other place.
- shiftStartingPoint(proposal, shiftPolicy);
- if (shiftedToFar(proposal, shiftPolicy)) {
+ shiftStartingPoint(proposal, availableRect, shiftPolicy);
+ if (shiftedTooFar(proposal, availableRect, shiftPolicy)) {
// We don't want the task to go outside of the stack, because it won't look
// nice. Depending on the starting point we either restart, or immediately give up.
if (!allowRestart) {
@@ -220,13 +238,13 @@
}
// We must have started not from the top. Let's restart from there because there
// might be some space there.
- proposal.set(mAvailableRect.left, mAvailableRect.top,
- mAvailableRect.left + proposal.width(),
- mAvailableRect.top + proposal.height());
+ proposal.set(availableRect.left, availableRect.top,
+ availableRect.left + proposal.width(),
+ availableRect.top + proposal.height());
restarted = true;
}
- if (restarted && (proposal.left > mDefaultFreeformStartX
- || proposal.top > mDefaultFreeformStartY)) {
+ if (restarted && (proposal.left > getFreeformStartLeft(availableRect)
+ || proposal.top > getFreeformStartTop(availableRect))) {
// If we restarted and crossed the initial position, let's not struggle anymore.
// The user already must have ton of tasks visible, we can just smack the new
// one in the center.
@@ -237,27 +255,30 @@
task.updateOverrideConfiguration(proposal);
}
- private boolean shiftedToFar(Rect start, int shiftPolicy) {
+ private boolean shiftedTooFar(Rect start, Rect availableRect, int shiftPolicy) {
switch (shiftPolicy) {
case SHIFT_POLICY_HORIZONTAL_LEFT:
- return start.left < mAvailableRect.left;
+ return start.left < availableRect.left;
case SHIFT_POLICY_HORIZONTAL_RIGHT:
- return start.right > mAvailableRect.right;
+ return start.right > availableRect.right;
default: // SHIFT_POLICY_DIAGONAL_DOWN
- return start.right > mAvailableRect.right || start.bottom > mAvailableRect.bottom;
+ return start.right > availableRect.right || start.bottom > availableRect.bottom;
}
}
- private void shiftStartingPoint(Rect posposal, int shiftPolicy) {
+ private void shiftStartingPoint(Rect posposal, Rect availableRect, int shiftPolicy) {
+ final int defaultFreeformStepHorizontal = getHorizontalStep(availableRect);
+ final int defaultFreeformStepVertical = getVerticalStep(availableRect);
+
switch (shiftPolicy) {
case SHIFT_POLICY_HORIZONTAL_LEFT:
- posposal.offset(-mDefaultFreeformStepHorizontal, 0);
+ posposal.offset(-defaultFreeformStepHorizontal, 0);
break;
case SHIFT_POLICY_HORIZONTAL_RIGHT:
- posposal.offset(mDefaultFreeformStepHorizontal, 0);
+ posposal.offset(defaultFreeformStepHorizontal, 0);
break;
default: // SHIFT_POLICY_DIAGONAL_DOWN:
- posposal.offset(mDefaultFreeformStepHorizontal, mDefaultFreeformStepVertical);
+ posposal.offset(defaultFreeformStepHorizontal, defaultFreeformStepVertical);
break;
}
}
@@ -296,8 +317,4 @@
return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
&& Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
}
-
- void reset() {
- mDefaultStartBoundsConfigurationSet = false;
- }
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0e318d9..e847723 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -27,6 +27,7 @@
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.am.proto.ProcessRecordProto;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -44,6 +45,7 @@
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -621,6 +623,22 @@
}
}
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ proto.write(ProcessRecordProto.PID, pid);
+ proto.write(ProcessRecordProto.PROCESS_NAME, processName);
+ if (info.uid < Process.FIRST_APPLICATION_UID) {
+ proto.write(ProcessRecordProto.UID, uid);
+ } else {
+ proto.write(ProcessRecordProto.USER_ID, userId);
+ proto.write(ProcessRecordProto.APP_ID, UserHandle.getAppId(info.uid));
+ if (uid != info.uid) {
+ proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid));
+ }
+ }
+ proto.end(token);
+ }
+
public String toShortString() {
if (shortStringName != null) {
return shortStringName;
diff --git a/services/core/java/com/android/server/am/ReceiverList.java b/services/core/java/com/android/server/am/ReceiverList.java
index 6ade736..a989063 100644
--- a/services/core/java/com/android/server/am/ReceiverList.java
+++ b/services/core/java/com/android/server/am/ReceiverList.java
@@ -21,6 +21,8 @@
import android.os.IBinder;
import android.util.PrintWriterPrinter;
import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
+import com.android.server.am.proto.ReceiverListProto;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -41,7 +43,7 @@
boolean linkedToDeath = false;
String stringName;
-
+
ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
int _pid, int _uid, int _userId, IIntentReceiver _receiver) {
owner = _owner;
@@ -59,12 +61,31 @@
public int hashCode() {
return System.identityHashCode(this);
}
-
+
public void binderDied() {
linkedToDeath = false;
owner.unregisterReceiver(receiver);
}
-
+
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ app.writeToProto(proto, ReceiverListProto.APP);
+ proto.write(ReceiverListProto.PID, pid);
+ proto.write(ReceiverListProto.UID, uid);
+ proto.write(ReceiverListProto.USER, userId);
+ if (curBroadcast != null) {
+ curBroadcast.writeToProto(proto, ReceiverListProto.CURRENT);
+ }
+ proto.write(ReceiverListProto.LINKED_TO_DEATH, linkedToDeath);
+ final int N = size();
+ for (int i=0; i<N; i++) {
+ BroadcastFilter bf = get(i);
+ bf.writeToProto(proto, ReceiverListProto.FILTERS);
+ }
+ proto.write(ReceiverListProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this)));
+ proto.end(token);
+ }
+
void dumpLocal(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("app="); pw.print(app != null ? app.toShortString() : null);
pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid);
@@ -74,7 +95,7 @@
pw.print(" linkedToDeath="); pw.println(linkedToDeath);
}
}
-
+
void dump(PrintWriter pw, String prefix) {
Printer pr = new PrintWriterPrinter(pw);
dumpLocal(pw, prefix);
@@ -89,7 +110,7 @@
bf.dumpInReceiverList(pw, pr, p2);
}
}
-
+
public String toString() {
if (stringName != null) {
return stringName;
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 365c5b1..8fef6be 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -16,15 +16,25 @@
package com.android.server.am;
+import static android.app.ActivityManager.FLAG_AND_UNLOCKED;
+import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
+import static android.app.ActivityManager.RECENT_WITH_EXCLUDED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import com.google.android.collect.Sets;
@@ -37,43 +47,87 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Bundle;
import android.os.Environment;
+import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.ArraySet;
+import android.util.MutableBoolean;
+import android.util.MutableInt;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.am.ActivityStack.ActivityState;
+
import java.io.File;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
/**
- * Class for managing the recent tasks list.
+ * Class for managing the recent tasks list. The list is ordered by most recent (index 0) to the
+ * least recent.
*/
-class RecentTasks extends ArrayList<TaskRecord> {
+class RecentTasks {
private static final String TAG = TAG_WITH_CLASS_NAME ? "RecentTasks" : TAG_AM;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+ private static final boolean TRIMMED = true;
- // Maximum number recent bitmaps to keep in memory.
- private static final int MAX_RECENT_BITMAPS = 3;
private static final int DEFAULT_INITIAL_CAPACITY = 5;
// Whether or not to move all affiliated tasks to the front when one of the tasks is launched
private static final boolean MOVE_AFFILIATED_TASKS_TO_FRONT = false;
+ // Comparator to sort by taskId
+ private static final Comparator<TaskRecord> TASK_ID_COMPARATOR =
+ (lhs, rhs) -> rhs.taskId - lhs.taskId;
+
+ // Placeholder variables to keep track of activities/apps that are no longer avialble while
+ // iterating through the recents list
+ private static final ActivityInfo NO_ACTIVITY_INFO_TOKEN = new ActivityInfo();
+ private static final ApplicationInfo NO_APPLICATION_INFO_TOKEN = new ApplicationInfo();
+
+ /**
+ * Callbacks made when manipulating the list.
+ */
+ interface Callbacks {
+ /**
+ * Called when a task is added to the recent tasks list.
+ */
+ void onRecentTaskAdded(TaskRecord task);
+
+ /**
+ * Called when a task is removed from the recent tasks list.
+ */
+ void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed);
+ }
+
/**
* Save recent tasks information across reboots.
*/
private final TaskPersister mTaskPersister;
private final ActivityManagerService mService;
+ private final UserController mUserController;
+
+ /**
+ * Mapping of user id -> whether recent tasks have been loaded for that user.
+ */
private final SparseBooleanArray mUsersWithRecentsLoaded = new SparseBooleanArray(
DEFAULT_INITIAL_CAPACITY);
@@ -81,21 +135,106 @@
* Stores for each user task ids that are taken by tasks residing in persistent storage. These
* tasks may or may not currently be in memory.
*/
- final SparseArray<SparseBooleanArray> mPersistedTaskIds = new SparseArray<>(
+ private final SparseArray<SparseBooleanArray> mPersistedTaskIds = new SparseArray<>(
DEFAULT_INITIAL_CAPACITY);
+ // List of all active recent tasks
+ private final ArrayList<TaskRecord> mTasks = new ArrayList<>();
+ private final ArrayList<Callbacks> mCallbacks = new ArrayList<>();
+
+ // These values are generally loaded from resources, but can be set dynamically in the tests
+ private boolean mHasVisibleRecentTasks;
+ private int mGlobalMaxNumTasks;
+ private int mMinNumVisibleTasks;
+ private int mMaxNumVisibleTasks;
+ private long mActiveTasksSessionDurationMs;
+
// Mainly to avoid object recreation on multiple calls.
- private final ArrayList<TaskRecord> mTmpRecents = new ArrayList<TaskRecord>();
+ private final ArrayList<TaskRecord> mTmpRecents = new ArrayList<>();
private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>();
private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>();
- private final ActivityInfo mTmpActivityInfo = new ActivityInfo();
- private final ApplicationInfo mTmpAppInfo = new ApplicationInfo();
+ private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray();
- RecentTasks(ActivityManagerService service, ActivityStackSupervisor mStackSupervisor) {
- File systemDir = Environment.getDataSystemDirectory();
+ @VisibleForTesting
+ RecentTasks(ActivityManagerService service, TaskPersister taskPersister,
+ UserController userController) {
mService = service;
- mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, service, this);
- mStackSupervisor.setRecentTasks(this);
+ mUserController = userController;
+ mTaskPersister = taskPersister;
+ mGlobalMaxNumTasks = ActivityManager.getMaxRecentTasksStatic();
+ mHasVisibleRecentTasks = true;
+ }
+
+ RecentTasks(ActivityManagerService service, ActivityStackSupervisor stackSupervisor) {
+ final File systemDir = Environment.getDataSystemDirectory();
+ final Resources res = service.mContext.getResources();
+ mService = service;
+ mUserController = service.mUserController;
+ mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this);
+ mGlobalMaxNumTasks = ActivityManager.getMaxRecentTasksStatic();
+ mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
+ loadParametersFromResources(service.mContext.getResources());
+ }
+
+ @VisibleForTesting
+ void setParameters(int minNumVisibleTasks, int maxNumVisibleTasks,
+ long activeSessionDurationMs) {
+ mMinNumVisibleTasks = minNumVisibleTasks;
+ mMaxNumVisibleTasks = maxNumVisibleTasks;
+ mActiveTasksSessionDurationMs = activeSessionDurationMs;
+ }
+
+ @VisibleForTesting
+ void setGlobalMaxNumTasks(int globalMaxNumTasks) {
+ mGlobalMaxNumTasks = globalMaxNumTasks;
+ }
+
+ /**
+ * Loads the parameters from the system resources.
+ */
+ @VisibleForTesting
+ void loadParametersFromResources(Resources res) {
+ if (ActivityManager.isLowRamDeviceStatic()) {
+ mMinNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_minNumVisibleRecentTasks_lowRam);
+ mMaxNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_maxNumVisibleRecentTasks_lowRam);
+ } else if (SystemProperties.getBoolean("ro.recents.grid", false)) {
+ mMinNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_minNumVisibleRecentTasks_grid);
+ mMaxNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_maxNumVisibleRecentTasks_grid);
+ } else {
+ mMinNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_minNumVisibleRecentTasks);
+ mMaxNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_maxNumVisibleRecentTasks);
+ }
+ final int sessionDurationHrs = res.getInteger(
+ com.android.internal.R.integer.config_activeTaskDurationHours);
+ mActiveTasksSessionDurationMs = (sessionDurationHrs > 0)
+ ? TimeUnit.HOURS.toMillis(sessionDurationHrs)
+ : -1;
+ }
+
+ void registerCallback(Callbacks callback) {
+ mCallbacks.add(callback);
+ }
+
+ void unregisterCallback(Callbacks callback) {
+ mCallbacks.remove(callback);
+ }
+
+ private void notifyTaskAdded(TaskRecord task) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onRecentTaskAdded(task);
+ }
+ }
+
+ private void notifyTaskRemoved(TaskRecord task, boolean wasTrimmed) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onRecentTaskRemoved(task, wasTrimmed);
+ }
}
/**
@@ -106,6 +245,7 @@
*/
void loadUserRecentsLocked(int userId) {
if (mUsersWithRecentsLoaded.get(userId)) {
+ // User already loaded, return early
return;
}
@@ -114,14 +254,14 @@
// Check if any tasks are added before recents is loaded
final SparseBooleanArray preaddedTasks = new SparseBooleanArray();
- for (final TaskRecord task : this) {
+ for (final TaskRecord task : mTasks) {
if (task.userId == userId && shouldPersistTaskLocked(task)) {
preaddedTasks.put(task.taskId, true);
}
}
Slog.i(TAG, "Loading recents for user " + userId + " into memory.");
- addAll(mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks));
+ mTasks.addAll(mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks));
cleanupLocked(userId);
mUsersWithRecentsLoaded.put(userId, true);
@@ -140,11 +280,25 @@
}
}
- boolean taskIdTakenForUserLocked(int taskId, int userId) {
+ /**
+ * @return whether the {@param taskId} is currently in use for the given user.
+ */
+ boolean containsTaskId(int taskId, int userId) {
loadPersistedTaskIdsForUserLocked(userId);
return mPersistedTaskIds.get(userId).get(taskId);
}
+ /**
+ * @return all the task ids for the user with the given {@param userId}.
+ */
+ SparseBooleanArray getTaskIdsForUser(int userId) {
+ loadPersistedTaskIdsForUserLocked(userId);
+ return mPersistedTaskIds.get(userId);
+ }
+
+ /**
+ * Kicks off the task persister to write any pending tasks to disk.
+ */
void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
final ActivityStack stack = task != null ? task.getStack() : null;
if (stack != null && stack.isHomeOrRecentsStack()) {
@@ -164,8 +318,8 @@
mPersistedTaskIds.valueAt(i).clear();
}
}
- for (int i = size() - 1; i >= 0; i--) {
- final TaskRecord task = get(i);
+ for (int i = mTasks.size() - 1; i >= 0; i--) {
+ final TaskRecord task = mTasks.get(i);
if (shouldPersistTaskLocked(task)) {
// Set of persisted taskIds for task.userId should not be null here
// TODO Investigate why it can happen. For now initialize with an empty set
@@ -180,12 +334,12 @@
}
private static boolean shouldPersistTaskLocked(TaskRecord task) {
- final ActivityStack<?> stack = task.getStack();
+ final ActivityStack stack = task.getStack();
return task.isPersistable && (stack == null || !stack.isHomeOrRecentsStack());
}
void onSystemReadyLocked() {
- clear();
+ mTasks.clear();
mTaskPersister.startPersisting();
}
@@ -225,14 +379,6 @@
return usersWithRecentsLoaded;
}
- private void unloadUserRecentsLocked(int userId) {
- if (mUsersWithRecentsLoaded.get(userId)) {
- Slog.i(TAG, "Unloading recents for user " + userId + " from memory.");
- mUsersWithRecentsLoaded.delete(userId);
- removeTasksForUserLocked(userId);
- }
- }
-
/**
* Removes recent tasks and any other state kept in memory for the passed in user. Does not
* touch the information present on persistent storage.
@@ -240,44 +386,36 @@
* @param userId the id of the user
*/
void unloadUserDataFromMemoryLocked(int userId) {
- unloadUserRecentsLocked(userId);
+ if (mUsersWithRecentsLoaded.get(userId)) {
+ Slog.i(TAG, "Unloading recents for user " + userId + " from memory.");
+ mUsersWithRecentsLoaded.delete(userId);
+ removeTasksForUserLocked(userId);
+ }
mPersistedTaskIds.delete(userId);
mTaskPersister.unloadUserDataFromMemory(userId);
}
- TaskRecord taskForIdLocked(int id) {
- final int recentsCount = size();
- for (int i = 0; i < recentsCount; i++) {
- TaskRecord tr = get(i);
- if (tr.taskId == id) {
- return tr;
- }
- }
- return null;
- }
-
/** Remove recent tasks for a user. */
- void removeTasksForUserLocked(int userId) {
+ private void removeTasksForUserLocked(int userId) {
if(userId <= 0) {
Slog.i(TAG, "Can't remove recent task on user " + userId);
return;
}
- for (int i = size() - 1; i >= 0; --i) {
- TaskRecord tr = get(i);
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ TaskRecord tr = mTasks.get(i);
if (tr.userId == userId) {
if(DEBUG_TASKS) Slog.i(TAG_TASKS,
"remove RecentTask " + tr + " when finishing user" + userId);
- remove(i);
- tr.removedFromRecents();
+ remove(mTasks.get(i));
}
}
}
void onPackagesSuspendedChanged(String[] packages, boolean suspended, int userId) {
final Set<String> packageNames = Sets.newHashSet(packages);
- for (int i = size() - 1; i >= 0; --i) {
- final TaskRecord tr = get(i);
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ final TaskRecord tr = mTasks.get(i);
if (tr.realActivity != null
&& packageNames.contains(tr.realActivity.getPackageName())
&& tr.userId == userId
@@ -286,7 +424,38 @@
notifyTaskPersisterLocked(tr, false);
}
}
+ }
+ void removeTasksByPackageName(String packageName, int userId) {
+ final int size = mTasks.size();
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+ final String taskPackageName =
+ tr.getBaseIntent().getComponent().getPackageName();
+ if (tr.userId != userId) return;
+ if (!taskPackageName.equals(packageName)) return;
+
+ mService.mStackSupervisor.removeTaskByIdLocked(tr.taskId, true, REMOVE_FROM_RECENTS);
+ }
+ }
+
+ void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses,
+ int userId) {
+ final int size = mTasks.size();
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+ if (userId != UserHandle.USER_ALL && tr.userId != userId) {
+ continue;
+ }
+
+ ComponentName cn = tr.intent.getComponent();
+ final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
+ && (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
+ if (sameComponent) {
+ mService.mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
+ REMOVE_FROM_RECENTS);
+ }
+ }
}
/**
@@ -295,24 +464,28 @@
* of affiliations.
*/
void cleanupLocked(int userId) {
- int recentsCount = size();
+ int recentsCount = mTasks.size();
if (recentsCount == 0) {
// Happens when called from the packagemanager broadcast before boot,
// or just any empty list.
return;
}
+ // Clear the temp lists
+ mTmpAvailActCache.clear();
+ mTmpAvailAppCache.clear();
+
final IPackageManager pm = AppGlobals.getPackageManager();
for (int i = recentsCount - 1; i >= 0; i--) {
- final TaskRecord task = get(i);
+ final TaskRecord task = mTasks.get(i);
if (userId != UserHandle.USER_ALL && task.userId != userId) {
// Only look at tasks for the user ID of interest.
continue;
}
if (task.autoRemoveRecents && task.getTopActivity() == null) {
// This situation is broken, and we should just get rid of it now.
- remove(i);
- task.removedFromRecents();
+ mTasks.remove(i);
+ notifyTaskRemoved(task, !TRIMMED);
Slog.w(TAG, "Removing auto-remove without activity: " + task);
continue;
}
@@ -331,11 +504,11 @@
continue;
}
if (ai == null) {
- ai = mTmpActivityInfo;
+ ai = NO_ACTIVITY_INFO_TOKEN;
}
mTmpAvailActCache.put(task.realActivity, ai);
}
- if (ai == mTmpActivityInfo) {
+ if (ai == NO_ACTIVITY_INFO_TOKEN) {
// This could be either because the activity no longer exists, or the
// app is temporarily gone. For the former we want to remove the recents
// entry; for the latter we want to mark it as unavailable.
@@ -350,15 +523,15 @@
continue;
}
if (app == null) {
- app = mTmpAppInfo;
+ app = NO_APPLICATION_INFO_TOKEN;
}
mTmpAvailAppCache.put(task.realActivity.getPackageName(), app);
}
- if (app == mTmpAppInfo
+ if (app == NO_APPLICATION_INFO_TOKEN
|| (app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
// Doesn't exist any more! Good-bye.
- remove(i);
- task.removedFromRecents();
+ mTasks.remove(i);
+ notifyTaskRemoved(task, !TRIMMED);
Slog.w(TAG, "Removing no longer valid recent: " + task);
continue;
} else {
@@ -390,15 +563,670 @@
// Verify the affiliate chain for each task.
int i = 0;
- recentsCount = size();
+ recentsCount = mTasks.size();
while (i < recentsCount) {
i = processNextAffiliateChainLocked(i);
}
// recent tasks are now in sorted, affiliated order.
}
- private final boolean moveAffiliatedTasksToFront(TaskRecord task, int taskIndex) {
- int recentsCount = size();
+ /**
+ * @return whether the given {@param task} can be added to the list without causing another
+ * task to be trimmed as a result of that add.
+ */
+ private boolean canAddTaskWithoutTrim(TaskRecord task) {
+ return findTrimIndexForAddTask(task) == -1;
+ }
+
+ /**
+ * Returns the list of {@link ActivityManager.AppTask}s.
+ */
+ ArrayList<IBinder> getAppTasksList(int callingUid, String callingPackage) {
+ final ArrayList<IBinder> list = new ArrayList<>();
+ final int size = mTasks.size();
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+ // Skip tasks that do not match the caller. We don't need to verify
+ // callingPackage, because we are also limiting to callingUid and know
+ // that will limit to the correct security sandbox.
+ if (tr.effectiveUid != callingUid) {
+ continue;
+ }
+ Intent intent = tr.getBaseIntent();
+ if (intent == null || !callingPackage.equals(intent.getComponent().getPackageName())) {
+ continue;
+ }
+ ActivityManager.RecentTaskInfo taskInfo = createRecentTaskInfo(tr);
+ AppTaskImpl taskImpl = new AppTaskImpl(mService, taskInfo.persistentId, callingUid);
+ list.add(taskImpl.asBinder());
+ }
+ return list;
+ }
+
+ /**
+ * @return the list of recent tasks for presentation.
+ */
+ ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags,
+ boolean getTasksAllowed, boolean getDetailedTasks, int userId, int callingUid) {
+ final boolean withExcluded = (flags & RECENT_WITH_EXCLUDED) != 0;
+
+ if (!mService.isUserRunning(userId, FLAG_AND_UNLOCKED)) {
+ Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
+ return ParceledListSlice.emptyList();
+ }
+ loadUserRecentsLocked(userId);
+
+ final Set<Integer> includedUsers = mUserController.getProfileIds(userId);
+ includedUsers.add(Integer.valueOf(userId));
+
+ final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
+ final int size = mTasks.size();
+ int numVisibleTasks = 0;
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+
+ if (isVisibleRecentTask(tr)) {
+ numVisibleTasks++;
+ if (isInVisibleRange(tr, numVisibleTasks)) {
+ // Fall through
+ } else {
+ // Not in visible range
+ continue;
+ }
+ } else {
+ // Not visible
+ continue;
+ }
+
+ // Skip remaining tasks once we reach the requested size
+ if (res.size() >= maxNum) {
+ continue;
+ }
+
+ // Only add calling user or related users recent tasks
+ if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
+ continue;
+ }
+
+ if (tr.realActivitySuspended) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, activity suspended: " + tr);
+ continue;
+ }
+
+ // Return the entry if desired by the caller. We always return
+ // the first entry, because callers always expect this to be the
+ // foreground app. We may filter others if the caller has
+ // not supplied RECENT_WITH_EXCLUDED and there is some reason
+ // we should exclude the entry.
+
+ if (i == 0
+ || withExcluded
+ || (tr.intent == null)
+ || ((tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ == 0)) {
+ if (!getTasksAllowed) {
+ // If the caller doesn't have the GET_TASKS permission, then only
+ // allow them to see a small subset of tasks -- their own and home.
+ if (!tr.isActivityTypeHome() && tr.effectiveUid != callingUid) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not allowed: " + tr);
+ continue;
+ }
+ }
+ if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
+ // Don't include auto remove tasks that are finished or finishing.
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, auto-remove without activity: " + tr);
+ continue;
+ }
+ if ((flags & RECENT_IGNORE_UNAVAILABLE) != 0 && !tr.isAvailable) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, unavail real act: " + tr);
+ continue;
+ }
+
+ if (!tr.mUserSetupComplete) {
+ // Don't include task launched while user is not done setting-up.
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, user setup not complete: " + tr);
+ continue;
+ }
+
+ ActivityManager.RecentTaskInfo rti = RecentTasks.createRecentTaskInfo(tr);
+ if (!getDetailedTasks) {
+ rti.baseIntent.replaceExtras((Bundle)null);
+ }
+
+ res.add(rti);
+ }
+ }
+ return new ParceledListSlice<>(res);
+ }
+
+ /**
+ * @return the list of persistable task ids.
+ */
+ void getPersistableTaskIds(ArraySet<Integer> persistentTaskIds) {
+ final int size = mTasks.size();
+ for (int i = 0; i < size; i++) {
+ final TaskRecord task = mTasks.get(i);
+ if (TaskPersister.DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task
+ + " persistable=" + task.isPersistable);
+ final ActivityStack stack = task.getStack();
+ if ((task.isPersistable || task.inRecents)
+ && (stack == null || !stack.isHomeOrRecentsStack())) {
+ if (TaskPersister.DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
+ persistentTaskIds.add(task.taskId);
+ } else {
+ if (TaskPersister.DEBUG) Slog.d(TAG, "omitting from persistentTaskIds task="
+ + task);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ ArrayList<TaskRecord> getRawTasks() {
+ return mTasks;
+ }
+
+ /**
+ * @return the task in the task list with the given {@param id} if one exists.
+ */
+ TaskRecord getTask(int id) {
+ final int recentsCount = mTasks.size();
+ for (int i = 0; i < recentsCount; i++) {
+ TaskRecord tr = mTasks.get(i);
+ if (tr.taskId == id) {
+ return tr;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Add a new task to the recent tasks list.
+ */
+ void add(TaskRecord task) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "add: task=" + task);
+
+ final boolean isAffiliated = task.mAffiliatedTaskId != task.taskId
+ || task.mNextAffiliateTaskId != INVALID_TASK_ID
+ || task.mPrevAffiliateTaskId != INVALID_TASK_ID;
+
+ int recentsCount = mTasks.size();
+ // Quick case: never add voice sessions.
+ // TODO: VI what about if it's just an activity?
+ // Probably nothing to do here
+ if (task.voiceSession != null) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "addRecent: not adding voice interaction " + task);
+ return;
+ }
+ // Another quick case: check if the top-most recent task is the same.
+ if (!isAffiliated && recentsCount > 0 && mTasks.get(0) == task) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: already at top: " + task);
+ return;
+ }
+ // Another quick case: check if this is part of a set of affiliated
+ // tasks that are at the top.
+ if (isAffiliated && recentsCount > 0 && task.inRecents
+ && task.mAffiliatedTaskId == mTasks.get(0).mAffiliatedTaskId) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: affiliated " + mTasks.get(0)
+ + " at top when adding " + task);
+ return;
+ }
+
+ boolean needAffiliationFix = false;
+
+ // Slightly less quick case: the task is already in recents, so all we need
+ // to do is move it.
+ if (task.inRecents) {
+ int taskIndex = mTasks.indexOf(task);
+ if (taskIndex >= 0) {
+ if (!isAffiliated || !MOVE_AFFILIATED_TASKS_TO_FRONT) {
+ // Simple case: this is not an affiliated task, so we just move it to the front.
+ mTasks.remove(taskIndex);
+ mTasks.add(0, task);
+ notifyTaskPersisterLocked(task, false);
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving to top " + task
+ + " from " + taskIndex);
+ return;
+ } else {
+ // More complicated: need to keep all affiliated tasks together.
+ if (moveAffiliatedTasksToFront(task, taskIndex)) {
+ // All went well.
+ return;
+ }
+
+ // Uh oh... something bad in the affiliation chain, try to rebuild
+ // everything and then go through our general path of adding a new task.
+ needAffiliationFix = true;
+ }
+ } else {
+ Slog.wtf(TAG, "Task with inRecent not in recents: " + task);
+ needAffiliationFix = true;
+ }
+ }
+
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: trimming tasks for " + task);
+ trimForAddTask(task);
+
+ task.inRecents = true;
+ if (!isAffiliated || needAffiliationFix) {
+ // If this is a simple non-affiliated task, or we had some failure trying to
+ // handle it as part of an affilated task, then just place it at the top.
+ mTasks.add(0, task);
+ notifyTaskAdded(task);
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding " + task);
+ } else if (isAffiliated) {
+ // If this is a new affiliated task, then move all of the affiliated tasks
+ // to the front and insert this new one.
+ TaskRecord other = task.mNextAffiliate;
+ if (other == null) {
+ other = task.mPrevAffiliate;
+ }
+ if (other != null) {
+ int otherIndex = mTasks.indexOf(other);
+ if (otherIndex >= 0) {
+ // Insert new task at appropriate location.
+ int taskIndex;
+ if (other == task.mNextAffiliate) {
+ // We found the index of our next affiliation, which is who is
+ // before us in the list, so add after that point.
+ taskIndex = otherIndex+1;
+ } else {
+ // We found the index of our previous affiliation, which is who is
+ // after us in the list, so add at their position.
+ taskIndex = otherIndex;
+ }
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "addRecent: new affiliated task added at " + taskIndex + ": " + task);
+ mTasks.add(taskIndex, task);
+ notifyTaskAdded(task);
+
+ // Now move everything to the front.
+ if (moveAffiliatedTasksToFront(task, taskIndex)) {
+ // All went well.
+ return;
+ }
+
+ // Uh oh... something bad in the affiliation chain, try to rebuild
+ // everything and then go through our general path of adding a new task.
+ needAffiliationFix = true;
+ } else {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "addRecent: couldn't find other affiliation " + other);
+ needAffiliationFix = true;
+ }
+ } else {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "addRecent: adding affiliated task without next/prev:" + task);
+ needAffiliationFix = true;
+ }
+ }
+
+ if (needAffiliationFix) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: regrouping affiliations");
+ cleanupLocked(task.userId);
+ }
+
+ // Trim the set of tasks to the active set
+ trimInactiveRecentTasks();
+ }
+
+ /**
+ * Add the task to the bottom if possible.
+ */
+ boolean addToBottom(TaskRecord task) {
+ if (!canAddTaskWithoutTrim(task)) {
+ // Adding this task would cause the task to be removed (since it's appended at
+ // the bottom and would be trimmed) so just return now
+ return false;
+ }
+
+ add(task);
+ return true;
+ }
+
+ /**
+ * Remove a task from the recent tasks list.
+ */
+ void remove(TaskRecord task) {
+ mTasks.remove(task);
+ notifyTaskRemoved(task, !TRIMMED);
+ }
+
+ /**
+ * Trims the recents task list to the global max number of recents.
+ */
+ private void trimInactiveRecentTasks() {
+ int recentsCount = mTasks.size();
+
+ // Remove from the end of the list until we reach the max number of recents
+ while (recentsCount > mGlobalMaxNumTasks) {
+ final TaskRecord tr = mTasks.remove(recentsCount - 1);
+ notifyTaskRemoved(tr, TRIMMED);
+ recentsCount--;
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming over max-recents task=" + tr
+ + " max=" + mGlobalMaxNumTasks);
+ }
+
+ // Remove any tasks that belong to currently quiet profiles
+ final int[] profileUserIds = mUserController.getCurrentProfileIds();
+ mTmpQuietProfileUserIds.clear();
+ for (int userId : profileUserIds) {
+ final UserInfo userInfo = mUserController.getUserInfo(userId);
+ if (userInfo.isManagedProfile() && userInfo.isQuietModeEnabled()) {
+ mTmpQuietProfileUserIds.put(userId, true);
+ }
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "User: " + userInfo
+ + " quiet=" + mTmpQuietProfileUserIds.get(userId));
+ }
+
+ // Remove any inactive tasks, calculate the latest set of visible tasks
+ int numVisibleTasks = 0;
+ for (int i = 0; i < mTasks.size();) {
+ final TaskRecord task = mTasks.get(i);
+
+ if (isActiveRecentTask(task, mTmpQuietProfileUserIds)) {
+ if (!mHasVisibleRecentTasks) {
+ // Keep all active tasks if visible recent tasks is not supported
+ i++;
+ continue;
+ }
+
+ if (!isVisibleRecentTask(task)) {
+ // Keep all active-but-invisible tasks
+ i++;
+ continue;
+ } else {
+ numVisibleTasks++;
+ if (isInVisibleRange(task, numVisibleTasks)) {
+ // Keep visible tasks in range
+ i++;
+ continue;
+ } else {
+ // Fall through to trim visible tasks that are no longer in range
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG,
+ "Trimming out-of-range visible task=" + task);
+ }
+ }
+ } else {
+ // Fall through to trim inactive tasks
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming inactive task=" + task);
+ }
+
+ // Task is no longer active, trim it from the list
+ mTasks.remove(task);
+ notifyTaskRemoved(task, TRIMMED);
+ notifyTaskPersisterLocked(task, false /* flush */);
+ }
+ }
+
+ /**
+ * @return whether the given task should be considered active.
+ */
+ private boolean isActiveRecentTask(TaskRecord task, SparseBooleanArray quietProfileUserIds) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isActiveRecentTask: task=" + task
+ + " globalMax=" + mGlobalMaxNumTasks);
+
+ if (quietProfileUserIds.get(task.userId)) {
+ // Quiet profile user's tasks are never active
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\tisQuietProfileTask=true");
+ return false;
+ }
+
+ if (task.mAffiliatedTaskId != INVALID_TASK_ID && task.mAffiliatedTaskId != task.taskId) {
+ // Keep the task active if its affiliated task is also active
+ final TaskRecord affiliatedTask = getTask(task.mAffiliatedTaskId);
+ if (affiliatedTask != null) {
+ if (!isActiveRecentTask(affiliatedTask, quietProfileUserIds)) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG,
+ "\taffiliatedWithTask=" + affiliatedTask + " is not active");
+ return false;
+ }
+ }
+ }
+
+ // All other tasks are considered active
+ return true;
+ }
+
+ /**
+ * @return whether the given active task should be presented to the user through SystemUI.
+ */
+ private boolean isVisibleRecentTask(TaskRecord task) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isVisibleRecentTask: task=" + task
+ + " minVis=" + mMinNumVisibleTasks + " maxVis=" + mMaxNumVisibleTasks
+ + " sessionDuration=" + mActiveTasksSessionDurationMs
+ + " inactiveDuration=" + task.getInactiveDuration()
+ + " activityType=" + task.getActivityType()
+ + " windowingMode=" + task.getWindowingMode());
+
+ // Ignore certain activity types completely
+ switch (task.getActivityType()) {
+ case ACTIVITY_TYPE_HOME:
+ case ACTIVITY_TYPE_RECENTS:
+ return false;
+ }
+
+ // Ignore certain windowing modes
+ switch (task.getWindowingMode()) {
+ case WINDOWING_MODE_PINNED:
+ return false;
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\ttop=" + task.getStack().topTask());
+ final ActivityStack stack = task.getStack();
+ if (stack != null && stack.topTask() == task) {
+ // Only the non-top task of the primary split screen mode is visible
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @return whether the given visible task is within the policy range.
+ */
+ private boolean isInVisibleRange(TaskRecord task, int numVisibleTasks) {
+ // Keep the last most task even if it is excluded from recents
+ final boolean isExcludeFromRecents =
+ (task.getBaseIntent().getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+ if (isExcludeFromRecents) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\texcludeFromRecents=true");
+ return numVisibleTasks == 1;
+ }
+
+ if (mMinNumVisibleTasks >= 0 && numVisibleTasks <= mMinNumVisibleTasks) {
+ // Always keep up to the min number of recent tasks, after that fall through to the
+ // checks below
+ return true;
+ }
+
+ if (mMaxNumVisibleTasks >= 0) {
+ // Always keep up to the max number of recent tasks, but return false afterwards
+ return numVisibleTasks <= mMaxNumVisibleTasks;
+ }
+
+ if (mActiveTasksSessionDurationMs > 0) {
+ // Keep the task if the inactive time is within the session window, this check must come
+ // after the checks for the min/max visible task range
+ if (task.getInactiveDuration() <= mActiveTasksSessionDurationMs) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * If needed, remove oldest existing entries in recents that are for the same kind
+ * of task as the given one.
+ */
+ private void trimForAddTask(TaskRecord task) {
+ final int removeIndex = findTrimIndexForAddTask(task);
+ if (removeIndex == -1) {
+ // Nothing to trim
+ return;
+ }
+
+ // There is a similar task that will be removed for the addition of {@param task}, but it
+ // can be the same task, and if so, the task will be re-added in add(), so skip the
+ // callbacks here.
+ final TaskRecord removedTask = mTasks.remove(removeIndex);
+ if (removedTask != task) {
+ notifyTaskRemoved(removedTask, TRIMMED);
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming task=" + removedTask
+ + " for addition of task=" + task);
+ }
+ notifyTaskPersisterLocked(removedTask, false /* flush */);
+ }
+
+ /**
+ * Find the task that would be removed if the given {@param task} is added to the recent tasks
+ * list (if any).
+ */
+ private int findTrimIndexForAddTask(TaskRecord task) {
+ int recentsCount = mTasks.size();
+ final Intent intent = task.intent;
+ final boolean document = intent != null && intent.isDocument();
+ int maxRecents = task.maxRecents - 1;
+ final ActivityStack stack = task.getStack();
+ for (int i = 0; i < recentsCount; i++) {
+ final TaskRecord tr = mTasks.get(i);
+ final ActivityStack trStack = tr.getStack();
+
+ if (task != tr) {
+ if (stack != null && trStack != null && stack != trStack) {
+ continue;
+ }
+ if (task.userId != tr.userId) {
+ continue;
+ }
+ final Intent trIntent = tr.intent;
+ final boolean sameAffinity =
+ task.affinity != null && task.affinity.equals(tr.affinity);
+ final boolean sameIntent = intent != null && intent.filterEquals(trIntent);
+ boolean multiTasksAllowed = false;
+ final int flags = intent.getFlags();
+ if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0
+ && (flags & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
+ multiTasksAllowed = true;
+ }
+ final boolean trIsDocument = trIntent != null && trIntent.isDocument();
+ final boolean bothDocuments = document && trIsDocument;
+ if (!sameAffinity && !sameIntent && !bothDocuments) {
+ continue;
+ }
+
+ if (bothDocuments) {
+ // Do these documents belong to the same activity?
+ final boolean sameActivity = task.realActivity != null
+ && tr.realActivity != null
+ && task.realActivity.equals(tr.realActivity);
+ if (!sameActivity) {
+ // If the document is open in another app or is not the same document, we
+ // don't need to trim it.
+ continue;
+ } else if (maxRecents > 0) {
+ // Otherwise only trim if we are over our max recents for this task
+ --maxRecents;
+ if (!sameIntent || multiTasksAllowed) {
+ // We don't want to trim if we are not over the max allowed entries and
+ // the tasks are not of the same intent filter, or multiple entries for
+ // the task is allowed.
+ continue;
+ }
+ }
+ // Hit the maximum number of documents for this task. Fall through
+ // and remove this document from recents.
+ } else if (document || trIsDocument) {
+ // Only one of these is a document. Not the droid we're looking for.
+ continue;
+ }
+ }
+ return i;
+ }
+ return -1;
+ }
+
+ // Extract the affiliates of the chain containing recent at index start.
+ private int processNextAffiliateChainLocked(int start) {
+ final TaskRecord startTask = mTasks.get(start);
+ final int affiliateId = startTask.mAffiliatedTaskId;
+
+ // Quick identification of isolated tasks. I.e. those not launched behind.
+ if (startTask.taskId == affiliateId && startTask.mPrevAffiliate == null &&
+ startTask.mNextAffiliate == null) {
+ // There is still a slim chance that there are other tasks that point to this task
+ // and that the chain is so messed up that this task no longer points to them but
+ // the gain of this optimization outweighs the risk.
+ startTask.inRecents = true;
+ return start + 1;
+ }
+
+ // Remove all tasks that are affiliated to affiliateId and put them in mTmpRecents.
+ mTmpRecents.clear();
+ for (int i = mTasks.size() - 1; i >= start; --i) {
+ final TaskRecord task = mTasks.get(i);
+ if (task.mAffiliatedTaskId == affiliateId) {
+ mTasks.remove(i);
+ mTmpRecents.add(task);
+ }
+ }
+
+ // Sort them all by taskId. That is the order they were create in and that order will
+ // always be correct.
+ Collections.sort(mTmpRecents, TASK_ID_COMPARATOR);
+
+ // Go through and fix up the linked list.
+ // The first one is the end of the chain and has no next.
+ final TaskRecord first = mTmpRecents.get(0);
+ first.inRecents = true;
+ if (first.mNextAffiliate != null) {
+ Slog.w(TAG, "Link error 1 first.next=" + first.mNextAffiliate);
+ first.setNextAffiliate(null);
+ notifyTaskPersisterLocked(first, false);
+ }
+ // Everything in the middle is doubly linked from next to prev.
+ final int tmpSize = mTmpRecents.size();
+ for (int i = 0; i < tmpSize - 1; ++i) {
+ final TaskRecord next = mTmpRecents.get(i);
+ final TaskRecord prev = mTmpRecents.get(i + 1);
+ if (next.mPrevAffiliate != prev) {
+ Slog.w(TAG, "Link error 2 next=" + next + " prev=" + next.mPrevAffiliate +
+ " setting prev=" + prev);
+ next.setPrevAffiliate(prev);
+ notifyTaskPersisterLocked(next, false);
+ }
+ if (prev.mNextAffiliate != next) {
+ Slog.w(TAG, "Link error 3 prev=" + prev + " next=" + prev.mNextAffiliate +
+ " setting next=" + next);
+ prev.setNextAffiliate(next);
+ notifyTaskPersisterLocked(prev, false);
+ }
+ prev.inRecents = true;
+ }
+ // The last one is the beginning of the list and has no prev.
+ final TaskRecord last = mTmpRecents.get(tmpSize - 1);
+ if (last.mPrevAffiliate != null) {
+ Slog.w(TAG, "Link error 4 last.prev=" + last.mPrevAffiliate);
+ last.setPrevAffiliate(null);
+ notifyTaskPersisterLocked(last, false);
+ }
+
+ // Insert the group back into mTmpTasks at start.
+ mTasks.addAll(start, mTmpRecents);
+ mTmpRecents.clear();
+
+ // Let the caller know where we left off.
+ return start + tmpSize;
+ }
+
+ private boolean moveAffiliatedTasksToFront(TaskRecord task, int taskIndex) {
+ int recentsCount = mTasks.size();
TaskRecord top = task;
int topIndex = taskIndex;
while (top.mNextAffiliate != null && topIndex > 0) {
@@ -412,7 +1240,7 @@
int endIndex = topIndex;
TaskRecord prev = top;
while (endIndex < recentsCount) {
- TaskRecord cur = get(endIndex);
+ TaskRecord cur = mTasks.get(endIndex);
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: looking at next chain @"
+ endIndex + " " + cur);
if (cur == top) {
@@ -487,8 +1315,8 @@
for (int i=topIndex; i<=endIndex; i++) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving affiliated " + task
+ " from " + i + " to " + (i-topIndex));
- TaskRecord cur = remove(i);
- add(i - topIndex, cur);
+ TaskRecord cur = mTasks.remove(i);
+ mTasks.add(i - topIndex, cur);
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: done moving tasks " + topIndex
+ " to " + endIndex);
@@ -499,301 +1327,87 @@
return false;
}
- final void addLocked(TaskRecord task) {
- final boolean isAffiliated = task.mAffiliatedTaskId != task.taskId
- || task.mNextAffiliateTaskId != INVALID_TASK_ID
- || task.mPrevAffiliateTaskId != INVALID_TASK_ID;
-
- int recentsCount = size();
- // Quick case: never add voice sessions.
- // TODO: VI what about if it's just an activity?
- // Probably nothing to do here
- if (task.voiceSession != null) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "addRecent: not adding voice interaction " + task);
- return;
- }
- // Another quick case: check if the top-most recent task is the same.
- if (!isAffiliated && recentsCount > 0 && get(0) == task) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: already at top: " + task);
- return;
- }
- // Another quick case: check if this is part of a set of affiliated
- // tasks that are at the top.
- if (isAffiliated && recentsCount > 0 && task.inRecents
- && task.mAffiliatedTaskId == get(0).mAffiliatedTaskId) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: affiliated " + get(0)
- + " at top when adding " + task);
+ void dump(PrintWriter pw, boolean dumpAll, String dumpPackage) {
+ pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
+ if (mTasks.isEmpty()) {
return;
}
- boolean needAffiliationFix = false;
+ final MutableBoolean printedAnything = new MutableBoolean(false);
+ final MutableBoolean printedHeader = new MutableBoolean(false);
+ final int size = mTasks.size();
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+ if (dumpPackage != null && (tr.realActivity == null ||
+ !dumpPackage.equals(tr.realActivity.getPackageName()))) {
+ continue;
+ }
- // Slightly less quick case: the task is already in recents, so all we need
- // to do is move it.
- if (task.inRecents) {
- int taskIndex = indexOf(task);
- if (taskIndex >= 0) {
- if (!isAffiliated || MOVE_AFFILIATED_TASKS_TO_FRONT) {
- // Simple case: this is not an affiliated task, so we just move it to the front.
- remove(taskIndex);
- add(0, task);
- notifyTaskPersisterLocked(task, false);
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving to top " + task
- + " from " + taskIndex);
- return;
- } else {
- // More complicated: need to keep all affiliated tasks together.
- if (moveAffiliatedTasksToFront(task, taskIndex)) {
- // All went well.
- return;
- }
-
- // Uh oh... something bad in the affiliation chain, try to rebuild
- // everything and then go through our general path of adding a new task.
- needAffiliationFix = true;
- }
- } else {
- Slog.wtf(TAG, "Task with inRecent not in recents: " + task);
- needAffiliationFix = true;
+ if (!printedHeader.value) {
+ pw.println(" Recent tasks:");
+ printedHeader.value = true;
+ printedAnything.value = true;
+ }
+ pw.print(" * Recent #"); pw.print(i); pw.print(": ");
+ pw.println(tr);
+ if (dumpAll) {
+ tr.dump(pw, " ");
}
}
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: trimming tasks for " + task);
- trimForTaskLocked(task, true);
-
- recentsCount = size();
- final int maxRecents = ActivityManager.getMaxRecentTasksStatic();
- while (recentsCount >= maxRecents) {
- final TaskRecord tr = remove(recentsCount - 1);
- tr.removedFromRecents();
- recentsCount--;
- }
- task.inRecents = true;
- if (!isAffiliated || needAffiliationFix) {
- // If this is a simple non-affiliated task, or we had some failure trying to
- // handle it as part of an affilated task, then just place it at the top.
- add(0, task);
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding " + task);
- } else if (isAffiliated) {
- // If this is a new affiliated task, then move all of the affiliated tasks
- // to the front and insert this new one.
- TaskRecord other = task.mNextAffiliate;
- if (other == null) {
- other = task.mPrevAffiliate;
- }
- if (other != null) {
- int otherIndex = indexOf(other);
- if (otherIndex >= 0) {
- // Insert new task at appropriate location.
- int taskIndex;
- if (other == task.mNextAffiliate) {
- // We found the index of our next affiliation, which is who is
- // before us in the list, so add after that point.
- taskIndex = otherIndex+1;
- } else {
- // We found the index of our previous affiliation, which is who is
- // after us in the list, so add at their position.
- taskIndex = otherIndex;
- }
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "addRecent: new affiliated task added at " + taskIndex + ": " + task);
- add(taskIndex, task);
-
- // Now move everything to the front.
- if (moveAffiliatedTasksToFront(task, taskIndex)) {
- // All went well.
- return;
- }
-
- // Uh oh... something bad in the affiliation chain, try to rebuild
- // everything and then go through our general path of adding a new task.
- needAffiliationFix = true;
- } else {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "addRecent: couldn't find other affiliation " + other);
- needAffiliationFix = true;
- }
- } else {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "addRecent: adding affiliated task without next/prev:" + task);
- needAffiliationFix = true;
- }
- }
-
- if (needAffiliationFix) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: regrouping affiliations");
- cleanupLocked(task.userId);
+ if (!printedAnything.value) {
+ pw.println(" (nothing)");
}
}
/**
- * If needed, remove oldest existing entries in recents that are for the same kind
- * of task as the given one.
+ * Creates a new RecentTaskInfo from a TaskRecord.
*/
- int trimForTaskLocked(TaskRecord task, boolean doTrim) {
- int recentsCount = size();
- final Intent intent = task.intent;
- final boolean document = intent != null && intent.isDocument();
- int maxRecents = task.maxRecents - 1;
- final ActivityStack stack = task.getStack();
- for (int i = 0; i < recentsCount; i++) {
- final TaskRecord tr = get(i);
- final ActivityStack trStack = tr.getStack();
- if (task != tr) {
- if (stack != null && trStack != null && stack != trStack) {
- continue;
- }
- if (task.userId != tr.userId) {
- continue;
- }
- final Intent trIntent = tr.intent;
- final boolean sameAffinity =
- task.affinity != null && task.affinity.equals(tr.affinity);
- final boolean sameIntentFilter = intent != null && intent.filterEquals(trIntent);
- boolean multiTasksAllowed = false;
- final int flags = intent.getFlags();
- if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0
- && (flags & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
- multiTasksAllowed = true;
- }
- final boolean trIsDocument = trIntent != null && trIntent.isDocument();
- final boolean bothDocuments = document && trIsDocument;
- if (!sameAffinity && !sameIntentFilter && !bothDocuments) {
- continue;
- }
+ static ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
+ // Update the task description to reflect any changes in the task stack
+ tr.updateTaskDescription();
- if (bothDocuments) {
- // Do these documents belong to the same activity?
- final boolean sameActivity = task.realActivity != null
- && tr.realActivity != null
- && task.realActivity.equals(tr.realActivity);
- // If the document is open in another app or is not the same
- // document, we don't need to trim it.
- if (!sameActivity) {
- continue;
- // Otherwise only trim if we are over our max recents for this task
- } else if (maxRecents > 0) {
- --maxRecents;
- if (!doTrim || !sameIntentFilter || multiTasksAllowed) {
- // We don't want to trim if we are not over the max allowed entries and
- // the caller doesn't want us to trim, the tasks are not of the same
- // intent filter, or multiple entries fot the task is allowed.
- continue;
- }
- }
- // Hit the maximum number of documents for this task. Fall through
- // and remove this document from recents.
- } else if (document || trIsDocument) {
- // Only one of these is a document. Not the droid we're looking for.
- continue;
- }
- }
+ // Compose the recent task info
+ ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
+ rti.id = tr.getTopActivity() == null ? INVALID_TASK_ID : tr.taskId;
+ rti.persistentId = tr.taskId;
+ rti.baseIntent = new Intent(tr.getBaseIntent());
+ rti.origActivity = tr.origActivity;
+ rti.realActivity = tr.realActivity;
+ rti.description = tr.lastDescription;
+ rti.stackId = tr.getStackId();
+ rti.userId = tr.userId;
+ rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
+ rti.lastActiveTime = tr.lastActiveTime;
+ rti.affiliatedTaskId = tr.mAffiliatedTaskId;
+ rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
+ rti.numActivities = 0;
+ if (tr.mBounds != null) {
+ rti.bounds = new Rect(tr.mBounds);
+ }
+ rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
+ rti.resizeMode = tr.mResizeMode;
+ rti.configuration.setTo(tr.getConfiguration());
- if (!doTrim) {
- // If the caller is not actually asking for a trim, just tell them we reached
- // a point where the trim would happen.
- return i;
- }
+ ActivityRecord base = null;
+ ActivityRecord top = null;
+ ActivityRecord tmp;
- // Either task and tr are the same or, their affinities match or their intents match
- // and neither of them is a document, or they are documents using the same activity
- // and their maxRecents has been reached.
- remove(i);
- if (task != tr) {
- tr.removedFromRecents();
+ for (int i = tr.mActivities.size() - 1; i >= 0; --i) {
+ tmp = tr.mActivities.get(i);
+ if (tmp.finishing) {
+ continue;
}
- i--;
- recentsCount--;
- if (task.intent == null) {
- // If the new recent task we are adding is not fully
- // specified, then replace it with the existing recent task.
- task = tr;
+ base = tmp;
+ if (top == null || (top.state == ActivityState.INITIALIZING)) {
+ top = base;
}
- notifyTaskPersisterLocked(tr, false);
+ rti.numActivities++;
}
- return -1;
- }
+ rti.baseActivity = (base != null) ? base.intent.getComponent() : null;
+ rti.topActivity = (top != null) ? top.intent.getComponent() : null;
- // Sort by taskId
- private static Comparator<TaskRecord> sTaskRecordComparator = new Comparator<TaskRecord>() {
- @Override
- public int compare(TaskRecord lhs, TaskRecord rhs) {
- return rhs.taskId - lhs.taskId;
- }
- };
-
- // Extract the affiliates of the chain containing recent at index start.
- private int processNextAffiliateChainLocked(int start) {
- final TaskRecord startTask = get(start);
- final int affiliateId = startTask.mAffiliatedTaskId;
-
- // Quick identification of isolated tasks. I.e. those not launched behind.
- if (startTask.taskId == affiliateId && startTask.mPrevAffiliate == null &&
- startTask.mNextAffiliate == null) {
- // There is still a slim chance that there are other tasks that point to this task
- // and that the chain is so messed up that this task no longer points to them but
- // the gain of this optimization outweighs the risk.
- startTask.inRecents = true;
- return start + 1;
- }
-
- // Remove all tasks that are affiliated to affiliateId and put them in mTmpRecents.
- mTmpRecents.clear();
- for (int i = size() - 1; i >= start; --i) {
- final TaskRecord task = get(i);
- if (task.mAffiliatedTaskId == affiliateId) {
- remove(i);
- mTmpRecents.add(task);
- }
- }
-
- // Sort them all by taskId. That is the order they were create in and that order will
- // always be correct.
- Collections.sort(mTmpRecents, sTaskRecordComparator);
-
- // Go through and fix up the linked list.
- // The first one is the end of the chain and has no next.
- final TaskRecord first = mTmpRecents.get(0);
- first.inRecents = true;
- if (first.mNextAffiliate != null) {
- Slog.w(TAG, "Link error 1 first.next=" + first.mNextAffiliate);
- first.setNextAffiliate(null);
- notifyTaskPersisterLocked(first, false);
- }
- // Everything in the middle is doubly linked from next to prev.
- final int tmpSize = mTmpRecents.size();
- for (int i = 0; i < tmpSize - 1; ++i) {
- final TaskRecord next = mTmpRecents.get(i);
- final TaskRecord prev = mTmpRecents.get(i + 1);
- if (next.mPrevAffiliate != prev) {
- Slog.w(TAG, "Link error 2 next=" + next + " prev=" + next.mPrevAffiliate +
- " setting prev=" + prev);
- next.setPrevAffiliate(prev);
- notifyTaskPersisterLocked(next, false);
- }
- if (prev.mNextAffiliate != next) {
- Slog.w(TAG, "Link error 3 prev=" + prev + " next=" + prev.mNextAffiliate +
- " setting next=" + next);
- prev.setNextAffiliate(next);
- notifyTaskPersisterLocked(prev, false);
- }
- prev.inRecents = true;
- }
- // The last one is the beginning of the list and has no prev.
- final TaskRecord last = mTmpRecents.get(tmpSize - 1);
- if (last.mPrevAffiliate != null) {
- Slog.w(TAG, "Link error 4 last.prev=" + last.mPrevAffiliate);
- last.setPrevAffiliate(null);
- notifyTaskPersisterLocked(last, false);
- }
-
- // Insert the group back into mRecentTasks at start.
- addAll(start, mTmpRecents);
- mTmpRecents.clear();
-
- // Let the caller know where we left off.
- return start + tmpSize;
+ return rti;
}
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index ac85e6b..16995e5 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -33,6 +33,7 @@
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -517,14 +518,27 @@
} catch (PackageManager.NameNotFoundException e) {
}
}
- if (localForegroundNoti.getSmallIcon() == null
- || nm.getNotificationChannel(localPackageName, appUid,
+ if (nm.getNotificationChannel(localPackageName, appUid,
localForegroundNoti.getChannelId()) == null) {
+ int targetSdkVersion = Build.VERSION_CODES.O_MR1;
+ try {
+ final ApplicationInfo applicationInfo =
+ ams.mContext.getPackageManager().getApplicationInfoAsUser(
+ appInfo.packageName, 0, userId);
+ targetSdkVersion = applicationInfo.targetSdkVersion;
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ if (targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
+ throw new RuntimeException(
+ "invalid channel for service notification: "
+ + foregroundNoti);
+ }
+ }
+ if (localForegroundNoti.getSmallIcon() == null) {
// Notifications whose icon is 0 are defined to not show
// a notification, silently ignoring it. We don't want to
// just ignore it, we want to prevent the service from
// being foreground.
- // Also every notification needs a channel.
throw new RuntimeException("invalid service notification: "
+ foregroundNoti);
}
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 61994b5..2689d6a 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -567,7 +567,7 @@
SparseArray<SparseBooleanArray> changedTaskIdsPerUser = new SparseArray<>();
synchronized (mService) {
for (int userId : mRecentTasks.usersWithRecentsLoadedLocked()) {
- SparseBooleanArray taskIdsToSave = mRecentTasks.mPersistedTaskIds.get(userId);
+ SparseBooleanArray taskIdsToSave = mRecentTasks.getTaskIdsForUser(userId);
SparseBooleanArray persistedIdsInFile = mTaskIdsInFile.get(userId);
if (persistedIdsInFile != null && persistedIdsInFile.equals(taskIdsToSave)) {
continue;
@@ -640,7 +640,7 @@
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- ArraySet<Integer> persistentTaskIds = new ArraySet<Integer>();
+ ArraySet<Integer> persistentTaskIds = new ArraySet<>();
while (true) {
// We can't lock mService while holding TaskPersister.this, but we don't want to
// call removeObsoleteFiles every time through the loop, only the last time before
@@ -654,20 +654,7 @@
persistentTaskIds.clear();
synchronized (mService) {
if (DEBUG) Slog.d(TAG, "mRecents=" + mRecentTasks);
- for (int taskNdx = mRecentTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mRecentTasks.get(taskNdx);
- if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task +
- " persistable=" + task.isPersistable);
- final ActivityStack stack = task.getStack();
- if ((task.isPersistable || task.inRecents)
- && (stack == null || !stack.isHomeOrRecentsStack())) {
- if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
- persistentTaskIds.add(task.taskId);
- } else {
- if (DEBUG) Slog.d(TAG,
- "omitting from persistentTaskIds task=" + task);
- }
- }
+ mRecentTasks.getPersistableTaskIds(persistentTaskIds);
mService.mWindowManager.removeObsoleteTaskFiles(persistentTaskIds,
mRecentTasks.usersWithRecentsLoadedLocked());
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 0d8df79..7817f1a 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -18,10 +18,7 @@
import static android.app.ActivityManager.RESIZE_MODE_FORCED;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -31,6 +28,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
@@ -102,6 +100,7 @@
import android.graphics.Rect;
import android.os.Debug;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
@@ -155,8 +154,6 @@
private static final String ATTR_EFFECTIVE_UID = "effective_uid";
@Deprecated
private static final String ATTR_TASKTYPE = "task_type";
- private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
- private static final String ATTR_LASTACTIVETIME = "last_active_time";
private static final String ATTR_LASTDESCRIPTION = "last_description";
private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
@@ -212,9 +209,10 @@
ComponentName realActivity; // The actual activity component that started the task.
boolean realActivitySuspended; // True if the actual activity component that started the
// task is suspended.
- long firstActiveTime; // First time this task was active.
- long lastActiveTime; // Last time this task was active, including sleep.
boolean inRecents; // Actually in the recents list?
+ long lastActiveTime; // Last time this task was active in the current device session,
+ // including sleep. This time is initialized to the elapsed time when
+ // restored from disk.
boolean isAvailable; // Is the activity available to be launched?
boolean rootWasReset; // True if the intent at the root of the task had
// the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
@@ -339,6 +337,7 @@
TaskPersister.IMAGE_EXTENSION;
userId = UserHandle.getUserId(info.applicationInfo.uid);
taskId = _taskId;
+ lastActiveTime = SystemClock.elapsedRealtime();
mAffiliatedTaskId = _taskId;
voiceSession = _voiceSession;
voiceInteractor = _voiceInteractor;
@@ -359,6 +358,7 @@
TaskPersister.IMAGE_EXTENSION;
userId = UserHandle.getUserId(info.applicationInfo.uid);
taskId = _taskId;
+ lastActiveTime = SystemClock.elapsedRealtime();
mAffiliatedTaskId = _taskId;
voiceSession = null;
voiceInteractor = null;
@@ -385,12 +385,12 @@
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
- long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
- boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
- int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
- int callingUid, String callingPackage, int resizeMode, boolean supportsPictureInPicture,
- boolean privileged, boolean _realActivitySuspended, boolean userSetupComplete,
- int minWidth, int minHeight) {
+ long lastTimeMoved, boolean neverRelinquishIdentity,
+ TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
+ int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
+ int resizeMode, boolean supportsPictureInPicture, boolean privileged,
+ boolean _realActivitySuspended, boolean userSetupComplete, int minWidth,
+ int minHeight) {
mService = service;
mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
TaskPersister.IMAGE_EXTENSION;
@@ -412,8 +412,7 @@
userId = _userId;
mUserSetupComplete = userSetupComplete;
effectiveUid = _effectiveUid;
- firstActiveTime = _firstActiveTime;
- lastActiveTime = _lastActiveTime;
+ lastActiveTime = SystemClock.elapsedRealtime();
lastDescription = _lastDescription;
mActivities = activities;
mLastTimeMoved = lastTimeMoved;
@@ -520,7 +519,7 @@
// All we can do for now is update the bounds so it can be used when the task is
// added to window manager.
updateOverrideConfiguration(bounds);
- if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
+ if (!inFreeformWindowingMode()) {
// re-restore the task so it can have the proper stack association.
mService.mStackSupervisor.restoreRecentTaskLocked(this, null);
}
@@ -616,8 +615,7 @@
* @return whether the task was reparented
*/
// TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
- // re-parenting the task. Can only be done when we are no longer using static stack Ids like
- /** {@link ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} */
+ // re-parenting the task. Can only be done when we are no longer using static stack Ids.
boolean reparent(ActivityStack preferredStack, int position,
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
boolean schedulePictureInPictureModeChange, String reason) {
@@ -630,12 +628,12 @@
return false;
}
- final int sourceStackId = getStackId();
- final int stackId = toStack.getStackId();
+ final int toStackWindowingMode = toStack.getWindowingMode();
final ActivityRecord topActivity = getTopActivity();
- final boolean mightReplaceWindow = StackId.replaceWindowsOnTaskMove(sourceStackId, stackId)
- && topActivity != null;
+ final boolean mightReplaceWindow =
+ replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode)
+ && topActivity != null;
if (mightReplaceWindow) {
// We are about to relaunch the activity because its configuration changed due to
// being maximized, i.e. size change. The activity will first remove the old window
@@ -707,10 +705,10 @@
toStack.prepareFreezingTaskBounds();
// Make sure the task has the appropriate bounds/size for the stack it is in.
- final int toStackWindowingMode = toStack.getWindowingMode();
final boolean toStackSplitScreenPrimary =
toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
- if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
+ if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
+ || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
&& !Objects.equals(mBounds, toStack.mBounds)) {
kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
deferResume);
@@ -751,7 +749,7 @@
// TODO: Handle incorrect request to move before the actual move, not after.
final boolean inSplitScreenMode = supervisor.getDefaultDisplay().hasSplitScreenStack();
supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
- DEFAULT_DISPLAY, stackId);
+ DEFAULT_DISPLAY, toStack.mStackId);
boolean successful = (preferredStack == toStack);
if (successful && toStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
@@ -761,6 +759,18 @@
return successful;
}
+ /**
+ * Returns true if the windows of tasks being moved to the target stack from the source
+ * stack should be replaced, meaning that window manager will keep the old window around
+ * until the new is ready.
+ * @hide
+ */
+ private static boolean replaceWindowsOnTaskMove(
+ int sourceWindowingMode, int targetWindowingMode) {
+ return sourceWindowingMode == WINDOWING_MODE_FREEFORM
+ || targetWindowingMode == WINDOWING_MODE_FREEFORM;
+ }
+
void cancelWindowTransition() {
mWindowContainerController.cancelWindowTransition();
}
@@ -780,14 +790,11 @@
}
void touchActiveTime() {
- lastActiveTime = System.currentTimeMillis();
- if (firstActiveTime == 0) {
- firstActiveTime = lastActiveTime;
- }
+ lastActiveTime = SystemClock.elapsedRealtime();
}
long getInactiveDuration() {
- return System.currentTimeMillis() - lastActiveTime;
+ return SystemClock.elapsedRealtime() - lastActiveTime;
}
/** Sets the original intent, and the calling uid and package. */
@@ -1263,7 +1270,7 @@
mService.notifyTaskPersisterLocked(this, false);
}
- if (getStackId() == PINNED_STACK_ID) {
+ if (inPinnedWindowingMode()) {
// We normally notify listeners of task stack changes on pause, however pinned stack
// activities are normally in the paused state so no notification will be sent there
// before the activity is removed. We send it here so instead.
@@ -1493,7 +1500,7 @@
* @return True if the requested bounds are okay for a resizing request.
*/
private boolean canResizeToBounds(Rect bounds) {
- if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
+ if (bounds == null || !inFreeformWindowingMode()) {
// Note: If not on the freeform workspace, we ignore the bounds.
return true;
}
@@ -1647,8 +1654,6 @@
out.attribute(null, ATTR_USERID, String.valueOf(userId));
out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
- out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
- out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
if (lastDescription != null) {
@@ -1721,8 +1726,6 @@
boolean userSetupComplete = true;
int effectiveUid = -1;
String lastDescription = null;
- long firstActiveTime = -1;
- long lastActiveTime = -1;
long lastTimeOnTop = 0;
boolean neverRelinquishIdentity = true;
int taskId = INVALID_TASK_ID;
@@ -1774,10 +1777,6 @@
effectiveUid = Integer.parseInt(attrValue);
} else if (ATTR_TASKTYPE.equals(attrName)) {
taskType = Integer.parseInt(attrValue);
- } else if (ATTR_FIRSTACTIVETIME.equals(attrName)) {
- firstActiveTime = Long.parseLong(attrValue);
- } else if (ATTR_LASTACTIVETIME.equals(attrName)) {
- lastActiveTime = Long.parseLong(attrValue);
} else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
lastDescription = attrValue;
} else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
@@ -1888,9 +1887,9 @@
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
- activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
- taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
- callingUid, callingPackage, resizeMode, supportsPictureInPicture, privileged,
+ activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
+ taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
+ callingPackage, resizeMode, supportsPictureInPicture, privileged,
realActivitySuspended, userSetupComplete, minWidth, minHeight);
task.updateOverrideConfiguration(bounds);
@@ -1911,7 +1910,7 @@
// If the task has no requested minimal size, we'd like to enforce a minimal size
// so that the user can not render the task too small to manipulate. We don't need
// to do this for the pinned stack as the bounds are controlled by the system.
- if (getStackId() != PINNED_STACK_ID) {
+ if (!inPinnedWindowingMode()) {
if (minWidth == INVALID_MIN_SIZE) {
minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
}
@@ -2085,7 +2084,7 @@
return;
}
- if (inStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ if (inStack.inFreeformWindowingMode()) {
if (!isResizeable()) {
throw new IllegalArgumentException("Can not position non-resizeable task="
+ this + " in stack=" + inStack);
@@ -2220,7 +2219,6 @@
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
pw.print(" isResizeable=" + isResizeable());
- pw.print(" firstActiveTime=" + firstActiveTime);
pw.print(" lastActiveTime=" + lastActiveTime);
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 6506cf7..4943173 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -184,11 +184,15 @@
}
}
+ private static final int FLAGS_FOR_SILENCE_OVERRIDE =
+ AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
+ AudioAttributes.FLAG_BYPASS_MUTE;
+
private void checkVolumeForPrivilegedAlarm(AudioPlaybackConfiguration apc, int event) {
if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED ||
apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
- if ((apc.getAudioAttributes().getAllFlags() &
- AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0 &&
+ if ((apc.getAudioAttributes().getAllFlags() & FLAGS_FOR_SILENCE_OVERRIDE)
+ == FLAGS_FOR_SILENCE_OVERRIDE &&
apc.getAudioAttributes().getUsage() == AudioAttributes.USAGE_ALARM &&
mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
apc.getClientPid(), apc.getClientUid()) ==
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 0b11479..664d2f9 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -784,6 +784,14 @@
mService.enforcePhoneStatePermission(pid, uid);
}
mFlags = flags;
+ if ((flags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mService.setGlobalPrioritySession(MediaSessionRecord.this);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index b102dde..aa65244 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -178,17 +178,6 @@
return;
}
if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
- if (mGlobalPrioritySession != record) {
- Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
- + " to " + record);
- mGlobalPrioritySession = record;
- if (user != null && user.mPriorityStack.contains(record)) {
- // Handle the global priority session separately.
- // Otherwise, it will be the media button session even after it becomes
- // inactive because it has been the lastly played media app.
- user.mPriorityStack.removeSession(record);
- }
- }
if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
}
@@ -204,6 +193,24 @@
}
}
+ public void setGlobalPrioritySession(MediaSessionRecord record) {
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+ if (mGlobalPrioritySession != record) {
+ Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
+ + " to " + record);
+ mGlobalPrioritySession = record;
+ if (user != null && user.mPriorityStack.contains(record)) {
+ // Handle the global priority session separately.
+ // Otherwise, it can be the media button session regardless of the active state
+ // because it or other system components might have been the lastly played media
+ // app.
+ user.mPriorityStack.removeSession(record);
+ }
+ }
+ }
+ }
+
private List<MediaSessionRecord> getActiveSessionsLocked(int userId) {
List<MediaSessionRecord> records = new ArrayList<>();
if (userId == UserHandle.USER_ALL) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 14cd055..168f070 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -282,6 +282,7 @@
private WindowManagerInternal mWindowManagerInternal;
private AlarmManager mAlarmManager;
private ICompanionDeviceManager mCompanionManager;
+ private AccessibilityManager mAccessibilityManager;
final IBinder mForegroundToken = new Binder();
private WorkerHandler mHandler;
@@ -1221,6 +1222,12 @@
mUsageStats = us;
}
+ @VisibleForTesting
+ void setAccessibilityManager(AccessibilityManager am) {
+ mAccessibilityManager = am;
+ }
+
+
// TODO: All tests should use this init instead of the one-off setters above.
@VisibleForTesting
void init(Looper looper, IPackageManager packageManager,
@@ -1235,6 +1242,8 @@
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE);
+ mAccessibilityManager =
+ (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
mAm = ActivityManager.getService();
mPackageManager = packageManager;
mPackageManagerClient = packageManagerClient;
@@ -4117,13 +4126,16 @@
// These are set inside the conditional if the notification is allowed to make noise.
boolean hasValidVibrate = false;
boolean hasValidSound = false;
+ boolean sentAccessibilityEvent = false;
+ // If the notification will appear in the status bar, it should send an accessibility
+ // event
+ if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) {
+ sendAccessibilityEvent(notification, record.sbn.getPackageName());
+ sentAccessibilityEvent = true;
+ }
if (aboveThreshold && isNotificationForCurrentUser(record)) {
- // If the notification will appear in the status bar, it should send an accessibility
- // event
- if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) {
- sendAccessibilityEvent(notification, record.sbn.getPackageName());
- }
+
if (mSystemReady && mAudioManager != null) {
Uri soundUri = record.getSound();
hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri);
@@ -4141,6 +4153,10 @@
boolean hasAudibleAlert = hasValidSound || hasValidVibrate;
if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) {
+ if (!sentAccessibilityEvent) {
+ sendAccessibilityEvent(notification, record.sbn.getPackageName());
+ sentAccessibilityEvent = true;
+ }
if (DBG) Slog.v(TAG, "Interrupting!");
if (hasValidSound) {
mSoundNotificationKey = key;
@@ -4661,8 +4677,7 @@
}
void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
- AccessibilityManager manager = AccessibilityManager.getInstance(getContext());
- if (!manager.isEnabled()) {
+ if (!mAccessibilityManager.isEnabled()) {
return;
}
@@ -4676,7 +4691,7 @@
event.getText().add(tickerText);
}
- manager.sendAccessibilityEvent(event);
+ mAccessibilityManager.sendAccessibilityEvent(event);
}
/**
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index a7a2743..abf2900 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -117,15 +117,19 @@
ZenLog.traceIntercepted(record, "alarmsOnly");
return true;
case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
- if (isAlarm(record)) {
- // Alarms are always priority
- return false;
- }
// allow user-prioritized packages through in priority mode
if (record.getPackagePriority() == Notification.PRIORITY_MAX) {
ZenLog.traceNotIntercepted(record, "priorityApp");
return false;
}
+
+ if (isAlarm(record)) {
+ if (!config.allowAlarms) {
+ ZenLog.traceIntercepted(record, "!allowAlarms");
+ return true;
+ }
+ return false;
+ }
if (isCall(record)) {
if (config.allowRepeatCallers
&& REPEAT_CALLERS.isRepeat(mContext, extras(record))) {
@@ -159,6 +163,15 @@
}
return false;
}
+ AudioAttributes aa = record.getAudioAttributes();
+ if (aa != null && AudioAttributes.SUPPRESSIBLE_USAGES.get(aa.getUsage()) ==
+ AudioAttributes.SUPPRESSIBLE_MEDIA_SYSTEM_OTHER) {
+ if (!config.allowMediaSystemOther) {
+ ZenLog.traceIntercepted(record, "!allowMediaSystemOther");
+ return true;
+ }
+ return false;
+ }
ZenLog.traceIntercepted(record, "!priority");
return true;
default:
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 9fcc67d..710684f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -59,6 +59,7 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.server.LocalServices;
@@ -87,7 +88,7 @@
private final Context mContext;
private final H mHandler;
private final SettingsObserver mSettingsObserver;
- private final AppOpsManager mAppOps;
+ @VisibleForTesting protected final AppOpsManager mAppOps;
protected ZenModeConfig mDefaultConfig;
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final ZenModeFiltering mFiltering;
@@ -102,9 +103,9 @@
private final String SCHEDULED_DEFAULT_RULE_1 = "SCHEDULED_DEFAULT_RULE_1";
private final String SCHEDULED_DEFAULT_RULE_2 = "SCHEDULED_DEFAULT_RULE_2";
- private int mZenMode;
+ @VisibleForTesting protected int mZenMode;
private int mUser = UserHandle.USER_SYSTEM;
- protected ZenModeConfig mConfig;
+ @VisibleForTesting protected ZenModeConfig mConfig;
private AudioManagerInternal mAudioManager;
protected PackageManager mPm;
private long mSuppressedEffects;
@@ -595,8 +596,9 @@
pw.println(config);
return;
}
- pw.printf("allow(calls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s,"
+ pw.printf("allow(alarms=%b,media=%bcalls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s,"
+ "events=%b,reminders=%b,whenScreenOff=%b,whenScreenOn=%b)\n",
+ config.allowAlarms, config.allowMediaSystemOther,
config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
config.allowRepeatCallers, config.allowMessages,
ZenModeConfig.sourceToString(config.allowMessagesFrom),
@@ -813,7 +815,8 @@
}
}
- private void applyRestrictions() {
+ @VisibleForTesting
+ protected void applyRestrictions() {
final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
// notification restrictions
@@ -822,6 +825,10 @@
// call restrictions
final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
|| (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
+ // alarm restrictions
+ final boolean muteAlarms = zen && !mConfig.allowAlarms;
+ // alarm restrictions
+ final boolean muteMediaAndSystemSounds = zen && !mConfig.allowMediaSystemOther;
// total silence restrictions
final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
@@ -833,13 +840,18 @@
applyRestrictions(muteNotifications || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
applyRestrictions(muteCalls || muteEverything, usage);
+ } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
+ applyRestrictions(muteAlarms || muteEverything, usage);
+ } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA_SYSTEM_OTHER) {
+ applyRestrictions(muteMediaAndSystemSounds || muteEverything, usage);
} else {
applyRestrictions(muteEverything, usage);
}
}
}
- private void applyRestrictions(boolean mute, int usage) {
+ @VisibleForTesting
+ protected void applyRestrictions(boolean mute, int usage) {
final String[] exceptionPackages = null; // none (for now)
mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage,
mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d7329db..d2f2426 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -21893,7 +21893,7 @@
}
private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.println();
ipw.println("Dexopt state:");
ipw.increaseIndent();
@@ -21920,7 +21920,7 @@
}
private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) {
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.println();
ipw.println("Compiler stats:");
ipw.increaseIndent();
diff --git a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
index 4f5d156..815f885 100644
--- a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
+++ b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
@@ -21,6 +21,8 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.drawable.Icon;
+import android.os.StrictMode;
+import android.os.StrictMode.ThreadPolicy;
import android.os.SystemClock;
import android.util.Log;
import android.util.Slog;
@@ -165,7 +167,13 @@
// Compress it and enqueue to the requests.
final byte[] bytes;
+ final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
try {
+ // compress() triggers a slow call, but in this case it's needed to save RAM and also
+ // the target bitmap is of an icon size, so let's just permit it.
+ StrictMode.setThreadPolicy(new ThreadPolicy.Builder(oldPolicy)
+ .permitCustomSlowCalls()
+ .build());
final Bitmap shrunk = mService.shrinkBitmap(original, maxDimension);
try {
try (final ByteArrayOutputStream out = new ByteArrayOutputStream(64 * 1024)) {
@@ -184,6 +192,8 @@
} catch (IOException | RuntimeException | OutOfMemoryError e) {
Slog.wtf(ShortcutService.TAG, "Unable to write bitmap to file", e);
return;
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
}
shortcut.addFlags(
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
index f922ad1..cedf476 100644
--- a/services/core/java/com/android/server/pm/ShortcutLauncher.java
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -83,11 +83,16 @@
return mOwnerUserId;
}
+ @Override
+ protected boolean canRestoreAnyVersion() {
+ // Launcher's pinned shortcuts can be restored to an older version.
+ return true;
+ }
+
/**
* Called when the new package can't receive the backup, due to signature or version mismatch.
*/
- @Override
- protected void onRestoreBlocked() {
+ private void onRestoreBlocked() {
final ArrayList<PackageWithUser> pinnedPackages =
new ArrayList<>(mPinnedShortcuts.keySet());
mPinnedShortcuts.clear();
@@ -101,15 +106,21 @@
}
@Override
- protected void onRestored() {
- // Nothing to do.
+ protected void onRestored(int restoreBlockReason) {
+ // For launcher, possible reasons here are DISABLED_REASON_SIGNATURE_MISMATCH or
+ // DISABLED_REASON_BACKUP_NOT_SUPPORTED.
+ // DISABLED_REASON_VERSION_LOWER will NOT happen because we don't check version
+ // code for launchers.
+ if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
+ onRestoreBlocked();
+ }
}
/**
* Pin the given shortcuts, replacing the current pinned ones.
*/
public void pinShortcuts(@UserIdInt int packageUserId,
- @NonNull String packageName, @NonNull List<String> ids) {
+ @NonNull String packageName, @NonNull List<String> ids, boolean forPinRequest) {
final ShortcutPackage packageShortcuts =
mShortcutUser.getPackageShortcutsIfExists(packageName);
if (packageShortcuts == null) {
@@ -124,8 +135,12 @@
} else {
final ArraySet<String> prevSet = mPinnedShortcuts.get(pu);
- // Pin shortcuts. Make sure only pin the ones that were visible to the caller.
- // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
+ // Actually pin shortcuts.
+ // This logic here is to make sure a launcher cannot pin a shortcut that is floating
+ // (i.e. not dynamic nor manifest but is pinned) and pinned by another launcher.
+ // In this case, technically the shortcut doesn't exist to this launcher, so it can't
+ // pin it.
+ // (Maybe unnecessarily strict...)
final ArraySet<String> newSet = new ArraySet<>();
@@ -135,8 +150,10 @@
if (si == null) {
continue;
}
- if (si.isDynamic() || si.isManifestShortcut()
- || (prevSet != null && prevSet.contains(id))) {
+ if (si.isDynamic()
+ || si.isManifestShortcut()
+ || (prevSet != null && prevSet.contains(id))
+ || forPinRequest) {
newSet.add(id);
}
}
@@ -155,7 +172,7 @@
}
/**
- * Return true if the given shortcut is pinned by this launcher.
+ * Return true if the given shortcut is pinned by this launcher.<code></code>
*/
public boolean hasPinned(ShortcutInfo shortcut) {
final ArraySet<String> pinned =
@@ -164,10 +181,10 @@
}
/**
- * Additionally pin a shortcut. c.f. {@link #pinShortcuts(int, String, List)}
+ * Additionally pin a shortcut. c.f. {@link #pinShortcuts(int, String, List, boolean)}
*/
public void addPinnedShortcut(@NonNull String packageName, @UserIdInt int packageUserId,
- String id) {
+ String id, boolean forPinRequest) {
final ArraySet<String> pinnedSet = getPinnedShortcutIds(packageName, packageUserId);
final ArrayList<String> pinnedList;
if (pinnedSet != null) {
@@ -178,21 +195,21 @@
}
pinnedList.add(id);
- pinShortcuts(packageUserId, packageName, pinnedList);
+ pinShortcuts(packageUserId, packageName, pinnedList, forPinRequest);
}
boolean cleanUpPackage(String packageName, @UserIdInt int packageUserId) {
return mPinnedShortcuts.remove(PackageWithUser.of(packageUserId, packageName)) != null;
}
- public void ensureVersionInfo() {
+ public void ensurePackageInfo() {
final PackageInfo pi = mShortcutUser.mService.getPackageInfoWithSignatures(
getPackageName(), getPackageUserId());
if (pi == null) {
Slog.w(TAG, "Package not found: " + getPackageName());
return;
}
- getPackageInfo().updateVersionInfo(pi);
+ getPackageInfo().updateFromPackageInfo(pi);
}
/**
@@ -201,6 +218,10 @@
@Override
public void saveToXml(XmlSerializer out, boolean forBackup)
throws IOException {
+ if (forBackup && !getPackageInfo().isBackupAllowed()) {
+ // If an launcher app doesn't support backup&restore, then nothing to do.
+ return;
+ }
final int size = mPinnedShortcuts.size();
if (size == 0) {
return; // Nothing to write.
@@ -209,7 +230,7 @@
out.startTag(null, TAG_ROOT);
ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, getPackageName());
ShortcutService.writeAttr(out, ATTR_LAUNCHER_USER_ID, getPackageUserId());
- getPackageInfo().saveToXml(out);
+ getPackageInfo().saveToXml(out, forBackup);
for (int i = 0; i < size; i++) {
final PackageWithUser pu = mPinnedShortcuts.keyAt(i);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 6fc1e73..a4bec1d 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -84,6 +84,7 @@
private static final String ATTR_DISABLED_MESSAGE = "dmessage";
private static final String ATTR_DISABLED_MESSAGE_RES_ID = "dmessageid";
private static final String ATTR_DISABLED_MESSAGE_RES_NAME = "dmessagename";
+ private static final String ATTR_DISABLED_REASON = "disabled-reason";
private static final String ATTR_INTENT_LEGACY = "intent";
private static final String ATTR_INTENT_NO_EXTRA = "intent-base";
private static final String ATTR_RANK = "rank";
@@ -156,13 +157,25 @@
}
@Override
- protected void onRestoreBlocked() {
- // Can't restore due to version/signature mismatch. Remove all shortcuts.
- mShortcuts.clear();
+ protected boolean canRestoreAnyVersion() {
+ return false;
}
@Override
- protected void onRestored() {
+ protected void onRestored(int restoreBlockReason) {
+ // Shortcuts have been restored.
+ // - Unshadow all shortcuts.
+ // - Set disabled reason.
+ // - Disable if needed.
+ for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+ ShortcutInfo si = mShortcuts.valueAt(i);
+ si.clearFlags(ShortcutInfo.FLAG_SHADOW);
+
+ si.setDisabledReason(restoreBlockReason);
+ if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
+ si.addFlags(ShortcutInfo.FLAG_DISABLED);
+ }
+ }
// Because some launchers may not have been restored (e.g. allowBackup=false),
// we need to re-calculate the pinned shortcuts.
refreshPinnedFlags();
@@ -176,31 +189,47 @@
return mShortcuts.get(id);
}
- private void ensureNotImmutable(@Nullable ShortcutInfo shortcut) {
- if (shortcut != null && shortcut.isImmutable()) {
+ public boolean isShortcutExistsAndInvisibleToPublisher(String id) {
+ ShortcutInfo si = findShortcutById(id);
+ return si != null && !si.isVisibleToPublisher();
+ }
+
+ public boolean isShortcutExistsAndVisibleToPublisher(String id) {
+ ShortcutInfo si = findShortcutById(id);
+ return si != null && si.isVisibleToPublisher();
+ }
+
+ private void ensureNotImmutable(@Nullable ShortcutInfo shortcut, boolean ignoreInvisible) {
+ if (shortcut != null && shortcut.isImmutable()
+ && (!ignoreInvisible || shortcut.isVisibleToPublisher())) {
throw new IllegalArgumentException(
"Manifest shortcut ID=" + shortcut.getId()
+ " may not be manipulated via APIs");
}
}
- public void ensureNotImmutable(@NonNull String id) {
- ensureNotImmutable(mShortcuts.get(id));
+ public void ensureNotImmutable(@NonNull String id, boolean ignoreInvisible) {
+ ensureNotImmutable(mShortcuts.get(id), ignoreInvisible);
}
- public void ensureImmutableShortcutsNotIncludedWithIds(@NonNull List<String> shortcutIds) {
+ public void ensureImmutableShortcutsNotIncludedWithIds(@NonNull List<String> shortcutIds,
+ boolean ignoreInvisible) {
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
- ensureNotImmutable(shortcutIds.get(i));
+ ensureNotImmutable(shortcutIds.get(i), ignoreInvisible);
}
}
- public void ensureImmutableShortcutsNotIncluded(@NonNull List<ShortcutInfo> shortcuts) {
+ public void ensureImmutableShortcutsNotIncluded(@NonNull List<ShortcutInfo> shortcuts,
+ boolean ignoreInvisible) {
for (int i = shortcuts.size() - 1; i >= 0; i--) {
- ensureNotImmutable(shortcuts.get(i).getId());
+ ensureNotImmutable(shortcuts.get(i).getId(), ignoreInvisible);
}
}
- private ShortcutInfo deleteShortcutInner(@NonNull String id) {
+ /**
+ * Delete a shortcut by ID. This will *always* remove it even if it's immutable or invisible.
+ */
+ private ShortcutInfo forceDeleteShortcutInner(@NonNull String id) {
final ShortcutInfo shortcut = mShortcuts.remove(id);
if (shortcut != null) {
mShortcutUser.mService.removeIconLocked(shortcut);
@@ -210,10 +239,14 @@
return shortcut;
}
- private void addShortcutInner(@NonNull ShortcutInfo newShortcut) {
+ /**
+ * Force replace a shortcut. If there's already a shortcut with the same ID, it'll be removed,
+ * even if it's invisible.
+ */
+ private void forceReplaceShortcutInner(@NonNull ShortcutInfo newShortcut) {
final ShortcutService s = mShortcutUser.mService;
- deleteShortcutInner(newShortcut.getId());
+ forceDeleteShortcutInner(newShortcut.getId());
// Extract Icon and update the icon res ID and the bitmap path.
s.saveIconAndFixUpShortcutLocked(newShortcut);
@@ -222,11 +255,12 @@
}
/**
- * Add a shortcut, or update one with the same ID, with taking over existing flags.
+ * Add a shortcut. If there's already a one with the same ID, it'll be removed, even if it's
+ * invisible.
*
* It checks the max number of dynamic shortcuts.
*/
- public void addOrUpdateDynamicShortcut(@NonNull ShortcutInfo newShortcut) {
+ public void addOrReplaceDynamicShortcut(@NonNull ShortcutInfo newShortcut) {
Preconditions.checkArgument(newShortcut.isEnabled(),
"add/setDynamicShortcuts() cannot publish disabled shortcuts");
@@ -242,7 +276,7 @@
} else {
// It's an update case.
// Make sure the target is updatable. (i.e. should be mutable.)
- oldShortcut.ensureUpdatableWith(newShortcut);
+ oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
wasPinned = oldShortcut.isPinned();
}
@@ -252,7 +286,7 @@
newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
}
- addShortcutInner(newShortcut);
+ forceReplaceShortcutInner(newShortcut);
}
/**
@@ -273,7 +307,7 @@
}
if (removeList != null) {
for (int i = removeList.size() - 1; i >= 0; i--) {
- deleteShortcutInner(removeList.get(i));
+ forceDeleteShortcutInner(removeList.get(i));
}
}
}
@@ -281,13 +315,13 @@
/**
* Remove all dynamic shortcuts.
*/
- public void deleteAllDynamicShortcuts() {
+ public void deleteAllDynamicShortcuts(boolean ignoreInvisible) {
final long now = mShortcutUser.mService.injectCurrentTimeMillis();
boolean changed = false;
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (si.isDynamic()) {
+ if (si.isDynamic() && (!ignoreInvisible || si.isVisibleToPublisher())) {
changed = true;
si.setTimestamp(now);
@@ -307,9 +341,10 @@
* @return true if it's actually removed because it wasn't pinned, or false if it's still
* pinned.
*/
- public boolean deleteDynamicWithId(@NonNull String shortcutId) {
+ public boolean deleteDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
final ShortcutInfo removed = deleteOrDisableWithId(
- shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false);
+ shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible,
+ ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
return removed == null;
}
@@ -320,9 +355,11 @@
* @return true if it's actually removed because it wasn't pinned, or false if it's still
* pinned.
*/
- private boolean disableDynamicWithId(@NonNull String shortcutId) {
+ private boolean disableDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible,
+ int disabledReason) {
final ShortcutInfo disabled = deleteOrDisableWithId(
- shortcutId, /* disable =*/ true, /* overrideImmutable=*/ false);
+ shortcutId, /* disable =*/ true, /* overrideImmutable=*/ false, ignoreInvisible,
+ disabledReason);
return disabled == null;
}
@@ -331,9 +368,10 @@
* is pinned, it'll remain as a pinned shortcut but will be disabled.
*/
public void disableWithId(@NonNull String shortcutId, String disabledMessage,
- int disabledMessageResId, boolean overrideImmutable) {
+ int disabledMessageResId, boolean overrideImmutable, boolean ignoreInvisible,
+ int disabledReason) {
final ShortcutInfo disabled = deleteOrDisableWithId(shortcutId, /* disable =*/ true,
- overrideImmutable);
+ overrideImmutable, ignoreInvisible, disabledReason);
if (disabled != null) {
if (disabledMessage != null) {
@@ -348,14 +386,18 @@
@Nullable
private ShortcutInfo deleteOrDisableWithId(@NonNull String shortcutId, boolean disable,
- boolean overrideImmutable) {
+ boolean overrideImmutable, boolean ignoreInvisible, int disabledReason) {
+ Preconditions.checkState(
+ (disable == (disabledReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED)),
+ "disable and disabledReason disagree: " + disable + " vs " + disabledReason);
final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
- if (oldShortcut == null || !oldShortcut.isEnabled()) {
+ if (oldShortcut == null || !oldShortcut.isEnabled()
+ && (ignoreInvisible && !oldShortcut.isVisibleToPublisher())) {
return null; // Doesn't exist or already disabled.
}
if (!overrideImmutable) {
- ensureNotImmutable(oldShortcut);
+ ensureNotImmutable(oldShortcut, /*ignoreInvisible=*/ true);
}
if (oldShortcut.isPinned()) {
@@ -363,6 +405,10 @@
oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
+ // Do not overwrite the disabled reason if one is alreay set.
+ if (oldShortcut.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
+ oldShortcut.setDisabledReason(disabledReason);
+ }
}
oldShortcut.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis());
@@ -373,7 +419,7 @@
return oldShortcut;
} else {
- deleteShortcutInner(shortcutId);
+ forceDeleteShortcutInner(shortcutId);
return null;
}
}
@@ -381,11 +427,25 @@
public void enableWithId(@NonNull String shortcutId) {
final ShortcutInfo shortcut = mShortcuts.get(shortcutId);
if (shortcut != null) {
- ensureNotImmutable(shortcut);
+ ensureNotImmutable(shortcut, /*ignoreInvisible=*/ true);
shortcut.clearFlags(ShortcutInfo.FLAG_DISABLED);
+ shortcut.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
}
}
+ public void updateInvisibleShortcutForPinRequestWith(@NonNull ShortcutInfo shortcut) {
+ final ShortcutInfo source = mShortcuts.get(shortcut.getId());
+ Preconditions.checkNotNull(source);
+
+ mShortcutUser.mService.validateShortcutForPinRequest(shortcut);
+
+ shortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+
+ forceReplaceShortcutInner(shortcut);
+
+ adjustRanks();
+ }
+
/**
* Called after a launcher updates the pinned set. For each shortcut in this package,
* set FLAG_PINNED if any launcher has pinned it. Otherwise, clear it.
@@ -693,7 +753,27 @@
getPackageInfo().getVersionCode(), pi.versionCode));
}
- getPackageInfo().updateVersionInfo(pi);
+ getPackageInfo().updateFromPackageInfo(pi);
+ final int newVersionCode = getPackageInfo().getVersionCode();
+
+ // See if there are any shortcuts that were prevented restoring because the app was of a
+ // lower version, and re-enable them.
+ for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+ final ShortcutInfo si = mShortcuts.valueAt(i);
+ if (si.getDisabledReason() != ShortcutInfo.DISABLED_REASON_VERSION_LOWER) {
+ continue;
+ }
+ if (getPackageInfo().getBackupSourceVersionCode() > newVersionCode) {
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, String.format("Shortcut %s require version %s, still not restored.",
+ si.getId(), getPackageInfo().getBackupSourceVersionCode()));
+ }
+ continue;
+ }
+ Slog.i(TAG, String.format("Restoring shortcut: %s", si.getId()));
+ si.clearFlags(ShortcutInfo.FLAG_DISABLED);
+ si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
+ }
// For existing shortcuts, update timestamps if they have any resources.
// Also check if shortcuts' activities are still main activities. Otherwise, disable them.
@@ -713,7 +793,8 @@
Slog.w(TAG, String.format(
"%s is no longer main activity. Disabling shorcut %s.",
getPackageName(), si.getId()));
- if (disableDynamicWithId(si.getId())) {
+ if (disableDynamicWithId(si.getId(), /*ignoreInvisible*/ false,
+ ShortcutInfo.DISABLED_REASON_APP_CHANGED)) {
continue; // Actually removed.
}
// Still pinned, so fall-through and possibly update the resources.
@@ -809,7 +890,7 @@
// Note even if enabled=false, we still need to update all fields, so do it
// regardless.
- addShortcutInner(newShortcut); // This will clean up the old one too.
+ forceReplaceShortcutInner(newShortcut); // This will clean up the old one too.
if (!newDisabled && toDisableList != null) {
// Still alive, don't remove.
@@ -831,7 +912,8 @@
final String id = toDisableList.valueAt(i);
disableWithId(id, /* disable message =*/ null, /* disable message resid */ 0,
- /* overrideImmutable=*/ true);
+ /* overrideImmutable=*/ true, /*ignoreInvisible=*/ false,
+ ShortcutInfo.DISABLED_REASON_APP_CHANGED);
}
removeOrphans();
}
@@ -869,7 +951,7 @@
service.wtf("Found manifest shortcuts in excess list.");
continue;
}
- deleteDynamicWithId(shortcut.getId());
+ deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true);
}
}
@@ -1075,7 +1157,7 @@
if (ret != 0) {
return ret;
}
- // If they're stil tie, just sort by their IDs.
+ // If they're still tie, just sort by their IDs.
// This may happen with updateShortcuts() -- see
// the testUpdateShortcuts_noManifestShortcuts() test.
return a.getId().compareTo(b.getId());
@@ -1257,25 +1339,34 @@
ShortcutService.writeAttr(out, ATTR_NAME, getPackageName());
ShortcutService.writeAttr(out, ATTR_CALL_COUNT, mApiCallCount);
ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
- getPackageInfo().saveToXml(out);
+ getPackageInfo().saveToXml(out, forBackup);
for (int j = 0; j < size; j++) {
- saveShortcut(out, mShortcuts.valueAt(j), forBackup);
+ saveShortcut(out, mShortcuts.valueAt(j), forBackup,
+ getPackageInfo().isBackupAllowed());
}
out.endTag(null, TAG_ROOT);
}
- private void saveShortcut(XmlSerializer out, ShortcutInfo si, boolean forBackup)
+ private void saveShortcut(XmlSerializer out, ShortcutInfo si, boolean forBackup,
+ boolean appSupportsBackup)
throws IOException, XmlPullParserException {
final ShortcutService s = mShortcutUser.mService;
if (forBackup) {
if (!(si.isPinned() && si.isEnabled())) {
- return; // We only backup pinned shortcuts that are enabled.
+ // We only backup pinned shortcuts that are enabled.
+ // Note, this means, shortcuts that are restored but are blocked restore, e.g. due
+ // to a lower version code, will not be ported to a new device.
+ return;
}
}
+ final boolean shouldBackupDetails =
+ !forBackup // It's not backup
+ || appSupportsBackup; // Or, it's a backup and app supports backup.
+
// Note: at this point no shortcuts should have bitmaps pending save, but if they do,
// just remove the bitmap.
if (si.isIconPendingSave()) {
@@ -1292,20 +1383,31 @@
ShortcutService.writeAttr(out, ATTR_TEXT, si.getText());
ShortcutService.writeAttr(out, ATTR_TEXT_RES_ID, si.getTextResId());
ShortcutService.writeAttr(out, ATTR_TEXT_RES_NAME, si.getTextResName());
- ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE, si.getDisabledMessage());
- ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_ID,
- si.getDisabledMessageResourceId());
- ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_NAME,
- si.getDisabledMessageResName());
+ if (shouldBackupDetails) {
+ ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE, si.getDisabledMessage());
+ ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_ID,
+ si.getDisabledMessageResourceId());
+ ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_NAME,
+ si.getDisabledMessageResName());
+ }
+ ShortcutService.writeAttr(out, ATTR_DISABLED_REASON, si.getDisabledReason());
ShortcutService.writeAttr(out, ATTR_TIMESTAMP,
si.getLastChangedTimestamp());
if (forBackup) {
// Don't write icon information. Also drop the dynamic flag.
- ShortcutService.writeAttr(out, ATTR_FLAGS,
- si.getFlags() &
- ~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
+
+ int flags = si.getFlags() &
+ ~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
| ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE
- | ShortcutInfo.FLAG_DYNAMIC));
+ | ShortcutInfo.FLAG_DYNAMIC);
+ ShortcutService.writeAttr(out, ATTR_FLAGS, flags);
+
+ // Set the publisher version code at every backup.
+ final int packageVersionCode = getPackageInfo().getVersionCode();
+ if (packageVersionCode == 0) {
+ s.wtf("Package version code should be available at this point.");
+ // However, 0 is a valid version code, so we just go ahead with it...
+ }
} else {
// When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
// as dynamic.
@@ -1317,26 +1419,28 @@
ShortcutService.writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());
}
- {
- final Set<String> cat = si.getCategories();
- if (cat != null && cat.size() > 0) {
- out.startTag(null, TAG_CATEGORIES);
- XmlUtils.writeStringArrayXml(cat.toArray(new String[cat.size()]),
- NAME_CATEGORIES, out);
- out.endTag(null, TAG_CATEGORIES);
+ if (shouldBackupDetails) {
+ {
+ final Set<String> cat = si.getCategories();
+ if (cat != null && cat.size() > 0) {
+ out.startTag(null, TAG_CATEGORIES);
+ XmlUtils.writeStringArrayXml(cat.toArray(new String[cat.size()]),
+ NAME_CATEGORIES, out);
+ out.endTag(null, TAG_CATEGORIES);
+ }
}
- }
- final Intent[] intentsNoExtras = si.getIntentsNoExtras();
- final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
- final int numIntents = intentsNoExtras.length;
- for (int i = 0; i < numIntents; i++) {
- out.startTag(null, TAG_INTENT);
- ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
- out.endTag(null, TAG_INTENT);
- }
+ final Intent[] intentsNoExtras = si.getIntentsNoExtras();
+ final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
+ final int numIntents = intentsNoExtras.length;
+ for (int i = 0; i < numIntents; i++) {
+ out.startTag(null, TAG_INTENT);
+ ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+ out.endTag(null, TAG_INTENT);
+ }
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+ }
out.endTag(null, TAG_SHORTCUT);
}
@@ -1356,6 +1460,7 @@
ret.mLastResetTime =
ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
+
final int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1369,10 +1474,11 @@
switch (tag) {
case ShortcutPackageInfo.TAG_ROOT:
ret.getPackageInfo().loadFromXml(parser, fromBackup);
+
continue;
case TAG_SHORTCUT:
final ShortcutInfo si = parseShortcut(parser, packageName,
- shortcutUser.getUserId());
+ shortcutUser.getUserId(), fromBackup);
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
@@ -1385,7 +1491,8 @@
}
private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName,
- @UserIdInt int userId) throws IOException, XmlPullParserException {
+ @UserIdInt int userId, boolean fromBackup)
+ throws IOException, XmlPullParserException {
String id;
ComponentName activityComponent;
// Icon icon;
@@ -1398,6 +1505,7 @@
String disabledMessage;
int disabledMessageResId;
String disabledMessageResName;
+ int disabledReason;
Intent intentLegacy;
PersistableBundle intentPersistableExtrasLegacy = null;
ArrayList<Intent> intents = new ArrayList<>();
@@ -1408,6 +1516,7 @@
int iconResId;
String iconResName;
String bitmapPath;
+ int backupVersionCode;
ArraySet<String> categories = null;
id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
@@ -1424,6 +1533,7 @@
ATTR_DISABLED_MESSAGE_RES_ID);
disabledMessageResName = ShortcutService.parseStringAttribute(parser,
ATTR_DISABLED_MESSAGE_RES_NAME);
+ disabledReason = ShortcutService.parseIntAttribute(parser, ATTR_DISABLED_REASON);
intentLegacy = ShortcutService.parseIntentAttributeNoDefault(parser, ATTR_INTENT_LEGACY);
rank = (int) ShortcutService.parseLongAttribute(parser, ATTR_RANK);
lastChangedTimestamp = ShortcutService.parseLongAttribute(parser, ATTR_TIMESTAMP);
@@ -1480,6 +1590,19 @@
intents.add(intentLegacy);
}
+
+ if ((disabledReason == ShortcutInfo.DISABLED_REASON_NOT_DISABLED)
+ && ((flags & ShortcutInfo.FLAG_DISABLED) != 0)) {
+ // We didn't used to have the disabled reason, so if a shortcut is disabled
+ // and has no reason, we assume it was disabled by publisher.
+ disabledReason = ShortcutInfo.DISABLED_REASON_BY_APP;
+ }
+
+ // All restored shortcuts are initially "shadow".
+ if (fromBackup) {
+ flags |= ShortcutInfo.FLAG_SHADOW;
+ }
+
return new ShortcutInfo(
userId, id, packageName, activityComponent, /* icon =*/ null,
title, titleResId, titleResName, text, textResId, textResName,
@@ -1487,7 +1610,7 @@
categories,
intents.toArray(new Intent[intents.size()]),
rank, extras, lastChangedTimestamp, flags,
- iconResId, iconResName, bitmapPath);
+ iconResId, iconResName, bitmapPath, disabledReason);
}
private static Intent parseIntent(XmlPullParser parser)
@@ -1602,6 +1725,20 @@
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " has both resource and bitmap icons");
}
+ if (si.isEnabled()
+ != (si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED)) {
+ failed = true;
+ Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ + " isEnabled() and getDisabledReason() disagree: "
+ + si.isEnabled() + " vs " + si.getDisabledReason());
+ }
+ if ((si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_VERSION_LOWER)
+ && (getPackageInfo().getBackupSourceVersionCode()
+ == ShortcutInfo.VERSION_CODE_UNKNOWN)) {
+ failed = true;
+ Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ + " RESTORED_VERSION_LOWER with no backup source version code.");
+ }
if (s.isDummyMainActivity(si.getActivity())) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
index e5a2f5a..3a9bbc8 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.pm.PackageInfo;
+import android.content.pm.ShortcutInfo;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -45,32 +46,45 @@
static final String TAG_ROOT = "package-info";
private static final String ATTR_VERSION = "version";
private static final String ATTR_LAST_UPDATE_TIME = "last_udpate_time";
+ private static final String ATTR_BACKUP_SOURCE_VERSION = "bk_src_version";
+ private static final String ATTR_BACKUP_ALLOWED = "allow-backup";
+ private static final String ATTR_BACKUP_SOURCE_BACKUP_ALLOWED = "bk_src_backup-allowed";
private static final String ATTR_SHADOW = "shadow";
private static final String TAG_SIGNATURE = "signature";
private static final String ATTR_SIGNATURE_HASH = "hash";
- private static final int VERSION_UNKNOWN = -1;
-
/**
* When true, this package information was restored from the previous device, and the app hasn't
* been installed yet.
*/
private boolean mIsShadow;
- private int mVersionCode = VERSION_UNKNOWN;
+ private int mVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
+ private int mBackupSourceVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
private long mLastUpdateTime;
private ArrayList<byte[]> mSigHashes;
+ // mBackupAllowed didn't used to be parsisted, so we don't restore it from a file.
+ // mBackupAllowed will always start with false, and will have been updated before making a
+ // backup next time, which works file.
+ // We just don't want to print an uninitialzied mBackupAlldowed value on dumpsys, so
+ // we use this boolean to control dumpsys.
+ private boolean mBackupAllowedInitialized;
+ private boolean mBackupAllowed;
+ private boolean mBackupSourceBackupAllowed;
+
private ShortcutPackageInfo(int versionCode, long lastUpdateTime,
ArrayList<byte[]> sigHashes, boolean isShadow) {
mVersionCode = versionCode;
mLastUpdateTime = lastUpdateTime;
mIsShadow = isShadow;
mSigHashes = sigHashes;
+ mBackupAllowed = false; // By default, we assume false.
+ mBackupSourceBackupAllowed = false;
}
public static ShortcutPackageInfo newEmpty() {
- return new ShortcutPackageInfo(VERSION_UNKNOWN, /* last update time =*/ 0,
+ return new ShortcutPackageInfo(ShortcutInfo.VERSION_CODE_UNKNOWN, /* last update time =*/ 0,
new ArrayList<>(0), /* isShadow */ false);
}
@@ -86,15 +100,33 @@
return mVersionCode;
}
+ public int getBackupSourceVersionCode() {
+ return mBackupSourceVersionCode;
+ }
+
+ @VisibleForTesting
+ public boolean isBackupSourceBackupAllowed() {
+ return mBackupSourceBackupAllowed;
+ }
+
public long getLastUpdateTime() {
return mLastUpdateTime;
}
- /** Set {@link #mVersionCode} and {@link #mLastUpdateTime} from a {@link PackageInfo}. */
- public void updateVersionInfo(@NonNull PackageInfo pi) {
+ public boolean isBackupAllowed() {
+ return mBackupAllowed;
+ }
+
+ /**
+ * Set {@link #mVersionCode}, {@link #mLastUpdateTime} and {@link #mBackupAllowed}
+ * from a {@link PackageInfo}.
+ */
+ public void updateFromPackageInfo(@NonNull PackageInfo pi) {
if (pi != null) {
mVersionCode = pi.versionCode;
mLastUpdateTime = pi.lastUpdateTime;
+ mBackupAllowed = ShortcutService.shouldBackupApp(pi);
+ mBackupAllowedInitialized = true;
}
}
@@ -102,23 +134,24 @@
return mSigHashes.size() > 0;
}
- public boolean canRestoreTo(ShortcutService s, PackageInfo target) {
- if (!s.shouldBackupApp(target)) {
- // "allowBackup" was true when backed up, but now false.
- Slog.w(TAG, "Can't restore: package no longer allows backup");
- return false;
+ //@DisabledReason
+ public int canRestoreTo(ShortcutService s, PackageInfo currentPackage, boolean anyVersionOkay) {
+ if (!BackupUtils.signaturesMatch(mSigHashes, currentPackage)) {
+ Slog.w(TAG, "Can't restore: Package signature mismatch");
+ return ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH;
}
- if (target.versionCode < mVersionCode) {
+ if (!ShortcutService.shouldBackupApp(currentPackage) || !mBackupSourceBackupAllowed) {
+ // "allowBackup" was true when backed up, but now false.
+ Slog.w(TAG, "Can't restore: package didn't or doesn't allow backup");
+ return ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED;
+ }
+ if (!anyVersionOkay && (currentPackage.versionCode < mBackupSourceVersionCode)) {
Slog.w(TAG, String.format(
"Can't restore: package current version %d < backed up version %d",
- target.versionCode, mVersionCode));
- return false;
+ currentPackage.versionCode, mBackupSourceVersionCode));
+ return ShortcutInfo.DISABLED_REASON_VERSION_LOWER;
}
- if (!BackupUtils.signaturesMatch(mSigHashes, target)) {
- Slog.w(TAG, "Can't restore: Package signature mismatch");
- return false;
- }
- return true;
+ return ShortcutInfo.DISABLED_REASON_NOT_DISABLED;
}
@VisibleForTesting
@@ -132,6 +165,8 @@
final ShortcutPackageInfo ret = new ShortcutPackageInfo(pi.versionCode, pi.lastUpdateTime,
BackupUtils.hashSignatureArray(pi.signatures), /* shadow=*/ false);
+ ret.mBackupSourceBackupAllowed = s.shouldBackupApp(pi);
+ ret.mBackupSourceVersionCode = pi.versionCode;
return ret;
}
@@ -151,13 +186,19 @@
mSigHashes = BackupUtils.hashSignatureArray(pi.signatures);
}
- public void saveToXml(XmlSerializer out) throws IOException {
+ public void saveToXml(XmlSerializer out, boolean forBackup) throws IOException {
out.startTag(null, TAG_ROOT);
ShortcutService.writeAttr(out, ATTR_VERSION, mVersionCode);
ShortcutService.writeAttr(out, ATTR_LAST_UPDATE_TIME, mLastUpdateTime);
ShortcutService.writeAttr(out, ATTR_SHADOW, mIsShadow);
+ ShortcutService.writeAttr(out, ATTR_BACKUP_ALLOWED, mBackupAllowed);
+
+ ShortcutService.writeAttr(out, ATTR_BACKUP_SOURCE_VERSION, mBackupSourceVersionCode);
+ ShortcutService.writeAttr(out,
+ ATTR_BACKUP_SOURCE_BACKUP_ALLOWED, mBackupSourceBackupAllowed);
+
for (int i = 0; i < mSigHashes.size(); i++) {
out.startTag(null, TAG_SIGNATURE);
@@ -171,7 +212,9 @@
public void loadFromXml(XmlPullParser parser, boolean fromBackup)
throws IOException, XmlPullParserException {
- final int versionCode = ShortcutService.parseIntAttribute(parser, ATTR_VERSION);
+ // Don't use the version code from the backup file.
+ final int versionCode = ShortcutService.parseIntAttribute(parser, ATTR_VERSION,
+ ShortcutInfo.VERSION_CODE_UNKNOWN);
final long lastUpdateTime = ShortcutService.parseLongAttribute(
parser, ATTR_LAST_UPDATE_TIME);
@@ -180,6 +223,20 @@
final boolean shadow =
fromBackup || ShortcutService.parseBooleanAttribute(parser, ATTR_SHADOW);
+ // We didn't used to save these attributes, and all backed up shortcuts were from
+ // apps that support backups, so the default values take this fact into consideration.
+ final int backupSourceVersion = ShortcutService.parseIntAttribute(parser,
+ ATTR_BACKUP_SOURCE_VERSION, ShortcutInfo.VERSION_CODE_UNKNOWN);
+
+ // Note the only time these "true" default value is used is when restoring from an old
+ // build that didn't save ATTR_BACKUP_ALLOWED, and that means all the data included in
+ // a backup file were from apps that support backup, so we can just use "true" as the
+ // default.
+ final boolean backupAllowed = ShortcutService.parseBooleanAttribute(
+ parser, ATTR_BACKUP_ALLOWED, true);
+ final boolean backupSourceBackupAllowed = ShortcutService.parseBooleanAttribute(
+ parser, ATTR_BACKUP_SOURCE_BACKUP_ALLOWED, true);
+
final ArrayList<byte[]> hashes = new ArrayList<>();
final int outerDepth = parser.getDepth();
@@ -207,11 +264,28 @@
ShortcutService.warnForInvalidTag(depth, tag);
}
- // Successfully loaded; replace the feilds.
- mVersionCode = versionCode;
+ // Successfully loaded; replace the fields.
+ if (fromBackup) {
+ mVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
+ mBackupSourceVersionCode = versionCode;
+ mBackupSourceBackupAllowed = backupAllowed;
+ } else {
+ mVersionCode = versionCode;
+ mBackupSourceVersionCode = backupSourceVersion;
+ mBackupSourceBackupAllowed = backupSourceBackupAllowed;
+ }
mLastUpdateTime = lastUpdateTime;
mIsShadow = shadow;
mSigHashes = hashes;
+
+ // Note we don't restore it from the file because it didn't used to be saved.
+ // We always start by assuming backup is disabled for the current package,
+ // and this field will have been updated before we actually create a backup, at the same
+ // time when we update the version code.
+ // Until then, the value of mBackupAllowed shouldn't matter, but we don't want to print
+ // a false flag on dumpsys, so set mBackupAllowedInitialized to false.
+ mBackupAllowed = false;
+ mBackupAllowedInitialized = false;
}
public void dump(PrintWriter pw, String prefix) {
@@ -223,6 +297,7 @@
pw.print(prefix);
pw.print(" IsShadow: ");
pw.print(mIsShadow);
+ pw.print(mIsShadow ? " (not installed)" : " (installed)");
pw.println();
pw.print(prefix);
@@ -230,6 +305,25 @@
pw.print(mVersionCode);
pw.println();
+ if (mBackupAllowedInitialized) {
+ pw.print(prefix);
+ pw.print(" Backup Allowed: ");
+ pw.print(mBackupAllowed);
+ pw.println();
+ }
+
+ if (mBackupSourceVersionCode != ShortcutInfo.VERSION_CODE_UNKNOWN) {
+ pw.print(prefix);
+ pw.print(" Backup source version: ");
+ pw.print(mBackupSourceVersionCode);
+ pw.println();
+
+ pw.print(prefix);
+ pw.print(" Backup source backup allowed: ");
+ pw.print(mBackupSourceBackupAllowed);
+ pw.println();
+ }
+
pw.print(prefix);
pw.print(" Last package update time: ");
pw.print(mLastUpdateTime);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index e59d69f..97b7b59 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -17,6 +17,7 @@
import android.annotation.NonNull;
import android.content.pm.PackageInfo;
+import android.content.pm.ShortcutInfo;
import android.util.Slog;
import com.android.internal.util.Preconditions;
@@ -101,51 +102,42 @@
final ShortcutService s = mShortcutUser.mService;
if (!s.isPackageInstalled(mPackageName, mPackageUserId)) {
if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("Package still not installed: %s user=%d",
+ Slog.d(TAG, String.format("Package still not installed: %s/u%d",
mPackageName, mPackageUserId));
}
return; // Not installed, no need to restore yet.
}
- boolean blockRestore = false;
- if (!mPackageInfo.hasSignatures()) {
- s.wtf("Attempted to restore package " + mPackageName + ", user=" + mPackageUserId
- + " but signatures not found in the restore data.");
- blockRestore = true;
- }
- if (!blockRestore) {
- final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
- if (!mPackageInfo.canRestoreTo(s, pi)) {
- // Package is now installed, but can't restore. Let the subclass do the cleanup.
- blockRestore = true;
- }
- }
- if (blockRestore) {
- onRestoreBlocked();
- } else {
- if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("Restored package: %s/%d on user %d", mPackageName,
- mPackageUserId, getOwnerUserId()));
- }
+ int restoreBlockReason;
+ int currentVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
- onRestored();
+ if (!mPackageInfo.hasSignatures()) {
+ s.wtf("Attempted to restore package " + mPackageName + "/u" + mPackageUserId
+ + " but signatures not found in the restore data.");
+ restoreBlockReason = ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH;
+ } else {
+ final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
+ currentVersionCode = pi.versionCode;
+ restoreBlockReason = mPackageInfo.canRestoreTo(s, pi, canRestoreAnyVersion());
}
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, String.format("Restoring package: %s/u%d (version=%d) %s for u%d",
+ mPackageName, mPackageUserId, currentVersionCode,
+ ShortcutInfo.getDisabledReasonLabel(restoreBlockReason),
+ getOwnerUserId()));
+ }
+
+ onRestored(restoreBlockReason);
+
// Either way, it's no longer a shadow.
mPackageInfo.setShadow(false);
s.scheduleSaveUser(mPackageUserId);
}
- /**
- * Called when the new package can't be restored because it has a lower version number
- * or different signatures.
- */
- protected abstract void onRestoreBlocked();
+ protected abstract boolean canRestoreAnyVersion();
- /**
- * Called when the new package is successfully restored.
- */
- protected abstract void onRestored();
+ protected abstract void onRestored(int restoreBlockReason);
public abstract void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
throws IOException, XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java
index 3cf4200..866c46c 100644
--- a/services/core/java/com/android/server/pm/ShortcutParser.java
+++ b/services/core/java/com/android/server/pm/ShortcutParser.java
@@ -337,6 +337,9 @@
(enabled ? ShortcutInfo.FLAG_MANIFEST : ShortcutInfo.FLAG_DISABLED)
| ShortcutInfo.FLAG_IMMUTABLE
| ((iconResId != 0) ? ShortcutInfo.FLAG_HAS_ICON_RES : 0);
+ final int disabledReason =
+ enabled ? ShortcutInfo.DISABLED_REASON_NOT_DISABLED
+ : ShortcutInfo.DISABLED_REASON_BY_APP;
// Note we don't need to set resource names here yet. They'll be set when they're about
// to be published.
@@ -363,6 +366,7 @@
flags,
iconResId,
null, // icon res name
- null); // bitmap path
+ null, // bitmap path
+ disabledReason);
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
index 8a8128d..3e44de9 100644
--- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -300,10 +300,12 @@
final ShortcutInfo existing = ps.findShortcutById(inShortcut.getId());
final boolean existsAlready = existing != null;
+ final boolean existingIsVisible = existsAlready && existing.isVisibleToPublisher();
if (DEBUG) {
Slog.d(TAG, "requestPinnedShortcut: package=" + inShortcut.getPackage()
+ " existsAlready=" + existsAlready
+ + " existingIsVisible=" + existingIsVisible
+ " shortcut=" + inShortcut.toInsecureString());
}
@@ -378,7 +380,6 @@
// manifest shortcut.)
Preconditions.checkArgument(shortcutInfo.isEnabled(),
"Shortcut ID=" + shortcutInfo + " already exists but disabled.");
-
}
private boolean startRequestConfirmActivity(ComponentName activity, int launcherUserId,
@@ -463,7 +464,7 @@
launcher.attemptToRestoreIfNeededAndSave();
if (launcher.hasPinned(original)) {
if (DEBUG) {
- Slog.d(TAG, "Shortcut " + original + " already pinned.");
+ Slog.d(TAG, "Shortcut " + original + " already pinned."); // This too.
}
return true;
}
@@ -497,7 +498,7 @@
if (original.getActivity() == null) {
original.setActivity(mService.getDummyMainActivity(appPackageName));
}
- ps.addOrUpdateDynamicShortcut(original);
+ ps.addOrReplaceDynamicShortcut(original);
}
// Pin the shortcut.
@@ -505,13 +506,14 @@
Slog.d(TAG, "Pinning " + shortcutId);
}
- launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId);
+ launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId,
+ /*forPinRequest=*/ true);
if (current == null) {
if (DEBUG) {
Slog.d(TAG, "Removing " + shortcutId + " as dynamic");
}
- ps.deleteDynamicWithId(shortcutId);
+ ps.deleteDynamicWithId(shortcutId, /*ignoreInvisible=*/ false);
}
ps.adjustRanks(); // Shouldn't be needed, but just in case.
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 27560c5f..9d86796 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -553,6 +553,9 @@
public Lifecycle(Context context) {
super(context);
+ if (DEBUG) {
+ Binder.LOG_RUNTIME_EXCEPTION = true;
+ }
mService = new ShortcutService(context);
}
@@ -738,6 +741,10 @@
return parseLongAttribute(parser, attribute) == 1;
}
+ static boolean parseBooleanAttribute(XmlPullParser parser, String attribute, boolean def) {
+ return parseLongAttribute(parser, attribute, (def ? 1 : 0)) == 1;
+ }
+
static int parseIntAttribute(XmlPullParser parser, String attribute) {
return (int) parseLongAttribute(parser, attribute);
}
@@ -835,6 +842,8 @@
static void writeAttr(XmlSerializer out, String name, boolean value) throws IOException {
if (value) {
writeAttr(out, name, "1");
+ } else {
+ writeAttr(out, name, "0");
}
}
@@ -1689,7 +1698,7 @@
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
+ ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
fillInDefaultActivity(newShortcuts);
@@ -1709,12 +1718,12 @@
}
// First, remove all un-pinned; dynamic shortcuts
- ps.deleteAllDynamicShortcuts();
+ ps.deleteAllDynamicShortcuts(/*ignoreInvisible=*/ true);
// Then, add/update all. We need to make sure to take over "pinned" flag.
for (int i = 0; i < size; i++) {
final ShortcutInfo newShortcut = newShortcuts.get(i);
- ps.addOrUpdateDynamicShortcut(newShortcut);
+ ps.addOrReplaceDynamicShortcut(newShortcut);
}
// Lastly, adjust the ranks.
@@ -1740,7 +1749,7 @@
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
+ ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
// For update, don't fill in the default activity. Having null activity means
// "don't update the activity" here.
@@ -1761,7 +1770,9 @@
fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
final ShortcutInfo target = ps.findShortcutById(source.getId());
- if (target == null) {
+
+ // Invisible shortcuts can't be updated.
+ if (target == null || !target.isVisibleToPublisher()) {
continue;
}
@@ -1808,7 +1819,7 @@
}
@Override
- public boolean addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
+ public boolean addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
@@ -1820,7 +1831,7 @@
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
+ ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
fillInDefaultActivity(newShortcuts);
@@ -1845,7 +1856,7 @@
newShortcut.setRankChanged();
// Add it.
- ps.addOrUpdateDynamicShortcut(newShortcut);
+ ps.addOrReplaceDynamicShortcut(newShortcut);
}
// Lastly, adjust the ranks.
@@ -1901,6 +1912,22 @@
Preconditions.checkState(isUidForegroundLocked(injectBinderCallingUid()),
"Calling application must have a foreground activity or a foreground service");
+ // If it's a pin shortcut request, and there's already a shortcut with the same ID
+ // that's not visible to the caller (i.e. restore-blocked; meaning it's pinned by
+ // someone already), then we just replace the existing one with this new one,
+ // and then proceed the rest of the process.
+ if (shortcut != null) {
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(
+ packageName, userId);
+ final String id = shortcut.getId();
+ if (ps.isShortcutExistsAndInvisibleToPublisher(id)) {
+
+ ps.updateInvisibleShortcutForPinRequestWith(shortcut);
+
+ packageShortcutsChanged(packageName, userId);
+ }
+ }
+
// Send request to the launcher, if supported.
ret = mShortcutRequestPinProcessor.requestPinItemLocked(shortcut, appWidget, extras,
userId, resultIntent);
@@ -1922,15 +1949,21 @@
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
+ ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
+ /*ignoreInvisible=*/ true);
final String disabledMessageString =
(disabledMessage == null) ? null : disabledMessage.toString();
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
- ps.disableWithId(Preconditions.checkStringNotEmpty((String) shortcutIds.get(i)),
+ final String id = Preconditions.checkStringNotEmpty((String) shortcutIds.get(i));
+ if (!ps.isShortcutExistsAndVisibleToPublisher(id)) {
+ continue;
+ }
+ ps.disableWithId(id,
disabledMessageString, disabledMessageResId,
- /* overrideImmutable=*/ false);
+ /* overrideImmutable=*/ false, /*ignoreInvisible=*/ true,
+ ShortcutInfo.DISABLED_REASON_BY_APP);
}
// We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
@@ -1951,10 +1984,15 @@
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
+ ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
+ /*ignoreInvisible=*/ true);
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
- ps.enableWithId((String) shortcutIds.get(i));
+ final String id = Preconditions.checkStringNotEmpty((String) shortcutIds.get(i));
+ if (!ps.isShortcutExistsAndVisibleToPublisher(id)) {
+ continue;
+ }
+ ps.enableWithId(id);
}
}
packageShortcutsChanged(packageName, userId);
@@ -1973,11 +2011,15 @@
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
+ ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
+ /*ignoreInvisible=*/ true);
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
- ps.deleteDynamicWithId(
- Preconditions.checkStringNotEmpty((String) shortcutIds.get(i)));
+ final String id = Preconditions.checkStringNotEmpty((String) shortcutIds.get(i));
+ if (!ps.isShortcutExistsAndVisibleToPublisher(id)) {
+ continue;
+ }
+ ps.deleteDynamicWithId(id, /*ignoreInvisible=*/ true);
}
// We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
@@ -1996,7 +2038,7 @@
throwIfUserLockedL(userId);
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.deleteAllDynamicShortcuts();
+ ps.deleteAllDynamicShortcuts(/*ignoreInvisible=*/ true);
}
packageShortcutsChanged(packageName, userId);
@@ -2013,7 +2055,7 @@
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isDynamic);
+ ShortcutInfo::isDynamicVisible);
}
}
@@ -2027,7 +2069,7 @@
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isManifestShortcut);
+ ShortcutInfo::isManifestVisible);
}
}
@@ -2041,7 +2083,7 @@
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isPinned);
+ ShortcutInfo::isPinnedVisible);
}
}
@@ -2513,7 +2555,7 @@
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId);
launcher.attemptToRestoreIfNeededAndSave();
- launcher.pinShortcuts(userId, packageName, shortcutIds);
+ launcher.pinShortcuts(userId, packageName, shortcutIds, /*forPinRequest=*/ false);
}
packageShortcutsChanged(packageName, userId);
@@ -3343,7 +3385,7 @@
return isApplicationFlagSet(packageName, userId, ApplicationInfo.FLAG_ALLOW_BACKUP);
}
- boolean shouldBackupApp(PackageInfo pi) {
+ static boolean shouldBackupApp(PackageInfo pi) {
return (pi.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0;
}
@@ -3371,7 +3413,7 @@
// Set the version code for the launchers.
// We shouldn't do this for publisher packages, because we don't want to update the
// version code without rescanning the manifest.
- user.forAllLaunchers(launcher -> launcher.ensureVersionInfo());
+ user.forAllLaunchers(launcher -> launcher.ensurePackageInfo());
// Save to the filesystem.
scheduleSaveUser(userId);
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 55e6d28..48eccd0 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -364,9 +364,6 @@
private void saveShortcutPackageItem(XmlSerializer out,
ShortcutPackageItem spi, boolean forBackup) throws IOException, XmlPullParserException {
if (forBackup) {
- if (!mService.shouldBackupApp(spi.getPackageName(), spi.getPackageUserId())) {
- return; // Don't save.
- }
if (spi.getPackageUserId() != spi.getOwnerUserId()) {
return; // Don't save cross-user information.
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index db7817e..ceb0ad0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -18,13 +18,14 @@
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Context.CONTEXT_RESTRICTED;
import static android.content.Context.DISPLAY_SERVICE;
@@ -552,7 +553,6 @@
int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
int mUserRotation = Surface.ROTATION_0;
- boolean mAccelerometerDefault;
boolean mSupportAutoRotation;
int mAllowAllRotations = -1;
@@ -707,7 +707,6 @@
Intent mVrHeadsetHomeIntent;
boolean mSearchKeyShortcutPending;
boolean mConsumeSearchKeyUp;
- boolean mAssistKeyLongPressed;
boolean mPendingMetaAction;
boolean mPendingCapsLockToggle;
int mMetaState;
@@ -838,6 +837,8 @@
private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 24;
private static final int MSG_SYSTEM_KEY_PRESS = 25;
private static final int MSG_HANDLE_ALL_APPS = 26;
+ private static final int MSG_LAUNCH_ASSIST = 27;
+ private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 28;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -879,8 +880,16 @@
case MSG_HIDE_BOOT_MESSAGE:
handleHideBootMessage();
break;
+ case MSG_LAUNCH_ASSIST:
+ final int deviceId = msg.arg1;
+ final String hint = (String) msg.obj;
+ launchAssistAction(hint, deviceId);
+ break;
+ case MSG_LAUNCH_ASSIST_LONG_PRESS:
+ launchAssistLongPressAction();
+ break;
case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
- launchVoiceAssistWithWakeLock(msg.arg1 != 0);
+ launchVoiceAssistWithWakeLock();
break;
case MSG_POWER_DELAYED_PRESS:
powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
@@ -910,7 +919,7 @@
disposeInputConsumer((InputConsumer) msg.obj);
break;
case MSG_BACK_DELAYED_PRESS:
- backMultiPressAction((Long) msg.obj, msg.arg1);
+ backMultiPressAction(msg.arg1);
finishBackKeyPress();
break;
case MSG_ACCESSIBILITY_SHORTCUT:
@@ -1414,7 +1423,7 @@
}
}
- private void backMultiPressAction(long eventTime, int count) {
+ private void backMultiPressAction(int count) {
if (count >= PANIC_PRESS_BACK_COUNT) {
switch (mPanicPressOnBackBehavior) {
case PANIC_PRESS_BACK_NOTHING:
@@ -1583,7 +1592,7 @@
}
}
- private void sleepPress(long eventTime) {
+ private void sleepPress() {
if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
}
@@ -2270,7 +2279,11 @@
// Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
// http://developer.android.com/guide/practices/screens_support.html#range
- mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
+ // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
+ // so if the orientation is forced, we need to respect that no matter what.
+ boolean isCar = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE);
+ mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar) &&
res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
// For debug purposes the next line turns this feature off with:
// $ adb shell setprop config.override_forced_orient true
@@ -2844,7 +2857,7 @@
boolean keyguardLocked = isKeyguardLocked();
boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
- && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
+ && !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
|| hideDockDivider;
}
@@ -3537,44 +3550,11 @@
toggleKeyboardShortcutsMenu(event.getDeviceId());
}
} else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
- if (down) {
- if (repeatCount == 0) {
- mAssistKeyLongPressed = false;
- } else if (repeatCount == 1) {
- mAssistKeyLongPressed = true;
- if (!keyguardOn) {
- launchAssistLongPressAction();
- }
- }
- } else {
- if (mAssistKeyLongPressed) {
- mAssistKeyLongPressed = false;
- } else {
- if (!keyguardOn) {
- launchAssistAction(null, event.getDeviceId());
- }
- }
- }
+ Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");
return -1;
} else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
- if (!down) {
- Intent voiceIntent;
- if (!keyguardOn) {
- voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
- } else {
- IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
- if (dic != null) {
- try {
- dic.exitIdle("voice-search");
- } catch (RemoteException e) {
- }
- }
- voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
- voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
- }
- startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
- }
+ Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in interceptKeyBeforeQueueing");
+ return -1;
} else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
if (down && repeatCount == 0) {
mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
@@ -5445,7 +5425,10 @@
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
&& attrs.type < FIRST_SYSTEM_WINDOW;
- final int stackId = win.getStackId();
+ final int windowingMode = win.getWindowingMode();
+ final boolean inFullScreenOrSplitScreenSecondaryWindowingMode =
+ windowingMode == WINDOWING_MODE_FULLSCREEN
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
mForceStatusBar = true;
@@ -5464,7 +5447,7 @@
// represent should be hidden or if we should hide the lockscreen. For attached app
// windows we defer the decision to the window it is attached to.
if (appWindow && attached == null) {
- if (attrs.isFullscreen() && StackId.normallyFullscreenWindows(stackId)) {
+ if (attrs.isFullscreen() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
@@ -5495,7 +5478,7 @@
// Keep track of the window if it's dimming but not necessarily fullscreen.
if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
- && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
+ && win.isDimming() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
mTopFullscreenOpaqueOrDimmingWindowState = win;
}
@@ -5503,7 +5486,7 @@
// separately, because both the "real fullscreen" opaque window and the one for the docked
// stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
- && attrs.isFullscreen() && stackId == DOCKED_STACK_ID) {
+ && attrs.isFullscreen() && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
mTopDockedOpaqueWindowState = win;
if (mTopDockedOpaqueOrDimmingWindowState == null) {
mTopDockedOpaqueOrDimmingWindowState = win;
@@ -5513,7 +5496,7 @@
// Also keep track of any windows that are dimming but not necessarily fullscreen in the
// docked stack.
if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
- && stackId == DOCKED_STACK_ID) {
+ && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
mTopDockedOpaqueOrDimmingWindowState = win;
}
@@ -5608,8 +5591,9 @@
changes |= FINISH_LAYOUT_REDO_LAYOUT;
}
} else if (topIsFullscreen
- && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
- && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
+ && !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_FREEFORM)
+ && !mWindowManagerInternal.isStackVisible(
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
if (mStatusBarController.setBarShowingLw(false)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT;
@@ -6191,7 +6175,7 @@
useHapticFeedback = false; // suppress feedback if already non-interactive
}
if (down) {
- sleepPress(event.getEventTime());
+ sleepPress();
} else {
sleepRelease(event.getEventTime());
}
@@ -6262,18 +6246,30 @@
}
break;
}
- case KeyEvent.KEYCODE_VOICE_ASSIST: {
- // Only do this if we would otherwise not pass it to the user. In that case,
- // interceptKeyBeforeDispatching would apply a similar but different policy in
- // order to invoke voice assist actions. Note that we need to make a copy of the
- // key event here because the original key event will be recycled when we return.
- if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
- mBroadcastWakeLock.acquire();
- Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
- keyguardActive ? 1 : 0, 0);
+ case KeyEvent.KEYCODE_ASSIST: {
+ final boolean longPressed = event.getRepeatCount() > 0;
+ if (down && longPressed) {
+ Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST_LONG_PRESS);
msg.setAsynchronous(true);
msg.sendToTarget();
}
+ if (!down && !longPressed) {
+ Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST, event.getDeviceId(),
+ 0 /* unused */, null /* hint */);
+ msg.setAsynchronous(true);
+ msg.sendToTarget();
+ }
+ result &= ~ACTION_PASS_TO_USER;
+ break;
+ }
+ case KeyEvent.KEYCODE_VOICE_ASSIST: {
+ if (!down) {
+ mBroadcastWakeLock.acquire();
+ Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK);
+ msg.setAsynchronous(true);
+ msg.sendToTarget();
+ }
+ result &= ~ACTION_PASS_TO_USER;
break;
}
case KeyEvent.KEYCODE_WINDOW: {
@@ -6542,18 +6538,22 @@
}
}
- void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
- IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
- if (dic != null) {
- try {
- dic.exitIdle("voice-search");
- } catch (RemoteException e) {
+ void launchVoiceAssistWithWakeLock() {
+ final Intent voiceIntent;
+ if (!keyguardOn()) {
+ voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+ } else {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
+ }
}
+ voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
+ voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
}
- Intent voiceIntent =
- new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
- voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
mBroadcastWakeLock.release();
}
@@ -8009,9 +8009,10 @@
}
private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
- final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
+ final boolean dockedStackVisible =
+ mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
final boolean freeformStackVisible =
- mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
+ mWindowManagerInternal.isStackVisible(WINDOWING_MODE_FREEFORM);
final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
// We need to force system bars when the docked stack is visible, when the freeform stack
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 6a5ecfaa..ca3dd05 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 @@
private final PendingIntent mAnomalyAlarmIntent;
private final PendingIntent mPollingAlarmIntent;
private final BroadcastReceiver mAppUpdateReceiver;
+ private final BroadcastReceiver mUserUpdateReceiver;
public StatsCompanionService(Context context) {
super();
@@ -75,6 +76,26 @@
mPollingAlarmIntent = PendingIntent.getBroadcast(mContext, 0,
new Intent(mContext, PollingAlarmReceiver.class), 0);
mAppUpdateReceiver = new AppUpdateReceiver();
+ mUserUpdateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (sStatsdLock) {
+ sStatsd = fetchStatsdService();
+ if (sStatsd == null) {
+ Slog.w(TAG, "Could not access statsd");
+ return;
+ }
+ try {
+ // Pull the latest state of UID->app name, version mapping.
+ // Needed since the new user basically has a version of every app.
+ informAllUidsLocked(context);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to inform statsd that statscompanion is ready", e);
+ forgetEverything();
+ }
+ }
+ }
+ };
Slog.w(TAG, "Registered receiver for ACTION_PACKAGE_REPLACE AND ADDED.");
}
@@ -121,6 +142,14 @@
@Override
public void onReceive(Context context, Intent intent) {
Slog.i(TAG, "StatsCompanionService noticed an app was updated.");
+ /**
+ * App updates actually consist of REMOVE, ADD, and then REPLACE broadcasts. To avoid
+ * waste, we ignore the REMOVE and ADD broadcasts that contain the replacing flag.
+ */
+ if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED) &&
+ intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ return; // Keep only replacing or normal add and remove.
+ }
synchronized (sStatsdLock) {
if (sStatsd == null) {
Slog.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
@@ -370,6 +399,14 @@
filter.addDataScheme("package");
mContext.registerReceiverAsUser(mAppUpdateReceiver, UserHandle.ALL, filter, null,
null);
+
+ // Setup receiver for user initialize (which happens once for a new user) and
+ // if a user is removed.
+ filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE);
+ filter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiverAsUser(mUserUpdateReceiver, UserHandle.ALL,
+ filter, null, null);
+
// Pull the latest state of UID->app name, version mapping when statsd starts.
informAllUidsLocked(mContext);
} catch (RemoteException e) {
@@ -391,6 +428,7 @@
synchronized (sStatsdLock) {
sStatsd = null;
mContext.unregisterReceiver(mAppUpdateReceiver);
+ mContext.unregisterReceiver(mUserUpdateReceiver);
cancelAnomalyAlarm();
cancelPollingAlarms();
}
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 6117da7..c1607e9 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -1022,20 +1022,6 @@
}
}
- @Override
- public boolean dispatchKeyEventToHdmi(KeyEvent event) throws RemoteException {
- synchronized (mImplLock) {
- if (mReleased) {
- throw new IllegalStateException("Device already released.");
- }
- }
- if (mInfo.getType() != TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) {
- return false;
- }
- // TODO(hdmi): mHdmiClient.sendKeyEvent(event);
- return false;
- }
-
private boolean startCapture(Surface surface, TvStreamConfig config) {
synchronized (mImplLock) {
if (mReleased) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index a1eeff8..1b463c7 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -823,7 +823,7 @@
// For freeform windows, we can't freeze the bounds at the moment because this would make
// the resizing unresponsive.
- if (task == null || task.inFreeformWorkspace()) {
+ if (task == null || task.inFreeformWindowingMode()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index 5c29a0a..d206554 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -18,7 +18,6 @@
import static android.graphics.PixelFormat.OPAQUE;
import static android.view.SurfaceControl.FX_SURFACE_DIM;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -51,14 +50,8 @@
int w = r-l;
int h = b-t;
- if (DEBUG_SURFACE_TRACE) {
- surface = new WindowSurfaceController.SurfaceTrace(session, "BlackSurface("
- + l + ", " + t + ")",
- w, h, OPAQUE, FX_SURFACE_DIM | SurfaceControl.HIDDEN);
- } else {
- surface = new SurfaceControl(session, "BlackSurface",
- w, h, OPAQUE, FX_SURFACE_DIM | SurfaceControl.HIDDEN);
- }
+ surface = new SurfaceControl(session, "BlackSurface",
+ w, h, OPAQUE, FX_SURFACE_DIM | SurfaceControl.HIDDEN);
surface.setAlpha(1);
surface.setLayerStack(layerStack);
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index ae41541..85f468b 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -67,14 +66,9 @@
SurfaceControl ctrl = null;
try {
- if (DEBUG_SURFACE_TRACE) {
- ctrl = new WindowSurfaceController.SurfaceTrace(session, "CircularDisplayMask",
- mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
- SurfaceControl.HIDDEN);
- } else {
- ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x,
- mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
- }
+ ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x,
+ mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 9e028d3..5bfea98 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -21,7 +21,9 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -182,6 +184,11 @@
return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
+ public boolean inSplitScreenPrimaryWindowingMode() {
+ return mFullConfiguration.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+ }
+
/**
* Returns true if this container can be put in either
* {@link WindowConfiguration#WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} or
@@ -192,6 +199,14 @@
return mFullConfiguration.windowConfiguration.supportSplitScreenWindowingMode();
}
+ public boolean inPinnedWindowingMode() {
+ return mFullConfiguration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_PINNED;
+ }
+
+ public boolean inFreeformWindowingMode() {
+ return mFullConfiguration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
+ }
+
/** Returns the activity type associated with the the configuration container. */
/*@WindowConfiguration.ActivityType*/
public int getActivityType() {
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
index 708973d..48181d3 100644
--- a/services/core/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DIM_LAYER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -105,16 +104,10 @@
private void constructSurface(WindowManagerService service) {
service.openSurfaceTransaction();
try {
- if (DEBUG_SURFACE_TRACE) {
- mDimSurface = new WindowSurfaceController.SurfaceTrace(service.mFxSession,
- "DimSurface",
+ mDimSurface = new SurfaceControl(service.mFxSession, mName,
16, 16, PixelFormat.OPAQUE,
SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
- } else {
- mDimSurface = new SurfaceControl(service.mFxSession, mName,
- 16, 16, PixelFormat.OPAQUE,
- SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
- }
+
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
" DIM " + mDimSurface + ": CREATE");
mDimSurface.setLayerStack(mDisplayId);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0b65b22..05afd55 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -16,10 +16,8 @@
package com.android.server.wm;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -980,8 +978,8 @@
}
// In the presence of the PINNED stack or System Alert
- // windows we unforuntately can not seamlessly rotate.
- if (getStackById(PINNED_STACK_ID) != null) {
+ // windows we unfortunately can not seamlessly rotate.
+ if (getStack(WINDOWING_MODE_PINNED) != null) {
mayRotateSeamlessly = false;
}
for (int i = 0; i < mService.mSessions.size(); i++) {
@@ -1774,7 +1772,7 @@
mTaskStackContainers.addStackToDisplay(stack, onTop);
}
- if (stackId == DOCKED_STACK_ID) {
+ if (stack.inSplitScreenPrimaryWindowingMode()) {
mDividerControllerLocked.notifyDockedStackExistsChanged(true);
}
return stack;
@@ -2038,7 +2036,7 @@
final WindowState imeWin = mService.mInputMethodWindow;
final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
&& !mDividerControllerLocked.isImeHideRequested();
- final boolean dockVisible = isStackVisible(DOCKED_STACK_ID);
+ final boolean dockVisible = isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
final int imeDockSide = (dockVisible && imeTargetStack != null) ?
imeTargetStack.getDockSide() : DOCKED_INVALID;
@@ -2261,10 +2259,10 @@
return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
}
- /** Checks if stack with provided id is visible on this display. */
- boolean isStackVisible(int stackId) {
- final TaskStack stack = getStackById(stackId);
- return (stack != null && stack.isVisible());
+ /** Returns true if the stack in the windowing mode is visible. */
+ boolean isStackVisible(int windowingMode) {
+ final TaskStack stack = getStack(windowingMode);
+ return stack != null && stack.isVisible();
}
/**
@@ -3557,7 +3555,8 @@
@Override
int getOrientation() {
- if (isStackVisible(DOCKED_STACK_ID) || isStackVisible(FREEFORM_WORKSPACE_STACK_ID)) {
+ if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
+ || isStackVisible(WINDOWING_MODE_FREEFORM)) {
// Apps and their containers are not allowed to specify an orientation while the
// docked or freeform stack is visible...except for the home stack/task if the
// docked stack is minimized and it actually set something.
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 6f441b9..629af66 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -16,8 +16,6 @@
package com.android.server.wm;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -588,7 +586,7 @@
private boolean containsAppInDockedStack(ArraySet<AppWindowToken> apps) {
for (int i = apps.size() - 1; i >= 0; i--) {
final AppWindowToken token = apps.valueAt(i);
- if (token.getTask() != null && token.getTask().mStack.mStackId == DOCKED_STACK_ID) {
+ if (token.getTask() != null && token.inSplitScreenPrimaryWindowingMode()) {
return true;
}
}
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
index 3186d3d..19bd8e9 100644
--- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -57,14 +56,8 @@
SurfaceControl ctrl = null;
try {
- if (DEBUG_SURFACE_TRACE) {
- ctrl = new WindowSurfaceController.SurfaceTrace(session, "EmulatorDisplayOverlay",
- mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
- SurfaceControl.HIDDEN);
- } else {
- ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x,
- mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
- }
+ ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x,
+ mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 5057f63..238cb9f 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
@@ -650,7 +649,7 @@
final boolean hasFocus = w == mInputFocus;
final boolean isVisible = w.isVisibleLw();
- if (w.getStackId() == PINNED_STACK_ID) {
+ if (w.inPinnedWindowingMode()) {
if (mAddPipInputConsumerHandle
&& (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
// Update the bounds of the Pip input consumer to match the Pinned stack
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index d5b6d24..8e99be8 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -24,7 +23,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER;
-import static com.android.server.wm.WindowSurfaceController.SurfaceTrace;
import static com.android.server.wm.proto.ScreenRotationAnimationProto.ANIMATION_RUNNING;
import static com.android.server.wm.proto.ScreenRotationAnimationProto.STARTED;
@@ -276,17 +274,10 @@
flags |= SurfaceControl.SECURE;
}
- if (DEBUG_SURFACE_TRACE) {
- mSurfaceControl = new SurfaceTrace(session, "ScreenshotSurface",
- mWidth, mHeight,
- PixelFormat.OPAQUE, flags);
- Slog.w(TAG, "ScreenRotationAnimation ctor: displayOffset="
- + mOriginalDisplayRect.toShortString());
- } else {
- mSurfaceControl = new SurfaceControl(session, "ScreenshotSurface",
- mWidth, mHeight,
- PixelFormat.OPAQUE, flags);
- }
+ mSurfaceControl = new SurfaceControl(session, "ScreenshotSurface",
+ mWidth, mHeight,
+ PixelFormat.OPAQUE, flags);
+
// capture a screenshot into the surface we just created
Surface sur = new Surface();
sur.copyFrom(mSurfaceControl);
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index c0a4cb7..c0e5fd4 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -16,8 +16,6 @@
package com.android.server.wm;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Handler;
@@ -280,8 +278,9 @@
if (stack.getWindowConfiguration().tasksAreFloating()) {
// Floating tasks should not be resized to the screen's bounds.
- if (mStackId == PINNED_STACK_ID && bounds.width() == mTmpDisplayBounds.width() &&
- bounds.height() == mTmpDisplayBounds.height()) {
+ if (stack.inPinnedWindowingMode()
+ && bounds.width() == mTmpDisplayBounds.width()
+ && bounds.height() == mTmpDisplayBounds.height()) {
// If the bounds we are animating is the same as the fullscreen stack
// dimensions, then apply the same inset calculations that we normally do for
// the fullscreen stack, without intersecting it with the display bounds
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7e8d130..6c6934f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -17,8 +17,6 @@
package com.android.server.wm;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
@@ -213,7 +211,7 @@
// then we want to preserve our insets so that there will not
// be a jump in the area covered by system decorations. We rely
// on the pinned animation to later unset this value.
- if (stack.mStackId == PINNED_STACK_ID) {
+ if (stack.inPinnedWindowingMode()) {
mPreserveNonFloatingState = true;
} else {
mPreserveNonFloatingState = false;
@@ -492,7 +490,7 @@
final boolean dockedResizing = displayContent != null
&& displayContent.mDividerControllerLocked.isResizing();
if (useCurrentBounds()) {
- if (inFreeformWorkspace() && getMaxVisibleBounds(out)) {
+ if (inFreeformWindowingMode() && getMaxVisibleBounds(out)) {
return;
}
@@ -598,14 +596,6 @@
return (tokensCount != 0) && mChildren.get(tokensCount - 1).mShowForAllUsers;
}
- boolean inFreeformWorkspace() {
- return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
- }
-
- boolean inPinnedWorkspace() {
- return mStack != null && mStack.mStackId == PINNED_STACK_ID;
- }
-
/**
* When we are in a floating stack (Freeform, Pinned, ...) we calculate
* insets differently. However if we are animating to the fullscreen stack
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index c58212c..87de151 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -20,7 +20,6 @@
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.app.ActivityManager.RESIZE_MODE_USER_FORCED;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -649,7 +648,7 @@
* shouldn't be shown.
*/
private int getDimSide(int x) {
- if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
+ if (!mTask.mStack.inFreeformWindowingMode()
|| !mTask.mStack.fillsParent()
|| mTask.mStack.getConfiguration().orientation != ORIENTATION_LANDSCAPE) {
return CTRL_NONE;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index bff24f6..54ef065 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -294,7 +294,9 @@
decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
node.end(c);
final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
-
+ if (hwBitmap == null) {
+ return null;
+ }
return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
topChild.getConfiguration().orientation, mainWindow.mStableInsets,
ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 65278837..3780d19 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -18,8 +18,6 @@
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -409,7 +407,7 @@
return false;
}
- if (mStackId == PINNED_STACK_ID) {
+ if (inPinnedWindowingMode()) {
getAnimationOrCurrentBounds(mTmpRect2);
boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
mTmpRect2, mTmpRect3);
@@ -443,21 +441,19 @@
mTmpRect2.set(mBounds);
mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
- switch (mStackId) {
- case DOCKED_STACK_ID:
- repositionDockedStackAfterRotation(mTmpRect2);
- snapDockedStackAfterRotation(mTmpRect2);
- final int newDockSide = getDockSide(mTmpRect2);
+ if (inSplitScreenPrimaryWindowingMode()) {
+ repositionDockedStackAfterRotation(mTmpRect2);
+ snapDockedStackAfterRotation(mTmpRect2);
+ final int newDockSide = getDockSide(mTmpRect2);
- // Update the dock create mode and clear the dock create bounds, these
- // might change after a rotation and the original values will be invalid.
- mService.setDockedStackCreateStateLocked(
- (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
- ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
- : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT,
- null);
- mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
- break;
+ // Update the dock create mode and clear the dock create bounds, these
+ // might change after a rotation and the original values will be invalid.
+ mService.setDockedStackCreateStateLocked(
+ (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
+ ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+ : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT,
+ null);
+ mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
}
mBoundsAfterRotation.set(mTmpRect2);
@@ -688,7 +684,7 @@
Rect bounds = null;
final TaskStack dockedStack = dc.getDockedStackIgnoringVisibility();
- if (mStackId == DOCKED_STACK_ID
+ if (inSplitScreenPrimaryWindowingMode()
|| (dockedStack != null && inSplitScreenSecondaryWindowingMode()
&& !dockedStack.fillsParent())) {
// The existence of a docked stack affects the size of other static stack created since
@@ -703,10 +699,10 @@
}
final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
== DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
- getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
+ getStackDockedModeBounds(mTmpRect, bounds, mTmpRect2,
mDisplayContent.mDividerControllerLocked.getContentWidth(),
dockedOnTopOrLeft);
- } else if (mStackId == PINNED_STACK_ID) {
+ } else if (inPinnedWindowingMode()) {
// Update the bounds based on any changes to the display info
getAnimationOrCurrentBounds(mTmpRect2);
boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
@@ -791,7 +787,7 @@
mDisplayContent.getLogicalDisplayRect(mTmpRect);
dockedStack.getRawBounds(mTmpRect2);
final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
- getStackDockedModeBounds(mTmpRect, outStackBounds, mStackId, mTmpRect2,
+ getStackDockedModeBounds(mTmpRect, outStackBounds, mTmpRect2,
mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
}
@@ -800,16 +796,15 @@
* Outputs the bounds a stack should be given the presence of a docked stack on the display.
* @param displayRect The bounds of the display the docked stack is on.
* @param outBounds Output bounds that should be used for the stack.
- * @param stackId Id of stack we are calculating the bounds for.
* @param dockedBounds Bounds of the docked stack.
* @param dockDividerWidth We need to know the width of the divider make to the output bounds
* close to the side of the dock.
* @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
*/
private void getStackDockedModeBounds(
- Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int dockDividerWidth,
+ Rect displayRect, Rect outBounds, Rect dockedBounds, int dockDividerWidth,
boolean dockOnTopOrLeft) {
- final boolean dockedStack = stackId == DOCKED_STACK_ID;
+ final boolean dockedStack = inSplitScreenPrimaryWindowingMode();
final boolean splitHorizontally = displayRect.width() > displayRect.height();
outBounds.set(displayRect);
@@ -866,7 +861,7 @@
}
void resetDockedStackToMiddle() {
- if (mStackId != DOCKED_STACK_ID) {
+ if (inSplitScreenPrimaryWindowingMode()) {
throw new IllegalStateException("Not a docked stack=" + this);
}
@@ -913,7 +908,7 @@
mAnimationBackgroundSurface = null;
}
- if (mStackId == DOCKED_STACK_ID) {
+ if (inSplitScreenPrimaryWindowingMode()) {
mDisplayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(false);
}
@@ -1035,8 +1030,8 @@
}
boolean shouldIgnoreInput() {
- return isAdjustedForMinimizedDockedStack() || mStackId == DOCKED_STACK_ID &&
- isMinimizedDockAndHomeStackResizable();
+ return isAdjustedForMinimizedDockedStack() ||
+ (inSplitScreenPrimaryWindowingMode() && isMinimizedDockAndHomeStackResizable());
}
/**
@@ -1471,7 +1466,7 @@
postExclude.set(mTmpRect);
}
- final boolean isFreeformed = task.inFreeformWorkspace();
+ final boolean isFreeformed = task.inFreeformWindowingMode();
if (task != focusedTask || isFreeformed) {
if (isFreeformed) {
// If the task is freeformed, enlarge the area to account for outside
@@ -1529,7 +1524,7 @@
}
}
- if (mStackId == PINNED_STACK_ID) {
+ if (inPinnedWindowingMode()) {
try {
mService.mActivityManager.notifyPinnedStackAnimationStarted();
} catch (RemoteException e) {
@@ -1561,7 +1556,7 @@
mService.requestTraversal();
}
- if (mStackId == PINNED_STACK_ID) {
+ if (inPinnedWindowingMode()) {
// Update to the final bounds if requested. This is done here instead of in the bounds
// animator to allow us to coordinate this after we notify the PiP mode changed
@@ -1595,7 +1590,7 @@
* bounds and we have a deferred PiP mode changed callback set with the animation.
*/
public boolean deferScheduleMultiWindowModeChanged() {
- if (mStackId == PINNED_STACK_ID) {
+ if (inPinnedWindowingMode()) {
return (mBoundsAnimatingRequested || mBoundsAnimating);
}
return false;
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 7213c95..629cc86 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -18,7 +18,7 @@
import com.android.internal.util.ToBooleanFunction;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
@@ -447,7 +447,7 @@
private void findWallpaperTarget(DisplayContent dc) {
mFindResults.reset();
- if (dc.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)) {
+ if (dc.isStackVisible(WINDOWING_MODE_FREEFORM)) {
// In freeform mode we set the wallpaper as its own target, so we don't need an
// additional window to make it visible.
mFindResults.setUseTopWallpaperAsTarget(true);
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 6d5673e..9d9805a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -60,7 +60,6 @@
static final boolean DEBUG_SCREENSHOT = false;
static final boolean DEBUG_BOOT = false;
static final boolean DEBUG_LAYOUT_REPEATS = false;
- static final boolean DEBUG_SURFACE_TRACE = false;
static final boolean DEBUG_WINDOW_TRACE = false;
static final boolean DEBUG_TASK_MOVEMENT = false;
static final boolean DEBUG_TASK_POSITIONING = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1fb2188..4ebcc36 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2384,7 +2384,7 @@
final Rect insets = new Rect();
final Rect stableInsets = new Rect();
Rect surfaceInsets = null;
- final boolean freeform = win != null && win.inFreeformWorkspace();
+ final boolean freeform = win != null && win.inFreeformWindowingMode();
if (win != null) {
// Containing frame will usually cover the whole screen, including dialog windows.
// For freeform workspace windows it will not cover the whole screen and it also
@@ -2794,7 +2794,7 @@
for (final WindowState win : mWindowMap.values()) {
final Task task = win.getTask();
if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
- && task.inFreeformWorkspace()) {
+ && task.inFreeformWindowingMode()) {
final AppWindowToken appToken = win.mAppToken;
if (appToken != null && appToken.mAppAnimator != null) {
appToken.mAppAnimator.startProlongAnimation(scaleUp ?
@@ -6898,11 +6898,6 @@
dumpSessionsLocked(pw, true);
}
return;
- } else if ("surfaces".equals(cmd)) {
- synchronized(mWindowMap) {
- WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
- }
- return;
} else if ("displays".equals(cmd) || "d".equals(cmd)) {
synchronized(mWindowMap) {
mRoot.dumpDisplayContents(pw);
@@ -6967,10 +6962,6 @@
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
- "-------------------------------------------------------------------------------"
- : null);
- pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
@@ -7604,10 +7595,10 @@
}
@Override
- public boolean isStackVisible(int stackId) {
+ public boolean isStackVisible(int windowingMode) {
synchronized (mWindowMap) {
final DisplayContent dc = getDefaultDisplayContentLocked();
- return dc.isStackVisible(stackId);
+ return dc.isStackVisible(windowingMode);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4ff0f39..2118024 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -16,10 +16,7 @@
package com.android.server.wm;
-import static android.app.ActivityManager.StackId;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
@@ -83,7 +80,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -815,13 +811,12 @@
final WindowState imeWin = mService.mInputMethodWindow;
// IME is up and obscuring this window. Adjust the window position so it is visible.
if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) {
- final int stackId = getStackId();
- if (stackId == FREEFORM_WORKSPACE_STACK_ID
+ if (inFreeformWindowingMode()
&& mContainingFrame.bottom > contentFrame.bottom) {
// In freeform we want to move the top up directly.
// TODO: Investigate why this is contentFrame not parentFrame.
mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
- } else if (stackId != PINNED_STACK_ID
+ } else if (!inPinnedWindowingMode()
&& mContainingFrame.bottom > parentFrame.bottom) {
// But in docked we want to behave like fullscreen and behave as if the task
// were given smaller bounds for the purposes of layout. Skip adjustments for
@@ -898,7 +893,7 @@
// For pinned workspace the frame isn't limited in any particular
// way since SystemUI controls the bounds. For freeform however
// we want to keep things inside the content frame.
- final Rect limitFrame = task.inPinnedWorkspace() ? mFrame : mContentFrame;
+ final Rect limitFrame = task.inPinnedWindowingMode() ? mFrame : mContentFrame;
// Keep the frame out of the blocked system area, limit it in size to the content area
// and make sure that there is always a minimum visible so that the user can drag it
// into a usable area..
@@ -1210,7 +1205,7 @@
// application when it has finished drawing.
if (getOrientationChanging() || dragResizingChanged
|| isResizedWhileNotDragResizing()) {
- if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
+ if (DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
+ ", mDrawState=DRAW_PENDING in " + this
+ ", surfaceController " + winAnimator.mSurfaceController);
@@ -1662,9 +1657,9 @@
//
// Anyway we don't need to synchronize position and content updates for these
// windows since they aren't at the base layer and could be moved around anyway.
- if (!computeDragResizing() && mAttrs.type == TYPE_BASE_APPLICATION &&
- !mWinAnimator.isForceScaled() && !isGoneForLayoutLw() &&
- !getTask().inPinnedWorkspace()) {
+ if (!computeDragResizing() && mAttrs.type == TYPE_BASE_APPLICATION
+ && !mWinAnimator.isForceScaled() && !isGoneForLayoutLw()
+ && !getTask().inPinnedWindowingMode()) {
setResizedWhileNotDragResizing(true);
}
}
@@ -2196,12 +2191,6 @@
}
}
- // TODO: Strange usage of word workspace here and above.
- boolean inPinnedWorkspace() {
- final Task task = getTask();
- return task != null && task.inPinnedWorkspace();
- }
-
void applyAdjustForImeIfNeeded() {
final Task task = getTask();
if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) {
@@ -2235,7 +2224,7 @@
} else {
getVisibleBounds(mTmpRect);
}
- if (inFreeformWorkspace()) {
+ if (inFreeformWindowingMode()) {
// For freeform windows we the touch region to include the whole surface for the
// shadows.
final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
@@ -2938,8 +2927,7 @@
return mTmpRect;
}
- @Override
- public int getStackId() {
+ private int getStackId() {
final TaskStack stack = getStack();
if (stack == null) {
return INVALID_STACK_ID;
@@ -2983,11 +2971,6 @@
}
}
- boolean inFreeformWorkspace() {
- final Task task = getTask();
- return task != null && task.inFreeformWorkspace();
- }
-
@Override
public boolean isInMultiWindowMode() {
final Task task = getTask();
@@ -3105,7 +3088,7 @@
// background.
return (getDisplayContent().mDividerControllerLocked.isResizing()
|| mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
- !task.inFreeformWorkspace() && !isGoneForLayoutLw();
+ !task.inFreeformWindowingMode() && !isGoneForLayoutLw();
}
@@ -3695,7 +3678,7 @@
// Force the show in the next prepareSurfaceLocked() call.
mWinAnimator.mLastAlpha = -1;
- if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) Slog.v(TAG,
+ if (DEBUG_ANIM) Slog.v(TAG,
"performShowLocked: mDrawState=HAS_DRAWN in " + this);
mWinAnimator.mDrawState = HAS_DRAWN;
mService.scheduleAnimationLocked();
@@ -3756,7 +3739,7 @@
windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor;
windowInfo.focused = isFocused();
Task task = getTask();
- windowInfo.inPictureInPicture = (task != null) && task.inPinnedWorkspace();
+ windowInfo.inPictureInPicture = (task != null) && task.inPinnedWindowingMode();
if (mIsChildWindow) {
windowInfo.parentToken = getParentWindow().mClient.asBinder();
@@ -4219,7 +4202,7 @@
// If a freeform window is animating from a position where it would be cutoff, it would be
// cutoff during the animation. We don't want that, so for the duration of the animation
// we ignore the decor cropping and depend on layering to position windows correctly.
- final boolean cropToDecor = !(inFreeformWorkspace() && isAnimatingLw());
+ final boolean cropToDecor = !(inFreeformWindowingMode() && isAnimatingLw());
if (cropToDecor) {
// Intersect with the decor rect, offsetted by window position.
systemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
@@ -4303,7 +4286,7 @@
// scale for the animation using the source hint rect
// (see WindowStateAnimator#setSurfaceBoundariesLocked()).
if (isDragResizeChanged() || isResizedWhileNotDragResizing()
- || (surfaceInsetsChanging() && !inPinnedWorkspace())) {
+ || (surfaceInsetsChanging() && !inPinnedWindowingMode())) {
mLastSurfaceInsets.set(mAttrs.surfaceInsets);
setDragResizing();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1b7e527..5266903 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -31,7 +31,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP;
@@ -509,7 +508,7 @@
boolean layoutNeeded = false;
if (mDrawState == DRAW_PENDING) {
- if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
+ if (DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in "
+ mSurfaceController);
if (DEBUG_STARTING_WINDOW && startingWindow) {
@@ -532,7 +531,7 @@
if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
return false;
}
- if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) {
+ if (DEBUG_ANIM) {
Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController);
}
mDrawState = READY_TO_SHOW;
@@ -1033,7 +1032,7 @@
//Slog.i(TAG_WM, "Not applying alpha transform");
}
- if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV)
+ if ((DEBUG_ANIM || WindowManagerService.localLOGV)
&& (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
+ " self=" + (selfTransformation ? mTransformation.getAlpha() : "null")
@@ -1112,7 +1111,7 @@
*/
private boolean useFinalClipRect() {
return (isAnimationSet() && resolveStackClip() == STACK_CLIP_AFTER_ANIM)
- || mDestroyPreservedSurfaceUponRedraw || mWin.inPinnedWorkspace();
+ || mDestroyPreservedSurfaceUponRedraw || mWin.inPinnedWindowingMode();
}
/**
@@ -1177,7 +1176,7 @@
return false;
}
- if (w.inPinnedWorkspace()) {
+ if (w.inPinnedWindowingMode()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 2e1e3f7..d56df55 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -22,7 +22,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -565,262 +564,4 @@
public String toString() {
return mSurfaceControl.toString();
}
-
- static class SurfaceTrace extends SurfaceControl {
- private final static String SURFACE_TAG = TAG_WITH_CLASS_NAME ? "SurfaceTrace" : TAG_WM;
- private final static boolean LOG_SURFACE_TRACE = DEBUG_SURFACE_TRACE;
- final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>();
-
- private float mSurfaceTraceAlpha = 0;
- private int mLayer;
- private final PointF mPosition = new PointF();
- private final Point mSize = new Point();
- private final Rect mWindowCrop = new Rect();
- private final Rect mFinalCrop = new Rect();
- private boolean mShown = false;
- private int mLayerStack;
- private boolean mIsOpaque;
- private float mDsdx, mDtdx, mDsdy, mDtdy;
- private final String mName;
-
- public SurfaceTrace(SurfaceSession s, String name, int w, int h, int format, int flags,
- int windowType, int ownerUid)
- throws OutOfResourcesException {
- super(s, name, w, h, format, flags, windowType, ownerUid);
- mName = name != null ? name : "Not named";
- mSize.set(w, h);
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
- + Debug.getCallers(3));
- synchronized (sSurfaces) {
- sSurfaces.add(0, this);
- }
- }
-
- public SurfaceTrace(SurfaceSession s,
- String name, int w, int h, int format, int flags) {
- super(s, name, w, h, format, flags);
- mName = name != null ? name : "Not named";
- mSize.set(w, h);
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
- + Debug.getCallers(3));
- synchronized (sSurfaces) {
- sSurfaces.add(0, this);
- }
- }
-
- @Override
- public void setAlpha(float alpha) {
- if (mSurfaceTraceAlpha != alpha) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setAlpha(" + alpha + "): OLD:" + this +
- ". Called by " + Debug.getCallers(3));
- mSurfaceTraceAlpha = alpha;
- }
- super.setAlpha(alpha);
- }
-
- @Override
- public void setLayer(int zorder) {
- if (zorder != mLayer) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setLayer(" + zorder + "): OLD:" + this
- + ". Called by " + Debug.getCallers(3));
- mLayer = zorder;
- }
- super.setLayer(zorder);
-
- synchronized (sSurfaces) {
- sSurfaces.remove(this);
- int i;
- for (i = sSurfaces.size() - 1; i >= 0; i--) {
- SurfaceTrace s = sSurfaces.get(i);
- if (s.mLayer < zorder) {
- break;
- }
- }
- sSurfaces.add(i + 1, this);
- }
- }
-
- @Override
- public void setPosition(float x, float y) {
- if (x != mPosition.x || y != mPosition.y) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setPosition(" + x + "," + y + "): OLD:"
- + this + ". Called by " + Debug.getCallers(3));
- mPosition.set(x, y);
- }
- super.setPosition(x, y);
- }
-
- @Override
- public void setGeometryAppliesWithResize() {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setGeometryAppliesWithResize(): OLD: "
- + this + ". Called by" + Debug.getCallers(3));
- super.setGeometryAppliesWithResize();
- }
-
- @Override
- public void setSize(int w, int h) {
- if (w != mSize.x || h != mSize.y) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setSize(" + w + "," + h + "): OLD:"
- + this + ". Called by " + Debug.getCallers(3));
- mSize.set(w, h);
- }
- super.setSize(w, h);
- }
-
- @Override
- public void setWindowCrop(Rect crop) {
- if (crop != null) {
- if (!crop.equals(mWindowCrop)) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setWindowCrop("
- + crop.toShortString() + "): OLD:" + this + ". Called by "
- + Debug.getCallers(3));
- mWindowCrop.set(crop);
- }
- }
- super.setWindowCrop(crop);
- }
-
- @Override
- public void setFinalCrop(Rect crop) {
- if (crop != null) {
- if (!crop.equals(mFinalCrop)) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setFinalCrop("
- + crop.toShortString() + "): OLD:" + this + ". Called by "
- + Debug.getCallers(3));
- mFinalCrop.set(crop);
- }
- }
- super.setFinalCrop(crop);
- }
-
- @Override
- public void setLayerStack(int layerStack) {
- if (layerStack != mLayerStack) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setLayerStack(" + layerStack + "): OLD:"
- + this + ". Called by " + Debug.getCallers(3));
- mLayerStack = layerStack;
- }
- super.setLayerStack(layerStack);
- }
-
- @Override
- public void setOpaque(boolean isOpaque) {
- if (isOpaque != mIsOpaque) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setOpaque(" + isOpaque + "): OLD:"
- + this + ". Called by " + Debug.getCallers(3));
- mIsOpaque = isOpaque;
- }
- super.setOpaque(isOpaque);
- }
-
- @Override
- public void setSecure(boolean isSecure) {
- super.setSecure(isSecure);
- }
-
- @Override
- public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
- if (dsdx != mDsdx || dtdx != mDtdx || dsdy != mDsdy || dtdy != mDtdy) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setMatrix(" + dsdx + "," + dtdx + ","
- + dsdy + "," + dtdy + "): OLD:" + this + ". Called by "
- + Debug.getCallers(3));
- mDsdx = dsdx;
- mDtdx = dtdx;
- mDsdy = dsdy;
- mDtdy = dtdy;
- }
- super.setMatrix(dsdx, dtdx, dsdy, dtdy);
- }
-
- @Override
- public void hide() {
- if (mShown) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by "
- + Debug.getCallers(3));
- mShown = false;
- }
- super.hide();
- }
-
- @Override
- public void show() {
- if (!mShown) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "show: OLD:" + this + ". Called by "
- + Debug.getCallers(3));
- mShown = true;
- }
- super.show();
- }
-
- @Override
- public void destroy() {
- super.destroy();
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "destroy: " + this + ". Called by "
- + Debug.getCallers(3));
- synchronized (sSurfaces) {
- sSurfaces.remove(this);
- }
- }
-
- @Override
- public void release() {
- super.release();
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "release: " + this + ". Called by "
- + Debug.getCallers(3));
- synchronized (sSurfaces) {
- sSurfaces.remove(this);
- }
- }
-
- @Override
- public void setTransparentRegionHint(Region region) {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setTransparentRegionHint(" + region
- + "): OLD: " + this + " . Called by " + Debug.getCallers(3));
- super.setTransparentRegionHint(region);
- }
-
- static void dumpAllSurfaces(PrintWriter pw, String header) {
- synchronized (sSurfaces) {
- final int N = sSurfaces.size();
- if (N <= 0) {
- return;
- }
- if (header != null) {
- pw.println(header);
- }
- pw.println("WINDOW MANAGER SURFACES (dumpsys window surfaces)");
- for (int i = 0; i < N; i++) {
- SurfaceTrace s = sSurfaces.get(i);
- pw.print(" Surface #"); pw.print(i); pw.print(": #");
- pw.print(Integer.toHexString(System.identityHashCode(s)));
- pw.print(" "); pw.println(s.mName);
- pw.print(" mLayerStack="); pw.print(s.mLayerStack);
- pw.print(" mLayer="); pw.println(s.mLayer);
- pw.print(" mShown="); pw.print(s.mShown); pw.print(" mAlpha=");
- pw.print(s.mSurfaceTraceAlpha); pw.print(" mIsOpaque=");
- pw.println(s.mIsOpaque);
- pw.print(" mPosition="); pw.print(s.mPosition.x); pw.print(",");
- pw.print(s.mPosition.y);
- pw.print(" mSize="); pw.print(s.mSize.x); pw.print("x");
- pw.println(s.mSize.y);
- pw.print(" mCrop="); s.mWindowCrop.printShortString(pw); pw.println();
- pw.print(" mFinalCrop="); s.mFinalCrop.printShortString(pw); pw.println();
- pw.print(" Transform: ("); pw.print(s.mDsdx); pw.print(", ");
- pw.print(s.mDtdx); pw.print(", "); pw.print(s.mDsdy);
- pw.print(", "); pw.print(s.mDtdy); pw.println(")");
- }
- }
- }
-
- @Override
- public String toString() {
- return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
- + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
- + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
- + " " + mSize.x + "x" + mSize.y
- + " crop=" + mWindowCrop.toShortString()
- + " opaque=" + mIsOpaque
- + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
- }
- }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ff45070..49dd5285 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -125,6 +125,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
+import static android.os.IServiceManager.DUMP_PRIORITY_CRITICAL;
import static android.view.Display.DEFAULT_DISPLAY;
public final class SystemServer {
@@ -824,7 +825,8 @@
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
- ServiceManager.addService(Context.WINDOW_SERVICE, wm);
+ ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
+ DUMP_PRIORITY_CRITICAL);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 9fa1d68..0b4d61f 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -19,6 +19,7 @@
import static android.app.Notification.GROUP_ALERT_CHILDREN;
import static android.app.Notification.GROUP_ALERT_SUMMARY;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -57,7 +58,13 @@
import android.service.notification.StatusBarNotification;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Slog;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManager;
+import android.view.accessibility.IAccessibilityManagerClient;
+import com.android.internal.util.IntPair;
import com.android.server.lights.Light;
import org.junit.Before;
@@ -67,6 +74,8 @@
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -80,6 +89,8 @@
NotificationManagerService.WorkerHandler mHandler;
@Mock
NotificationUsageStats mUsageStats;
+ @Mock
+ IAccessibilityManager mAccessibilityService;
private NotificationManagerService mService;
private String mPkg = "com.android.server.notification";
@@ -111,17 +122,25 @@
private static final int MAX_VIBRATION_DELAY = 1000;
@Before
- public void setUp() {
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mAudioManager.isAudioFocusExclusive()).thenReturn(false);
when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer);
when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
-
when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
- mService = new NotificationManagerService(getContext());
+ long serviceReturnValue = IntPair.of(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED,
+ AccessibilityEvent.TYPES_ALL_MASK);
+ when(mAccessibilityService.addClient(any(), anyInt())).thenReturn(serviceReturnValue);
+ AccessibilityManager accessibilityManager =
+ new AccessibilityManager(Handler.getMain(), mAccessibilityService, 0);
+ verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt());
+ assertTrue(accessibilityManager.isEnabled());
+
+ mService = spy(new NotificationManagerService(getContext()));
mService.setAudioManager(mAudioManager);
mService.setVibrator(mVibrator);
mService.setSystemReady(true);
@@ -130,6 +149,7 @@
mService.setScreenOn(false);
mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN);
mService.setUsageStats(mUsageStats);
+ mService.setAccessibilityManager(accessibilityManager);
}
//
@@ -381,6 +401,7 @@
verifyBeepLooped();
verifyNeverVibrate();
+ verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
}
@Test
@@ -435,6 +456,7 @@
r.isUpdate = true;
mService.buzzBeepBlinkLocked(r);
verifyBeepLooped();
+ verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
}
@Test
@@ -450,6 +472,7 @@
// update should not beep
mService.buzzBeepBlinkLocked(s);
verifyNeverBeep();
+ verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
}
@Test
@@ -547,7 +570,7 @@
mService.mInCall = true;
mService.buzzBeepBlinkLocked(r);
- //verify(mService, times(1)).playInCallNotification();
+ verify(mService, times(1)).playInCallNotification();
verifyNeverBeep(); // doesn't play normal beep
}
@@ -842,7 +865,6 @@
mService.addNotification(r);
mService.buzzBeepBlinkLocked(r);
-
verifyNeverBeep();
}
@@ -870,7 +892,6 @@
summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
mService.buzzBeepBlinkLocked(summary);
-
verify(mUsageStats, never()).isAlertRateLimited(any());
}
@@ -889,6 +910,30 @@
verifyNeverBeep();
}
+ @Test
+ public void testA11yMinInitialPost() throws Exception {
+ NotificationRecord r = getQuietNotification();
+ r.setImportance(IMPORTANCE_MIN, "");
+ mService.buzzBeepBlinkLocked(r);
+ verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
+ }
+
+ @Test
+ public void testA11yQuietInitialPost() throws Exception {
+ NotificationRecord r = getQuietNotification();
+ mService.buzzBeepBlinkLocked(r);
+ verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
+ }
+
+ @Test
+ public void testA11yQuietUpdate() throws Exception {
+ NotificationRecord r = getQuietNotification();
+ mService.buzzBeepBlinkLocked(r);
+ r.isUpdate = true;
+ mService.buzzBeepBlinkLocked(r);
+ verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
+ }
+
static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
private final int mRepeatIndex;
diff --git a/services/tests/notification/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/notification/src/com/android/server/notification/ZenModeHelperTest.java
new file mode 100644
index 0000000..cbe9650
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/ZenModeHelperTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2017 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 distriZenbuted 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.notification;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.media.AudioAttributes;
+import android.provider.Settings;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class ZenModeHelperTest extends NotificationTestCase {
+
+ @Mock ConditionProviders mConditionProviders;
+ private TestableLooper mTestableLooper;
+ private ZenModeHelper mZenModeHelperSpy;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mTestableLooper = TestableLooper.get(this);
+ mZenModeHelperSpy = spy(new ZenModeHelper(getContext(), mTestableLooper.getLooper(),
+ mConditionProviders));
+ }
+
+ @Test
+ public void testZenOff_NoMuteApplied() {
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_OFF;
+ assertTrue(mZenModeHelperSpy.mConfig.allowAlarms);
+ mZenModeHelperSpy.applyRestrictions();
+
+ doNothing().when(mZenModeHelperSpy).applyRestrictions(anyBoolean(), anyInt());
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_ALARM);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_MEDIA);
+ }
+
+ @Test
+ public void testZenOn_AllowAlarmsMedia_NoAlarmMediaMuteApplied() {
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ assertTrue(mZenModeHelperSpy.mConfig.allowAlarms);
+ assertTrue(mZenModeHelperSpy.mConfig.allowMediaSystemOther);
+ mZenModeHelperSpy.applyRestrictions();
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_ALARM);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_MEDIA);
+ }
+
+ @Test
+ public void testZenOn_DisallowAlarmsMedia_AlarmMediaMuteApplied() {
+
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mConfig.allowAlarms = false;
+ mZenModeHelperSpy.mConfig.allowMediaSystemOther = false;
+ assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
+ assertFalse(mZenModeHelperSpy.mConfig.allowMediaSystemOther);
+ mZenModeHelperSpy.applyRestrictions();
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_ALARM);
+
+ // Media is a catch-all that includes games and system sounds
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_MEDIA);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_GAME);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION);
+ }
+}
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index fd83223..6d7d4cb 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -62,6 +62,8 @@
LOCAL_STATIC_JAVA_LIBRARIES += ub-uiautomator
+LOCAL_PROGUARD_ENABLED := disabled
+
include $(BUILD_PACKAGE)
include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/tests/servicestests/assets/shortcut/shortcut_api27_backup.xml b/services/tests/servicestests/assets/shortcut/shortcut_api27_backup.xml
new file mode 100644
index 0000000..266ab99
--- /dev/null
+++ b/services/tests/servicestests/assets/shortcut/shortcut_api27_backup.xml
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<user>
+ <launcher-pins package-name="com.android.launcher.1" launcher-user="0">
+ <package-info version="9" last_udpate_time="1230768000000">
+ <signature hash="0X8l7PvMeFf3vr6kaTCL4LJYCUPpbROjrZihNnXEv8I" />
+ </package-info>
+ <package package-name="com.android.test.1" package-user="0">
+ <pin value="s1" />
+ </package>
+ </launcher-pins>
+ <package name="com.android.test.1" call-count="0" last-reset="1506991428317">
+ <package-info version="8" last_udpate_time="1506534668998">
+ <signature hash="zDmdc5A/Bu5pQDKrBTjwVjT/fhzl6OUKwzCocUhPNM8" />
+ </package-info>
+ <shortcut id="s1" activity="com.android.test.1/com.example.android.shortcutsample.Main" title="Leak wakelock" titleid="0" textid="0" dmessageid="0" timestamp="1507674156622" flags="130">
+ <intent intent-base="#Intent;action=com.example.android.shortcutsample.LEAK;launchFlags=0x1000c000;component=com.example.android.shortcutsample/.Main;end" />
+ </shortcut>
+ </package>
+</user>
diff --git a/services/tests/servicestests/res/xml/shortcut_5_altalt.xml b/services/tests/servicestests/res/xml/shortcut_5_altalt.xml
new file mode 100644
index 0000000..1476a27
--- /dev/null
+++ b/services/tests/servicestests/res/xml/shortcut_5_altalt.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="ms1"
+ android:enabled="true"
+ android:icon="@drawable/icon1"
+ android:shortcutShortLabel="@string/shortcut_title1"
+ android:shortcutLongLabel="@string/shortcut_text1"
+ android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
+ >
+ <intent
+ android:action="action1"
+ android:data="http://a.b.c/1"
+ >
+ </intent>
+ <categories android:name="android.shortcut.conversation" />
+ <categories android:name="android.shortcut.media" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="ms2"
+ android:enabled="true"
+ android:icon="@drawable/icon2"
+ android:shortcutShortLabel="@string/shortcut_title2"
+ android:shortcutLongLabel="@string/shortcut_text2"
+ android:shortcutDisabledMessage="@string/shortcut_disabled_message2"
+ >
+ <intent
+ android:action="action2"
+ >
+ </intent>
+ <categories android:name="android.shortcut.conversation" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="ms3"
+ android:shortcutShortLabel="@string/shortcut_title1"
+ android:shortcutLongLabel="@string/shortcut_title2"
+ >
+ <intent
+ android:action="android.intent.action.VIEW"
+ >
+ </intent>
+ </shortcut>
+ <shortcut
+ android:shortcutId="ms4"
+ android:shortcutShortLabel="@string/shortcut_title2"
+ android:shortcutLongLabel="@string/shortcut_title2"
+ >
+ <intent
+ android:action="android.intent.action.VIEW2"
+ >
+ </intent>
+ <categories />
+ <categories android:name="" />
+ <categories android:name="cat" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="ms5"
+ android:shortcutShortLabel="@string/shortcut_title1"
+ >
+ <intent
+ android:action="action"
+ android:data="http://www/"
+ android:targetPackage="abc"
+ android:targetClass=".xyz"
+ android:mimeType="foo/bar"
+ >
+ <categories android:name="cat1" />
+ <categories android:name="cat2" />
+ <extra android:name="key1" android:value="value1" />
+ <extra android:name="key2" android:value="value2" />
+ </intent>
+ </shortcut>
+</shortcuts>
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java
index 02f645a..c8dc9ff 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java
@@ -77,7 +77,6 @@
mAccessibilityCache.clear();
AccessibilityInteractionClient.getInstance().clearCache();
assertEquals(0, numA11yWinInfosInUse.get());
- assertEquals(0, numA11yNodeInfosInUse.get());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index 855b82c..e1623b0 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -20,7 +20,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import android.app.ActivityManager;
import android.content.ComponentName;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -83,7 +82,7 @@
assertTrue(task2.getStack() instanceof PinnedActivityStack);
mStarter.updateBounds(task2, bounds);
- verify(mService, times(1)).resizeStack(eq(ActivityManager.StackId.PINNED_STACK_ID),
+ verify(mService, times(1)).resizeStack(eq(task2.getStack().mStackId),
eq(bounds), anyBoolean(), anyBoolean(), anyBoolean(), anyInt());
// In the case of no animation, the stack and task bounds should be set immediately.
@@ -94,4 +93,4 @@
assertEquals(task2.mBounds, null);
}
}
-}
\ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index cc8bd69..20077f3 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -103,15 +103,21 @@
protected static TaskRecord createTask(ActivityStackSupervisor supervisor,
ComponentName component, ActivityStack stack) {
+ return createTask(supervisor, component, 0 /* flags */, 0 /* taskId */, stack);
+ }
+
+ protected static TaskRecord createTask(ActivityStackSupervisor supervisor,
+ ComponentName component, int flags, int taskId, ActivityStack stack) {
final ActivityInfo aInfo = new ActivityInfo();
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.packageName = component.getPackageName();
Intent intent = new Intent();
intent.setComponent(component);
+ intent.setFlags(flags);
- final TaskRecord task = new TaskRecord(supervisor.mService, 0, aInfo, intent /*intent*/,
- null /*_taskDescription*/);
+ final TaskRecord task = new TaskRecord(supervisor.mService, taskId, aInfo,
+ intent /*intent*/, null /*_taskDescription*/);
supervisor.setFocusStackUnchecked("test", stack);
stack.addTask(task, true, "creating test task");
task.setStack(stack);
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchBoundsTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchBoundsTests.java
new file mode 100644
index 0000000..e6d6831
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/LaunchBoundsTests.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2017 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.am;
+
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.WindowLayout;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import android.view.Display;
+import android.view.Gravity;
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.mockito.invocation.InvocationOnMock;
+
+import java.util.ArrayList;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doAnswer;
+import static org.junit.Assert.assertEquals;
+
+
+/**
+ * Tests for exercising resizing bounds.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.am.LaunchBoundsTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class LaunchBoundsTests extends ActivityTestsBase {
+ private final ComponentName testActivityComponent =
+ ComponentName.unflattenFromString("com.foo/.BarActivity");
+ private final ComponentName testActivityComponent2 =
+ ComponentName.unflattenFromString("com.foo/.BarActivity2");
+
+ private final static int STACK_WIDTH = 100;
+ private final static int STACK_HEIGHT = 200;
+
+ private final static Rect STACK_BOUNDS = new Rect(0, 0, STACK_WIDTH, STACK_HEIGHT);
+
+ private ActivityManagerService mService;
+ private ActivityStack mStack;
+ private TaskRecord mTask;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mService = createActivityManagerService();
+ mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ mStack.requestResize(STACK_BOUNDS);
+
+ // We must create the task after resizing to make sure it does not inherit the stack
+ // dimensions on resize.
+ mTask = createTask(mService.mStackSupervisor, testActivityComponent, mStack);
+ }
+
+ /**
+ * Ensures that the setup bounds are set as expected with the stack bounds set and the task
+ * bounds still {@code null}.
+ * @throws Exception
+ */
+ @Test
+ public void testInitialBounds() throws Exception {
+ assertEquals(mStack.mBounds, STACK_BOUNDS);
+ assertEquals(mTask.mBounds, null);
+ }
+
+ /**
+ * Ensures that a task positioned with no {@link WindowLayout} receives the default launch
+ * position.
+ * @throws Exception
+ */
+ @Test
+ public void testLaunchNoWindowLayout() throws Exception {
+ final Rect expectedTaskBounds = getDefaultBounds(Gravity.NO_GRAVITY);
+
+ mStack.layoutTaskInStack(mTask, null);
+
+ // We expect the task to be placed in the middle of the screen with margins applied.
+ assertEquals(mTask.mBounds, expectedTaskBounds);
+ }
+
+ /**
+ * Ensures that a task positioned with an empty {@link WindowLayout} receives the default launch
+ * position.
+ * @throws Exception
+ */
+ @Test
+ public void testlaunchEmptyWindowLayout() throws Exception {
+ final Rect expectedTaskBounds = getDefaultBounds(Gravity.NO_GRAVITY);
+
+ WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0);
+ mStack.layoutTaskInStack(mTask, layout);
+ assertEquals(mTask.mBounds, expectedTaskBounds);
+ }
+
+ /**
+ * Ensures that a task positioned with a {@link WindowLayout} gravity specified is positioned
+ * according to specification.
+ * @throws Exception
+ */
+ @Test
+ public void testlaunchWindowLayoutGravity() throws Exception {
+ // Unspecified gravity should be ignored
+ testGravity(Gravity.NO_GRAVITY);
+
+ // Unsupported gravity should be ignored
+ testGravity(Gravity.LEFT);
+ testGravity(Gravity.RIGHT);
+
+ // Test defaults for vertical gravities
+ testGravity(Gravity.TOP);
+ testGravity(Gravity.BOTTOM);
+
+ // Test corners
+ testGravity(Gravity.TOP | Gravity.LEFT);
+ testGravity(Gravity.TOP | Gravity.RIGHT);
+ testGravity(Gravity.BOTTOM | Gravity.LEFT);
+ testGravity(Gravity.BOTTOM | Gravity.RIGHT);
+ }
+
+ private void testGravity(int gravity) {
+ final WindowLayout gravityLayout = new WindowLayout(0, 0, 0, 0, gravity, 0, 0);
+ mStack.layoutTaskInStack(mTask, gravityLayout);
+ assertEquals(mTask.mBounds, getDefaultBounds(gravity));
+ }
+
+ /**
+ * Ensures that a task which causes a conflict with another task when positioned is adjusted as
+ * expected.
+ * @throws Exception
+ */
+ @Test
+ public void testLaunchWindowCenterConflict() throws Exception {
+ testConflict(Gravity.NO_GRAVITY);
+ testConflict(Gravity.TOP);
+ testConflict(Gravity.BOTTOM);
+ testConflict(Gravity.TOP | Gravity.LEFT);
+ testConflict(Gravity.TOP | Gravity.RIGHT);
+ testConflict(Gravity.BOTTOM | Gravity.LEFT);
+ testConflict(Gravity.BOTTOM | Gravity.RIGHT);
+ }
+
+ private void testConflict(int gravity) {
+ final WindowLayout layout = new WindowLayout(0, 0, 0, 0, gravity, 0, 0);
+
+ // layout first task
+ mStack.layoutTaskInStack(mTask, layout /*windowLayout*/);
+
+ // Second task will be laid out on top of the first so starting bounds is the same.
+ final Rect expectedBounds = new Rect(mTask.mBounds);
+
+ ActivityRecord activity = null;
+ TaskRecord secondTask = null;
+
+ // wrap with try/finally to ensure cleanup of activity/stack.
+ try {
+ // empty tasks are ignored in conflicts
+ activity = createActivity(mService, testActivityComponent, mTask);
+
+ // Create secondary task
+ secondTask = createTask(mService.mStackSupervisor, testActivityComponent,
+ mStack);
+
+ // layout second task
+ mStack.layoutTaskInStack(secondTask, layout /*windowLayout*/);
+
+ if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT)
+ || (gravity & (Gravity.BOTTOM | Gravity.RIGHT))
+ == (Gravity.BOTTOM | Gravity.RIGHT)) {
+ expectedBounds.offset(-LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds),
+ 0);
+ } else if ((gravity & Gravity.TOP) == Gravity.TOP
+ || (gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
+ expectedBounds.offset(LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds), 0);
+ } else {
+ expectedBounds.offset(LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds),
+ LaunchingTaskPositioner.getVerticalStep(mStack.mBounds));
+ }
+
+ assertEquals(secondTask.mBounds, expectedBounds);
+ } finally {
+ // Remove task and activity to prevent influencing future tests
+ if (activity != null) {
+ mTask.removeActivity(activity);
+ }
+
+ if (secondTask != null) {
+ mStack.removeTask(secondTask, "cleanup", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+ }
+ }
+ }
+
+ private Rect getDefaultBounds(int gravity) {
+ final Rect bounds = new Rect();
+ bounds.set(mStack.mBounds);
+
+ final int verticalInset = LaunchingTaskPositioner.getFreeformStartTop(mStack.mBounds);
+ final int horizontalInset = LaunchingTaskPositioner.getFreeformStartLeft(mStack.mBounds);
+
+ bounds.inset(horizontalInset, verticalInset);
+
+ if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT)) {
+ bounds.offsetTo(horizontalInset * 2, 0);
+ } else if ((gravity & Gravity.TOP) == Gravity.TOP) {
+ bounds.offsetTo(0, 0);
+ } else if ((gravity & (Gravity.BOTTOM | Gravity.RIGHT))
+ == (Gravity.BOTTOM | Gravity.RIGHT)) {
+ bounds.offsetTo(horizontalInset * 2, verticalInset * 2);
+ } else if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
+ bounds.offsetTo(0, verticalInset * 2);
+ }
+
+ return bounds;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
new file mode 100644
index 0000000..e607228
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2017 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.am;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.Debug;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.MutableLong;
+import android.util.SparseBooleanArray;
+
+import com.android.server.am.RecentTasks.Callbacks;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class RecentTasksTest extends ActivityTestsBase {
+ private static final int TEST_USER_0_ID = 0;
+ private static final int TEST_USER_1_ID = 10;
+ private static final int TEST_QUIET_USER_ID = 20;
+ private static final UserInfo DEFAULT_USER_INFO = new UserInfo();
+ private static final UserInfo QUIET_USER_INFO = new UserInfo();
+ private static int LAST_TASK_ID = 1;
+
+ private Context mContext = InstrumentationRegistry.getContext();
+ private ActivityManagerService mService;
+ private ActivityStack mStack;
+ private TestTaskPersister mTaskPersister;
+ private RecentTasks mRecentTasks;
+
+ private static ArrayList<TaskRecord> mTasks = new ArrayList<>();
+ private static ArrayList<TaskRecord> mSameDocumentTasks = new ArrayList<>();
+
+ private CallbacksRecorder mCallbacksRecorder;
+
+ class TestUserController extends UserController {
+ TestUserController(ActivityManagerService service) {
+ super(service);
+ }
+
+ @Override
+ int[] getCurrentProfileIds() {
+ return new int[] { TEST_USER_0_ID, TEST_QUIET_USER_ID };
+ }
+
+ @Override
+ UserInfo getUserInfo(int userId) {
+ switch (userId) {
+ case TEST_USER_0_ID:
+ case TEST_USER_1_ID:
+ return DEFAULT_USER_INFO;
+ case TEST_QUIET_USER_ID:
+ return QUIET_USER_INFO;
+ }
+ return null;
+ }
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mService = createActivityManagerService();
+ mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
+ mRecentTasks = new RecentTasks(mService, mTaskPersister, new TestUserController(mService));
+ mRecentTasks.loadParametersFromResources(mContext.getResources());
+ mCallbacksRecorder = new CallbacksRecorder();
+ mRecentTasks.registerCallback(mCallbacksRecorder);
+ QUIET_USER_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_QUIET_MODE;
+
+ mTasks.add(createTask(".Task1"));
+ mTasks.add(createTask(".Task2"));
+ mTasks.add(createTask(".Task3"));
+ mTasks.add(createTask(".Task4"));
+ mTasks.add(createTask(".Task5"));
+
+ mSameDocumentTasks.add(createDocumentTask(".DocumentTask1", null /* affinity */));
+ mSameDocumentTasks.add(createDocumentTask(".DocumentTask1", null /* affinity */));
+ }
+
+ @Test
+ public void testCallbacks() throws Exception {
+ // Add some tasks
+ mRecentTasks.add(mTasks.get(0));
+ mRecentTasks.add(mTasks.get(1));
+ assertTrue(mCallbacksRecorder.added.contains(mTasks.get(0))
+ && mCallbacksRecorder.added.contains(mTasks.get(1)));
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.isEmpty());
+ mCallbacksRecorder.clear();
+
+ // Remove some tasks
+ mRecentTasks.remove(mTasks.get(0));
+ mRecentTasks.remove(mTasks.get(1));
+ assertTrue(mCallbacksRecorder.added.isEmpty());
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.contains(mTasks.get(0)));
+ assertTrue(mCallbacksRecorder.removed.contains(mTasks.get(1)));
+ mCallbacksRecorder.clear();
+
+ // Add a task which will trigger the trimming of another
+ TaskRecord documentTask1 = createDocumentTask(".DocumentTask1", null /* affinity */);
+ documentTask1.maxRecents = 1;
+ TaskRecord documentTask2 = createDocumentTask(".DocumentTask1", null /* affinity */);
+ mRecentTasks.add(documentTask1);
+ mRecentTasks.add(documentTask2);
+ assertTrue(mCallbacksRecorder.added.contains(documentTask1));
+ assertTrue(mCallbacksRecorder.added.contains(documentTask2));
+ assertTrue(mCallbacksRecorder.trimmed.contains(documentTask1));
+ assertTrue(mCallbacksRecorder.removed.contains(documentTask1));
+ mCallbacksRecorder.clear();
+
+ // Remove the callback, ensure we don't get any calls
+ mRecentTasks.unregisterCallback(mCallbacksRecorder);
+ mRecentTasks.add(mTasks.get(0));
+ mRecentTasks.remove(mTasks.get(0));
+ assertTrue(mCallbacksRecorder.added.isEmpty());
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.isEmpty());
+ }
+
+ @Test
+ public void testUsersTasks() throws Exception {
+ // Setup some tasks for the users
+ mTaskPersister.userTaskIdsOverride = new SparseBooleanArray();
+ mTaskPersister.userTaskIdsOverride.put(1, true);
+ mTaskPersister.userTaskIdsOverride.put(2, true);
+ mTaskPersister.userTasksOverride = new ArrayList<>();
+ mTaskPersister.userTasksOverride.add(createTask(".UserTask1"));
+ mTaskPersister.userTasksOverride.add(createTask(".UserTask2"));
+
+ // Assert no user tasks are initially loaded
+ assertTrue(mRecentTasks.usersWithRecentsLoadedLocked().length == 0);
+
+ // Load user 0 tasks
+ mRecentTasks.loadUserRecentsLocked(TEST_USER_0_ID);
+ assertTrue(arrayContainsUser(mRecentTasks.usersWithRecentsLoadedLocked(), TEST_USER_0_ID));
+ assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_0_ID));
+ assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_0_ID));
+
+ // Load user 1 tasks
+ mRecentTasks.loadUserRecentsLocked(TEST_USER_1_ID);
+ assertTrue(arrayContainsUser(mRecentTasks.usersWithRecentsLoadedLocked(), TEST_USER_0_ID));
+ assertTrue(arrayContainsUser(mRecentTasks.usersWithRecentsLoadedLocked(), TEST_USER_1_ID));
+ assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_0_ID));
+ assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_0_ID));
+ assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_1_ID));
+ assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_1_ID));
+
+ // Unload user 1 tasks
+ mRecentTasks.unloadUserDataFromMemoryLocked(TEST_USER_1_ID);
+ assertTrue(arrayContainsUser(mRecentTasks.usersWithRecentsLoadedLocked(), TEST_USER_0_ID));
+ assertFalse(arrayContainsUser(mRecentTasks.usersWithRecentsLoadedLocked(), TEST_USER_1_ID));
+ assertTrue(mRecentTasks.containsTaskId(1, TEST_USER_0_ID));
+ assertTrue(mRecentTasks.containsTaskId(2, TEST_USER_0_ID));
+
+ // Unload user 0 tasks
+ mRecentTasks.unloadUserDataFromMemoryLocked(TEST_USER_0_ID);
+ assertFalse(arrayContainsUser(mRecentTasks.usersWithRecentsLoadedLocked(), TEST_USER_0_ID));
+ assertFalse(arrayContainsUser(mRecentTasks.usersWithRecentsLoadedLocked(), TEST_USER_1_ID));
+ }
+
+ @Test
+ public void testOrderedIteration() throws Exception {
+ MutableLong prevLastActiveTime = new MutableLong(0);
+ final ArrayList<TaskRecord> tasks = mRecentTasks.getRawTasks();
+ for (int i = 0; i < tasks.size(); i++) {
+ final TaskRecord task = tasks.get(i);
+ assertTrue(task.lastActiveTime >= prevLastActiveTime.value);
+ prevLastActiveTime.value = task.lastActiveTime;
+ }
+ }
+
+ @Test
+ public void testTrimToGlobalMaxNumRecents() throws Exception {
+ // Limit the global maximum number of recent tasks to a fixed size
+ mRecentTasks.setGlobalMaxNumTasks(2 /* globalMaxNumTasks */);
+
+ // Add N+1 tasks
+ mRecentTasks.add(mTasks.get(0));
+ mRecentTasks.add(mTasks.get(1));
+ mRecentTasks.add(mTasks.get(2));
+
+ // Ensure that the last task was trimmed as an inactive task
+ assertTrimmed(mTasks.get(0));
+ }
+
+ @Test
+ public void testTrimQuietProfileTasks() throws Exception {
+ TaskRecord qt1 = createTask(".QuietTask1", TEST_QUIET_USER_ID);
+ TaskRecord qt2 = createTask(".QuietTask2", TEST_QUIET_USER_ID);
+ mRecentTasks.add(qt1);
+ mRecentTasks.add(qt2);
+
+ mRecentTasks.add(mTasks.get(0));
+ mRecentTasks.add(mTasks.get(1));
+
+ // Ensure that the quiet user's tasks was trimmed once the new tasks were added
+ assertTrimmed(qt1, qt2);
+ }
+
+ @Test
+ public void testSessionDuration() throws Exception {
+ mRecentTasks.setParameters(-1 /* min */, -1 /* max */, 50 /* ms */);
+
+ TaskRecord t1 = createTask(".Task1");
+ t1.touchActiveTime();
+ mRecentTasks.add(t1);
+
+ // Force a small sleep just beyond the session duration
+ SystemClock.sleep(75);
+
+ TaskRecord t2 = createTask(".Task2");
+ t2.touchActiveTime();
+ mRecentTasks.add(t2);
+
+ // Assert that the old task has been removed due to being out of the active session
+ assertTrimmed(t1);
+ }
+
+ @Test
+ public void testVisibleTasks_excludedFromRecents() throws Exception {
+ mRecentTasks.setParameters(-1 /* min */, 4 /* max */, -1 /* ms */);
+
+ TaskRecord excludedTask1 = createTask(".ExcludedTask1", FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,
+ TEST_USER_0_ID);
+ TaskRecord excludedTask2 = createTask(".ExcludedTask2", FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,
+ TEST_USER_0_ID);
+
+ mRecentTasks.add(excludedTask1);
+ mRecentTasks.add(mTasks.get(0));
+ mRecentTasks.add(mTasks.get(1));
+ mRecentTasks.add(mTasks.get(2));
+ mRecentTasks.add(excludedTask2);
+
+ // The last excluded task should be trimmed, while the first-most excluded task should not
+ assertTrimmed(excludedTask1);
+ }
+
+ @Test
+ public void testVisibleTasks_minNum() throws Exception {
+ mRecentTasks.setParameters(5 /* min */, -1 /* max */, 25 /* ms */);
+
+ for (int i = 0; i < 4; i++) {
+ final TaskRecord task = mTasks.get(i);
+ task.touchActiveTime();
+ mRecentTasks.add(task);
+ }
+
+ // Force a small sleep just beyond the session duration
+ SystemClock.sleep(50);
+
+ // Add a new task to trigger tasks to be trimmed
+ mRecentTasks.add(mTasks.get(4));
+
+ // Ensure that there are a minimum number of tasks regardless of session length
+ assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+ assertTrue(mCallbacksRecorder.removed.isEmpty());
+ }
+
+ @Test
+ public void testVisibleTasks_maxNum() throws Exception {
+ mRecentTasks.setParameters(-1 /* min */, 3 /* max */, -1 /* ms */);
+
+ for (int i = 0; i < 5; i++) {
+ final TaskRecord task = mTasks.get(i);
+ task.touchActiveTime();
+ mRecentTasks.add(task);
+ }
+
+ // Ensure that only the last number of max tasks are kept
+ assertTrimmed(mTasks.get(0), mTasks.get(1));
+ }
+
+ private ComponentName createComponent(String className) {
+ return new ComponentName(mContext.getPackageName(), className);
+ }
+
+ private TaskRecord createTask(String className) {
+ return createTask(className, TEST_USER_0_ID);
+ }
+
+ private TaskRecord createTask(String className, int userId) {
+ return createTask(className, 0 /* flags */, userId);
+ }
+
+ private TaskRecord createTask(String className, int flags, int userId) {
+ TaskRecord task = createTask(mService.mStackSupervisor, createComponent(className), flags,
+ LAST_TASK_ID++, mStack);
+ task.userId = userId;
+ task.touchActiveTime();
+ return task;
+ }
+
+ private TaskRecord createDocumentTask(String className, String affinity) {
+ TaskRecord task = createTask(className, FLAG_ACTIVITY_NEW_DOCUMENT, TEST_USER_0_ID);
+ task.affinity = affinity;
+ return task;
+ }
+
+ private boolean arrayContainsUser(int[] userIds, int targetUserId) {
+ Arrays.sort(userIds);
+ return Arrays.binarySearch(userIds, targetUserId) >= 0;
+ }
+
+ private void assertTrimmed(TaskRecord... tasks) {
+ final ArrayList<TaskRecord> trimmed = mCallbacksRecorder.trimmed;
+ final ArrayList<TaskRecord> removed = mCallbacksRecorder.removed;
+ assertTrue("Expected " + tasks.length + " trimmed tasks, got " + trimmed.size(),
+ trimmed.size() == tasks.length);
+ assertTrue("Expected " + tasks.length + " removed tasks, got " + removed.size(),
+ removed.size() == tasks.length);
+ for (TaskRecord task : tasks) {
+ assertTrue("Expected trimmed task: " + task, trimmed.contains(task));
+ assertTrue("Expected removed task: " + task, removed.contains(task));
+ }
+ }
+
+ private static class CallbacksRecorder implements Callbacks {
+ ArrayList<TaskRecord> added = new ArrayList<>();
+ ArrayList<TaskRecord> trimmed = new ArrayList<>();
+ ArrayList<TaskRecord> removed = new ArrayList<>();
+
+ void clear() {
+ added.clear();
+ trimmed.clear();
+ removed.clear();
+ }
+
+ @Override
+ public void onRecentTaskAdded(TaskRecord task) {
+ added.add(task);
+ }
+
+ @Override
+ public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed) {
+ if (wasTrimmed) {
+ trimmed.add(task);
+ }
+ removed.add(task);
+ }
+ }
+
+ private static class TestTaskPersister extends TaskPersister {
+
+ SparseBooleanArray userTaskIdsOverride;
+ ArrayList<TaskRecord> userTasksOverride;
+
+ TestTaskPersister(File workingDir) {
+ super(workingDir);
+ }
+
+ @Override
+ SparseBooleanArray loadPersistedTaskIdsForUser(int userId) {
+ if (userTaskIdsOverride != null) {
+ return userTaskIdsOverride;
+ }
+ return super.loadPersistedTaskIdsForUser(userId);
+ }
+
+ @Override
+ List<TaskRecord> restoreTasksForUserLocked(int userId, SparseBooleanArray preaddedTasks) {
+ if (userTasksOverride != null) {
+ return userTasksOverride;
+ }
+ return super.restoreTasksForUserLocked(userId, preaddedTasks);
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index f4c4ea9..1bb93cc 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -247,6 +247,26 @@
assertEquals(7, updates.size());
}
+ public void testUpdatesReceived_queueEmptyAfterStartListening() {
+ int widgetId = setupHostAndWidget();
+ int widgetId2 = bindNewWidget();
+ mService.stopListening(mPkgName, HOST_ID);
+
+ sendDummyUpdates(widgetId, 22, 23);
+ sendDummyUpdates(widgetId2, 100, 101, 102);
+
+ List<PendingHostUpdate> updates = mService.startListening(
+ mMockHost, mPkgName, HOST_ID, new int[]{widgetId, widgetId2}).getList();
+ // 3 updates for first widget and 4 for second
+ assertEquals(7, updates.size());
+
+ // Stop and start listening again
+ mService.stopListening(mPkgName, HOST_ID);
+ updates = mService.startListening(
+ mMockHost, mPkgName, HOST_ID, new int[]{widgetId, widgetId2}).getList();
+ assertTrue(updates.isEmpty());
+ }
+
public void testGetInstalledProvidersForPackage() {
List<AppWidgetProviderInfo> allProviders = mManager.getInstalledProviders();
assertTrue(!allProviders.isEmpty());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 951f226..d017976 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -15,6 +15,11 @@
*/
package com.android.server.pm;
+import static android.content.pm.ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED;
+import static android.content.pm.ShortcutInfo.DISABLED_REASON_NOT_DISABLED;
+import static android.content.pm.ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH;
+import static android.content.pm.ShortcutInfo.DISABLED_REASON_VERSION_LOWER;
+
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.anyOrNull;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.anyStringOrNull;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDisabled;
@@ -71,7 +76,9 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.PinItemRequest;
import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
@@ -101,7 +108,6 @@
import java.util.List;
import java.util.Locale;
import java.util.function.BiConsumer;
-import java.util.function.BiPredicate;
/**
* Tests for ShortcutService and ShortcutManager.
@@ -250,7 +256,7 @@
final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.icon2));
final Icon icon3 = Icon.createWithAdaptiveBitmap(BitmapFactory.decodeResource(
- getTestContext().getResources(), R.drawable.icon2));
+ getTestContext().getResources(), R.drawable.icon2));
final ShortcutInfo si1 = makeShortcut(
"shortcut1",
@@ -706,13 +712,13 @@
assertBitmapSize(128, 128, bmp);
Drawable dr = mLauncherApps.getShortcutIconDrawable(
- makeShortcutWithIcon("bmp64x64", bmp64x64_maskable), 0);
+ makeShortcutWithIcon("bmp64x64", bmp64x64_maskable), 0);
assertTrue(dr instanceof AdaptiveIconDrawable);
float viewportPercentage = 1 / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
assertEquals((int) (bmp64x64_maskable.getBitmap().getWidth() * viewportPercentage),
- dr.getIntrinsicWidth());
+ dr.getIntrinsicWidth());
assertEquals((int) (bmp64x64_maskable.getBitmap().getHeight() * viewportPercentage),
- dr.getIntrinsicHeight());
+ dr.getIntrinsicHeight());
}
public void testCleanupDanglingBitmaps() throws Exception {
@@ -1118,8 +1124,8 @@
// Set resource icon
assertTrue(mManager.updateShortcuts(list(
new ShortcutInfo.Builder(mClientContext, "s1")
- .setIcon(Icon.createWithResource(getTestContext(), R.drawable.black_32x32))
- .build()
+ .setIcon(Icon.createWithResource(getTestContext(), R.drawable.black_32x32))
+ .build()
)));
assertWith(getCallerShortcuts())
@@ -1131,9 +1137,9 @@
// Set bitmap icon
assertTrue(mManager.updateShortcuts(list(
new ShortcutInfo.Builder(mClientContext, "s1")
- .setIcon(Icon.createWithBitmap(BitmapFactory.decodeResource(
- getTestContext().getResources(), R.drawable.black_64x64)))
- .build()
+ .setIcon(Icon.createWithBitmap(BitmapFactory.decodeResource(
+ getTestContext().getResources(), R.drawable.black_64x64)))
+ .build()
)));
assertWith(getCallerShortcuts())
@@ -2126,7 +2132,7 @@
final ShortcutQuery q = new ShortcutQuery().setQueryFlags(
ShortcutQuery.FLAG_MATCH_DYNAMIC | ShortcutQuery.FLAG_MATCH_PINNED
- | ShortcutQuery.FLAG_MATCH_MANIFEST);
+ | ShortcutQuery.FLAG_MATCH_MANIFEST);
// No shortcuts are visible.
assertWith(mLauncherApps.getShortcuts(q, HANDLE_USER_0)).isEmpty();
@@ -2668,10 +2674,10 @@
"Title 1",
makeComponent(ShortcutActivity.class),
/* icon =*/ null,
- new Intent[] {makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+ new Intent[]{makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123))
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK),
- new Intent("act2").setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)},
+ new Intent("act2").setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)},
/* rank */ 10);
final ShortcutInfo s1_2 = makeShortcut(
@@ -2776,8 +2782,8 @@
// Not launchable.
doReturn(ActivityManager.START_CLASS_NOT_FOUND)
.when(mMockActivityManagerInternal).startActivitiesAsPackage(
- anyStringOrNull(), anyInt(),
- anyOrNull(Intent[].class), anyOrNull(Bundle.class));
+ anyStringOrNull(), anyInt(),
+ anyOrNull(Intent[].class), anyOrNull(Bundle.class));
assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_0,
ActivityNotFoundException.class);
@@ -2911,7 +2917,7 @@
.revertToOriginalList()
.selectByIds("s1", "s2")
.areAllDynamic()
- ;
+ ;
});
// 3 Update the app with no manifest shortcuts. (Pinned one will survive.)
@@ -3309,13 +3315,13 @@
});
- final SparseArray<ShortcutUser> users = mService.getShortcutsForTest();
+ final SparseArray<ShortcutUser> users = mService.getShortcutsForTest();
assertEquals(2, users.size());
assertEquals(USER_0, users.keyAt(0));
assertEquals(USER_10, users.keyAt(1));
- final ShortcutUser user0 = users.get(USER_0);
- final ShortcutUser user10 = users.get(USER_10);
+ final ShortcutUser user0 = users.get(USER_0);
+ final ShortcutUser user10 = users.get(USER_10);
// Check the registered packages.
@@ -3531,7 +3537,7 @@
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -3548,7 +3554,7 @@
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -3853,52 +3859,77 @@
assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
}
- protected void checkCanRestoreTo(boolean expected, ShortcutPackageInfo spi,
- int version, String... signatures) {
- assertEquals(expected, spi.canRestoreTo(mService, genPackage(
- "dummy", /* uid */ 0, version, signatures)));
+ protected void checkCanRestoreTo(int expected, ShortcutPackageInfo spi,
+ boolean anyVersionOk, int version, boolean nowBackupAllowed, String... signatures) {
+ final PackageInfo pi = genPackage("dummy", /* uid */ 0, version, signatures);
+ if (!nowBackupAllowed) {
+ pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP;
+ }
+ assertEquals(expected, spi.canRestoreTo(mService, pi, anyVersionOk));
}
public void testCanRestoreTo() {
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "sig1");
- addPackage(CALLING_PACKAGE_2, CALLING_UID_1, 10, "sig1", "sig2");
+ addPackage(CALLING_PACKAGE_2, CALLING_UID_2, 10, "sig1", "sig2");
+ addPackage(CALLING_PACKAGE_3, CALLING_UID_3, 10, "sig1");
+
+ updatePackageInfo(CALLING_PACKAGE_3,
+ pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
final ShortcutPackageInfo spi1 = ShortcutPackageInfo.generateForInstalledPackageForTest(
mService, CALLING_PACKAGE_1, USER_0);
final ShortcutPackageInfo spi2 = ShortcutPackageInfo.generateForInstalledPackageForTest(
mService, CALLING_PACKAGE_2, USER_0);
+ final ShortcutPackageInfo spi3 = ShortcutPackageInfo.generateForInstalledPackageForTest(
+ mService, CALLING_PACKAGE_3, USER_0);
- checkCanRestoreTo(true, spi1, 10, "sig1");
- checkCanRestoreTo(true, spi1, 10, "x", "sig1");
- checkCanRestoreTo(true, spi1, 10, "sig1", "y");
- checkCanRestoreTo(true, spi1, 10, "x", "sig1", "y");
- checkCanRestoreTo(true, spi1, 11, "sig1");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, false, 10, true, "sig1");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, false, 10, true, "x", "sig1");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, false, 10, true, "sig1", "y");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, false, 10, true, "x", "sig1", "y");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, false, 11, true, "sig1");
- checkCanRestoreTo(false, spi1, 10 /* empty */);
- checkCanRestoreTo(false, spi1, 10, "x");
- checkCanRestoreTo(false, spi1, 10, "x", "y");
- checkCanRestoreTo(false, spi1, 10, "x");
- checkCanRestoreTo(false, spi1, 9, "sig1");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH, spi1, false, 10, true/* empty */);
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH, spi1, false, 10, true, "x");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH, spi1, false, 10, true, "x", "y");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH, spi1, false, 10, true, "x");
+ checkCanRestoreTo(DISABLED_REASON_VERSION_LOWER, spi1, false, 9, true, "sig1");
- checkCanRestoreTo(true, spi2, 10, "sig1", "sig2");
- checkCanRestoreTo(true, spi2, 10, "sig2", "sig1");
- checkCanRestoreTo(true, spi2, 10, "x", "sig1", "sig2");
- checkCanRestoreTo(true, spi2, 10, "x", "sig2", "sig1");
- checkCanRestoreTo(true, spi2, 10, "sig1", "sig2", "y");
- checkCanRestoreTo(true, spi2, 10, "sig2", "sig1", "y");
- checkCanRestoreTo(true, spi2, 10, "x", "sig1", "sig2", "y");
- checkCanRestoreTo(true, spi2, 10, "x", "sig2", "sig1", "y");
- checkCanRestoreTo(true, spi2, 11, "x", "sig2", "sig1", "y");
+ // Any version okay.
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, true, 9, true, "sig1");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, true, 9, true, "sig1");
- checkCanRestoreTo(false, spi2, 10, "sig1", "sig2x");
- checkCanRestoreTo(false, spi2, 10, "sig2", "sig1x");
- checkCanRestoreTo(false, spi2, 10, "x", "sig1x", "sig2");
- checkCanRestoreTo(false, spi2, 10, "x", "sig2x", "sig1");
- checkCanRestoreTo(false, spi2, 10, "sig1", "sig2x", "y");
- checkCanRestoreTo(false, spi2, 10, "sig2", "sig1x", "y");
- checkCanRestoreTo(false, spi2, 10, "x", "sig1x", "sig2", "y");
- checkCanRestoreTo(false, spi2, 10, "x", "sig2x", "sig1", "y");
- checkCanRestoreTo(false, spi2, 11, "x", "sig2x", "sig1", "y");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 10, true, "sig1", "sig2");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 10, true, "sig2", "sig1");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 10, true, "x", "sig1", "sig2");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 10, true, "x", "sig2", "sig1");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 10, true, "sig1", "sig2", "y");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 10, true, "sig2", "sig1", "y");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 10, true, "x", "sig1", "sig2", "y");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 10, true, "x", "sig2", "sig1", "y");
+ checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi2, false, 11, true, "x", "sig2", "sig1", "y");
+
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 10, true, "sig1", "sig2x");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 10, true, "sig2", "sig1x");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 10, true, "x", "sig1x", "sig2");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 10, true, "x", "sig2x", "sig1");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 10, true, "sig1", "sig2x", "y");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 10, true, "sig2", "sig1x", "y");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 10, true, "x", "sig1x", "sig2", "y");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 10, true, "x", "sig2x", "sig1", "y");
+ checkCanRestoreTo(DISABLED_REASON_SIGNATURE_MISMATCH,
+ spi2, false, 11, true, "x", "sig2x", "sig1", "y");
+
+ checkCanRestoreTo(DISABLED_REASON_BACKUP_NOT_SUPPORTED, spi1, true, 10, false, "sig1");
+ checkCanRestoreTo(DISABLED_REASON_BACKUP_NOT_SUPPORTED, spi3, true, 10, true, "sig1");
}
public void testHandlePackageDelete() {
@@ -3929,7 +3960,7 @@
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertWith(getCallerShortcuts())
@@ -4080,7 +4111,7 @@
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDataClear(CALLING_PACKAGE_1, USER_0));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -4099,7 +4130,7 @@
mRunningUsers.put(USER_10, true);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDataClear(CALLING_PACKAGE_2, USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -4126,7 +4157,7 @@
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4389,7 +4420,7 @@
// Update the package.
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -4524,7 +4555,7 @@
mRunningUsers.put(USER_10, true);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4552,11 +4583,11 @@
.revertToOriginalList()
.selectByIds("ms1-alt", "s2")
.areAllWithActivity(ACTIVITY2)
- ;
+ ;
});
// First, no changes.
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4579,7 +4610,7 @@
// Disable activity 1
mEnabledActivityChecker = (activity, userId) -> !ACTIVITY1.equals(activity);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4599,7 +4630,7 @@
// Re-enable activity 1.
// Manifest shortcuts will be re-published, but dynamic ones are not.
mEnabledActivityChecker = (activity, userId) -> true;
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4617,13 +4648,13 @@
.revertToOriginalList()
.selectByIds("ms1-alt", "s2")
.areAllWithActivity(ACTIVITY2)
- ;
+ ;
});
// Disable activity 2
// Because "ms1-alt" and "s2" are both pinned, they will remain, but disabled.
mEnabledActivityChecker = (activity, userId) -> !ACTIVITY2.equals(activity);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4686,7 +4717,7 @@
setCaller(LAUNCHER_1, USER_0);
assertForLauncherCallback(mLauncherApps, () -> {
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
}).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
// Make sure the launcher gets callbacks.
@@ -4708,12 +4739,11 @@
.areAllNotDynamic()
.areAllDisabled()
.areAllPinned()
- ;
+ ;
});
}
protected void prepareForBackupTest() {
-
prepareCrossProfileDataSet();
backupAndRestore();
@@ -4749,66 +4779,45 @@
assertFileExistsWithContent("user-0/shortcut_dump/restore-4.txt");
assertFileExistsWithContent("user-0/shortcut_dump/restore-5-finish.txt");
- checkBackupAndRestore_success();
+ checkBackupAndRestore_success(/*firstRestore=*/ true);
}
public void testBackupAndRestore_backupRestoreTwice() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- dumpsysOnLogcat("Before second backup");
+ checkBackupAndRestore_success(/*firstRestore=*/ true);
+
+ // Run a backup&restore again. Note the shortcuts that weren't restored in the previous
+ // restore are disabled, so they won't be restored again.
+ dumpsysOnLogcat("Before second backup&restore");
backupAndRestore();
- dumpsysOnLogcat("After second backup");
+ dumpsysOnLogcat("After second backup&restore");
- checkBackupAndRestore_success();
- }
-
- public void testBackupAndRestore_backupRestoreMultiple() {
- prepareForBackupTest();
-
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
- // This also shouldn't affect the result.
- runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertTrue(mManager.setDynamicShortcuts(list(
- makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
- makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
- });
-
- backupAndRestore();
-
- checkBackupAndRestore_success();
+ checkBackupAndRestore_success(/*firstRestore=*/ false);
}
public void testBackupAndRestore_restoreToNewVersion() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 2);
addPackage(LAUNCHER_1, LAUNCHER_UID_1, 5);
- checkBackupAndRestore_success();
+ checkBackupAndRestore_success(/*firstRestore=*/ true);
}
public void testBackupAndRestore_restoreToSuperSetSignatures() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
// Change package signatures.
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 1, "sigx", CALLING_PACKAGE_1);
addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4, LAUNCHER_1, "sigy");
- checkBackupAndRestore_success();
+ checkBackupAndRestore_success(/*firstRestore=*/ true);
}
- protected void checkBackupAndRestore_success() {
+ protected void checkBackupAndRestore_success(boolean firstRestore) {
// Make sure non-system user is not restored.
final ShortcutUser userP0 = mService.getUserShortcutsLocked(USER_P0);
assertEquals(0, userP0.getAllPackagesForTest().size());
@@ -4818,12 +4827,13 @@
final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
+
+ assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
assertExistsAndShadow(user0.getAllLaunchersForTest().get(
PackageWithUser.of(USER_0, LAUNCHER_1)));
assertExistsAndShadow(user0.getAllLaunchersForTest().get(
PackageWithUser.of(USER_0, LAUNCHER_2)));
- assertNull(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_P0, LAUNCHER_1)));
@@ -4835,14 +4845,16 @@
.revertToOriginalList()
.selectPinned()
- .haveIds("s1", "s2");
+ .haveIds("s1", "s2")
+ .areAllEnabled();
});
installPackage(USER_0, LAUNCHER_1);
runWithCaller(LAUNCHER_1, USER_0, () -> {
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
.areAllPinned()
- .haveIds("s1");
+ .haveIds("s1")
+ .areAllEnabled();
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
.isEmpty();
@@ -4862,17 +4874,20 @@
.revertToOriginalList()
.selectPinned()
- .haveIds("s1", "s2", "s3");
+ .haveIds("s1", "s2", "s3")
+ .areAllEnabled();
});
runWithCaller(LAUNCHER_1, USER_0, () -> {
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
.areAllPinned()
- .haveIds("s1");
+ .haveIds("s1")
+ .areAllEnabled();
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
.areAllPinned()
- .haveIds("s1", "s2");
+ .haveIds("s1", "s2")
+ .areAllEnabled();
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
.isEmpty();
@@ -4910,14 +4925,28 @@
runWithCaller(LAUNCHER_2, USER_0, () -> {
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
.areAllPinned()
- .haveIds("s2");
+ .haveIds("s2")
+ .areAllEnabled();
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
.areAllPinned()
- .haveIds("s2", "s3");
+ .haveIds("s2", "s3")
+ .areAllEnabled();
- assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- .isEmpty();
+ if (firstRestore) {
+ assertWith(
+ mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .haveIds("s2", "s3", "s4")
+ .areAllDisabled()
+ .areAllPinned()
+ .areAllNotDynamic()
+ .areAllWithDisabledReason(
+ ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
+ } else {
+ assertWith(
+ mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
+ }
assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
.isEmpty();
@@ -4937,14 +4966,27 @@
runWithCaller(LAUNCHER_1, USER_0, () -> {
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
.areAllPinned()
- .haveIds("s1");
+ .haveIds("s1")
+ .areAllEnabled();
assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
.areAllPinned()
- .haveIds("s1", "s2");
+ .haveIds("s1", "s2")
+ .areAllEnabled();
- assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- .isEmpty();
+ if (firstRestore) {
+ assertWith(
+ mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .haveIds("s1", "s2", "s3")
+ .areAllDisabled()
+ .areAllPinned()
+ .areAllNotDynamic()
+ .areAllWithDisabledReason(ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
+ } else {
+ assertWith(
+ mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
+ }
assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
.isEmpty();
@@ -4954,45 +4996,39 @@
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
assertWith(getCallerVisibleShortcuts())
.areAllPinned()
- .haveIds("s1", "s2", "s3");
+ .haveIds("s1", "s2", "s3")
+ .areAllEnabled();
});
}
public void testBackupAndRestore_publisherLowerVersion() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 0); // Lower version
- checkBackupAndRestore_publisherNotRestored();
+ checkBackupAndRestore_publisherNotRestored(ShortcutInfo.DISABLED_REASON_VERSION_LOWER);
}
public void testBackupAndRestore_publisherWrongSignature() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "sigx"); // different signature
- checkBackupAndRestore_publisherNotRestored();
+ checkBackupAndRestore_publisherNotRestored(ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH);
}
public void testBackupAndRestore_publisherNoLongerBackupTarget() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
updatePackageInfo(CALLING_PACKAGE_1,
pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
- checkBackupAndRestore_publisherNotRestored();
+ checkBackupAndRestore_publisherNotRestored(
+ ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
}
- protected void checkBackupAndRestore_publisherNotRestored() {
+ protected void checkBackupAndRestore_publisherNotRestored(
+ int package1DisabledReason) {
installPackage(USER_0, CALLING_PACKAGE_1);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(0, mManager.getDynamicShortcuts().size());
@@ -5014,27 +5050,31 @@
installPackage(USER_0, LAUNCHER_1);
runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
- /* empty */);
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s1", "s2");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty */);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .haveIds("s1")
+ .areAllPinned()
+ .areAllDisabled()
+ .areAllWithDisabledReason(package1DisabledReason);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .haveIds("s1", "s2")
+ .areAllPinned()
+ .areAllEnabled();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
});
installPackage(USER_0, LAUNCHER_2);
runWithCaller(LAUNCHER_2, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
- /* empty */);
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s2", "s3");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty */);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .haveIds("s2")
+ .areAllPinned()
+ .areAllDisabled()
+ .areAllWithDisabledReason(package1DisabledReason);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .haveIds("s2", "s3")
+ .areAllPinned()
+ .areAllEnabled();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
});
installPackage(USER_0, CALLING_PACKAGE_3);
@@ -5044,46 +5084,51 @@
});
runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
- /* empty */);
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s1", "s2");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty */);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .haveIds("s1")
+ .areAllPinned()
+ .areAllDisabled()
+ .areAllWithDisabledReason(package1DisabledReason);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .haveIds("s1", "s2")
+ .areAllPinned()
+ .areAllEnabled();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .haveIds("s1", "s2", "s3")
+ .areAllPinned()
+ .areAllDisabled()
+ .areAllWithDisabledReason(ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
});
runWithCaller(LAUNCHER_2, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
- /* empty */);
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s2", "s3");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty */);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .haveIds("s2")
+ .areAllPinned()
+ .areAllDisabled()
+ .areAllWithDisabledReason(package1DisabledReason);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .haveIds("s2", "s3")
+ .areAllPinned()
+ .areAllEnabled();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .haveIds("s2", "s3", "s4")
+ .areAllPinned()
+ .areAllDisabled()
+ .areAllWithDisabledReason(ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
});
}
public void testBackupAndRestore_launcherLowerVersion() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
addPackage(LAUNCHER_1, LAUNCHER_UID_1, 0); // Lower version
- checkBackupAndRestore_launcherNotRestored();
+ // Note, we restore pinned shortcuts even if the launcher is of a lower version.
+ checkBackupAndRestore_success(/*firstRestore=*/ true);
}
public void testBackupAndRestore_launcherWrongSignature() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
addPackage(LAUNCHER_1, LAUNCHER_UID_1, 10, "sigx"); // different signature
checkBackupAndRestore_launcherNotRestored();
@@ -5092,9 +5137,6 @@
public void testBackupAndRestore_launcherNoLongerBackupTarget() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
updatePackageInfo(LAUNCHER_1,
pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
@@ -5185,18 +5227,12 @@
assertShortcutIds(assertAllPinned(
mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
"s2", "s3");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty */);
});
}
public void testBackupAndRestore_launcherAndPackageNoLongerBackupTarget() {
prepareForBackupTest();
- // Note doing a backup & restore again here shouldn't affect the result.
- backupAndRestore();
-
updatePackageInfo(CALLING_PACKAGE_1,
pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
@@ -5235,15 +5271,15 @@
});
installPackage(USER_0, LAUNCHER_2);
runWithCaller(LAUNCHER_2, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
- /* empty */);
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s2", "s3");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty */);
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s2")
+ .areAllDisabled();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s2", "s3");
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
});
// Because launcher 1 wasn't restored, "s1" is no longer pinned.
@@ -5272,15 +5308,21 @@
/* empty */);
});
runWithCaller(LAUNCHER_2, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
- /* empty */);
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s2", "s3");
- assertShortcutIds(assertAllPinned(
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s2")
+ .areAllDisabled();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s2", "s3");
+ assertWith(
mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty */);
+ .haveIds("s2", "s3", "s4")
+ .areAllDisabled()
+ .areAllPinned()
+ .areAllNotDynamic()
+ .areAllWithDisabledReason(
+ ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
});
}
@@ -5305,12 +5347,12 @@
final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
+ assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
assertExistsAndShadow(user0.getAllLaunchersForTest().get(
PackageWithUser.of(USER_0, LAUNCHER_1)));
assertExistsAndShadow(user0.getAllLaunchersForTest().get(
PackageWithUser.of(USER_0, LAUNCHER_2)));
- assertNull(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_P0, LAUNCHER_1)));
@@ -5421,7 +5463,7 @@
.revertToOriginalList()
.selectByIds("s1", "s2")
.areAllNotDynamic()
- ;
+ ;
});
}
@@ -5555,6 +5597,287 @@
});
}
+
+ /**
+ * Restored to a lower version with no manifest shortcuts. All shortcuts are now invisible,
+ * and all calls from the publisher should ignore them.
+ */
+ public void testBackupAndRestore_disabledShortcutsAreIgnored() {
+ // Publish two manifest shortcuts.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_5_altalt);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(mServiceContext,
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcutWithShortLabel("s1", "original-title"),
+ makeShortcut("s2"), makeShortcut("s3"))));
+ });
+
+ // Pin from launcher 1.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+ list("ms1", "ms2", "ms3", "ms4", "s1", "s2"), HANDLE_USER_0);
+ });
+
+ backupAndRestore();
+
+ // Lower the version and remove the manifest shortcuts.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_0);
+ addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 0); // Lower version
+
+ // When re-installing the app, the manifest shortcut should be re-published.
+ mService.mPackageMonitor.onReceive(mServiceContext,
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+ mService.mPackageMonitor.onReceive(mServiceContext,
+ genPackageAddIntent(LAUNCHER_1, USER_0));
+
+ // No shortcuts should be visible to the publisher.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerVisibleShortcuts())
+ .isEmpty();
+ });
+
+ final Runnable checkAllDisabledForLauncher = () -> {
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertWith(getShortcutAsLauncher(USER_0))
+ .areAllPinned()
+ .haveIds("ms1", "ms2", "ms3", "ms4", "s1", "s2")
+ .areAllDisabled()
+ .areAllWithDisabledReason(ShortcutInfo.DISABLED_REASON_VERSION_LOWER)
+
+ .forShortcutWithId("s1", si -> {
+ assertEquals("original-title", si.getShortLabel());
+ })
+ .forShortcutWithId("ms1", si -> {
+ assertEquals("string-com.android.test.1-user:0-res:"
+ + R.string.shortcut_title1 + "/en"
+ , si.getShortLabel());
+ })
+ .forShortcutWithId("ms2", si -> {
+ assertEquals("string-com.android.test.1-user:0-res:"
+ + R.string.shortcut_title2 + "/en"
+ , si.getShortLabel());
+ })
+ .forShortcutWithId("ms3", si -> {
+ assertEquals("string-com.android.test.1-user:0-res:"
+ + R.string.shortcut_title1 + "/en"
+ , si.getShortLabel());
+ assertEquals("string-com.android.test.1-user:0-res:"
+ + R.string.shortcut_title2 + "/en"
+ , si.getLongLabel());
+ })
+ .forShortcutWithId("ms4", si -> {
+ assertEquals("string-com.android.test.1-user:0-res:"
+ + R.string.shortcut_title2 + "/en"
+ , si.getShortLabel());
+ assertEquals("string-com.android.test.1-user:0-res:"
+ + R.string.shortcut_title2 + "/en"
+ , si.getLongLabel());
+ });
+ });
+ };
+
+ checkAllDisabledForLauncher.run();
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+
+ makeCallerForeground(); // CALLING_PACKAGE_1 is now in the foreground.
+
+ // All changing API calls should be ignored.
+
+ getManager().enableShortcuts(list("ms1", "ms2", "ms3", "ms4", "s1", "s2"));
+ checkAllDisabledForLauncher.run();
+
+ getManager().enableShortcuts(list("ms1", "ms2", "ms3", "ms4", "s1", "s2"));
+ checkAllDisabledForLauncher.run();
+
+ getManager().enableShortcuts(list("ms1", "ms2", "ms3", "ms4", "s1", "s2"));
+ checkAllDisabledForLauncher.run();
+
+ getManager().removeAllDynamicShortcuts();
+ getManager().removeDynamicShortcuts(list("ms1", "ms2", "ms3", "ms4", "s1", "s2"));
+ checkAllDisabledForLauncher.run();
+
+ getManager().updateShortcuts(list(makeShortcutWithShortLabel("s1", "new-title")));
+ checkAllDisabledForLauncher.run();
+
+
+ // Add a shortcut -- even though ms1 was immutable, it will succeed.
+ assertTrue(getManager().addDynamicShortcuts(list(
+ makeShortcutWithShortLabel("ms1", "original-title"))));
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertWith(getShortcutAsLauncher(USER_0))
+ .haveIds("ms1", "ms2", "ms3", "ms4", "s1", "s2")
+
+ .selectByIds("ms1")
+ .areAllEnabled()
+ .areAllDynamic()
+ .areAllPinned()
+ .forAllShortcuts(si -> {
+ assertEquals("original-title", si.getShortLabel());
+ })
+
+ // The rest still exist and disabled.
+ .revertToOriginalList()
+ .selectByIds("ms2", "ms3", "ms4", "s1", "s2")
+ .areAllDisabled()
+ .areAllPinned()
+ ;
+ });
+
+ assertTrue(getManager().setDynamicShortcuts(list(
+ makeShortcutWithShortLabel("ms2", "new-title-2"))));
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertWith(getShortcutAsLauncher(USER_0))
+ .haveIds("ms1", "ms2", "ms3", "ms4", "s1", "s2")
+
+ .selectByIds("ms1")
+ .areAllEnabled()
+ .areAllNotDynamic() // ms1 was not in the list, so no longer dynamic.
+ .areAllPinned()
+ .areAllMutable()
+ .forAllShortcuts(si -> {
+ assertEquals("original-title", si.getShortLabel());
+ })
+
+ .revertToOriginalList()
+ .selectByIds("ms2")
+ .areAllEnabled()
+ .areAllDynamic()
+ .areAllPinned()
+ .areAllMutable()
+ .forAllShortcuts(si -> {
+ assertEquals("new-title-2", si.getShortLabel());
+ })
+
+ // The rest still exist and disabled.
+ .revertToOriginalList()
+ .selectByIds("ms3", "ms4", "s1", "s2")
+ .areAllDisabled()
+ .areAllPinned()
+ ;
+ });
+
+ // Prepare for requestPinShortcut().
+ setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
+ mPinConfirmActivityFetcher = (packageName, userId) ->
+ new ComponentName(packageName, PIN_CONFIRM_ACTIVITY_CLASS);
+
+ mManager.requestPinShortcut(
+ makeShortcutWithShortLabel("ms3", "new-title-3"),
+ /*PendingIntent=*/ null);
+
+ // Note this was pinned, so it'll be accepted right away.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertWith(getShortcutAsLauncher(USER_0))
+ .selectByIds("ms3")
+ .areAllEnabled()
+ .areAllNotDynamic()
+ .areAllPinned()
+ .areAllMutable()
+ .forAllShortcuts(si -> {
+ assertEquals("new-title-3", si.getShortLabel());
+ // The new one replaces the old manifest shortcut, so the long label
+ // should be gone now.
+ assertNull(si.getLongLabel());
+ });
+ });
+
+ // Now, change the launcher to launcher2, and request pin again.
+ setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_2, USER_0));
+
+ reset(mServiceContext);
+
+ assertTrue(mManager.isRequestPinShortcutSupported());
+ mManager.requestPinShortcut(
+ makeShortcutWithShortLabel("ms4", "new-title-4"),
+ /*PendingIntent=*/ null);
+
+ // Initially there should be no pinned shortcuts for L2.
+ runWithCaller(LAUNCHER_2, USER_0, () -> {
+ assertWith(getShortcutAsLauncher(USER_0))
+ .selectPinned()
+ .isEmpty();
+
+ final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
+
+ verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+
+ assertEquals(LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT,
+ intent.getValue().getAction());
+ assertEquals(LAUNCHER_2, intent.getValue().getComponent().getPackageName());
+
+ // Check the request object.
+ final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue());
+
+ assertNotNull(request);
+ assertEquals(PinItemRequest.REQUEST_TYPE_SHORTCUT, request.getRequestType());
+
+ assertWith(request.getShortcutInfo())
+ .haveIds("ms4")
+ .areAllOrphan()
+ .forAllShortcuts(si -> {
+ assertEquals("new-title-4", si.getShortLabel());
+ // The new one replaces the old manifest shortcut, so the long label
+ // should be gone now.
+ assertNull(si.getLongLabel());
+ });
+ assertTrue(request.accept());
+
+ assertWith(getShortcutAsLauncher(USER_0))
+ .selectPinned()
+ .haveIds("ms4")
+ .areAllEnabled();
+ });
+ });
+ }
+
+ /**
+ * Test for restoring the pre-P backup format.
+ */
+ public void testBackupAndRestore_api27format() throws Exception {
+ final byte[] payload = readTestAsset("shortcut/shortcut_api27_backup.xml").getBytes();
+
+ addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "22222");
+ addPackage(LAUNCHER_1, LAUNCHER_UID_1, 10, "11111");
+
+ runWithSystemUid(() -> mService.applyRestore(payload, USER_0));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerShortcuts())
+ .areAllPinned()
+ .haveIds("s1")
+ .areAllEnabled();
+ });
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertWith(getShortcutAsLauncher(USER_0))
+ .areAllPinned()
+ .haveIds("s1")
+ .areAllEnabled();
+ });
+ // Make sure getBackupSourceVersionCode and isBackupSourceBackupAllowed
+ // are correct. We didn't have them in the old format.
+ assertEquals(8, mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+ .getPackageInfo().getBackupSourceVersionCode());
+ assertTrue(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+ .getPackageInfo().isBackupSourceBackupAllowed());
+
+ assertEquals(9, mService.getLauncherShortcutForTest(LAUNCHER_1, USER_0)
+ .getPackageInfo().getBackupSourceVersionCode());
+ assertTrue(mService.getLauncherShortcutForTest(LAUNCHER_1, USER_0)
+ .getPackageInfo().isBackupSourceBackupAllowed());
+
+ }
+
public void testSaveAndLoad_crossProfile() {
prepareCrossProfileDataSet();
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 3220ea9..fcdadac 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -1131,7 +1131,8 @@
assertEquals(0, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED
+ | ShortcutInfo.FLAG_SHADOW , si.getFlags());
assertNull(si.getBitmapPath()); // No icon.
assertEquals(0, si.getIconResourceId());
@@ -1198,7 +1199,8 @@
assertEquals(0, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED
+ | ShortcutInfo.FLAG_SHADOW , si.getFlags());
assertNull(si.getBitmapPath()); // No icon.
assertEquals(0, si.getIconResourceId());
assertEquals(null, si.getIconResName());
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index 536a504..71bcae7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -16,19 +16,7 @@
package com.android.server.wm;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-
-import android.content.res.Configuration;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.Before;
-import org.junit.After;
-
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -36,6 +24,15 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.After;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
/**
* Tests for the {@link DisplayContent.TaskStackContainers} container in {@link DisplayContent}.
*
@@ -52,12 +49,8 @@
@Before
public void setUp() throws Exception {
super.setUp();
- final Configuration overrideConfig = new Configuration();
- overrideConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
- mPinnedStack = new StackWindowController(PINNED_STACK_ID, null,
- mDisplayContent.getDisplayId(), true /* onTop */, new Rect(), sWm).mContainer;
- mPinnedStack.onOverrideConfigurationChanged(overrideConfig);
-
+ mPinnedStack = createStackControllerOnStackOnDisplay(
+ WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
// Stack should contain visible app window to be considered visible.
final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
assertFalse(mPinnedStack.isVisible());
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 4e810f2..56a3fb0 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -36,8 +36,6 @@
import android.view.IWindow;
import android.view.WindowManager;
-import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.AppOpsManager.OP_NONE;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -70,7 +68,7 @@
// make sure we don't collide with any existing display. If we run into no other display, the
// added display should be treated as default. This cannot be the default display
private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
- private static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
+ static int sNextStackId = 1000;
private static boolean sOneTimeSetupDone = false;
DisplayContent mDisplayContent;
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 926a606..a4349f4 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -22,6 +22,7 @@
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertNotEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyString;
@@ -59,9 +60,7 @@
import org.json.JSONException;
import org.json.JSONObject;
import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
import org.mockito.hamcrest.MockitoHamcrest;
import java.io.BufferedReader;
@@ -898,11 +897,14 @@
public ShortcutListAsserter areAllEnabled() {
forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isEnabled()));
+ areAllWithDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
return this;
}
public ShortcutListAsserter areAllDisabled() {
forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isEnabled()));
+ forAllShortcuts(s -> assertNotEquals("id=" + s.getId(),
+ ShortcutInfo.DISABLED_REASON_NOT_DISABLED, s.getDisabledReason()));
return this;
}
@@ -930,6 +932,16 @@
return this;
}
+ public ShortcutListAsserter areAllVisibleToPublisher() {
+ forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isVisibleToPublisher()));
+ return this;
+ }
+
+ public ShortcutListAsserter areAllNotVisibleToPublisher() {
+ forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isVisibleToPublisher()));
+ return this;
+ }
+
public ShortcutListAsserter areAllWithKeyFieldsOnly() {
forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.hasKeyFieldsOnly()));
return this;
@@ -960,6 +972,17 @@
return this;
}
+ public ShortcutListAsserter areAllWithDisabledReason(int disabledReason) {
+ forAllShortcuts(s -> assertEquals("id=" + s.getId(),
+ disabledReason, s.getDisabledReason()));
+ if (disabledReason == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
+ areAllVisibleToPublisher();
+ } else {
+ areAllNotVisibleToPublisher();
+ }
+ return this;
+ }
+
public ShortcutListAsserter forAllShortcuts(Consumer<ShortcutInfo> sa) {
boolean found = false;
for (int i = 0; i < mList.size(); i++) {
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index acc27be..d359b70 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -132,7 +132,9 @@
mHasMidiFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
// initial scan
- mCardsParser.scan();
+ if (mCardsParser.scan() != AlsaCardsParser.SCANSTATUS_SUCCESS) {
+ Slog.e(TAG, "Error scanning ASLA cards file.");
+ }
}
public void systemReady() {
@@ -314,7 +316,7 @@
return null;
}
- if (!mDevicesParser.scan()) {
+ if (mDevicesParser.scan() != AlsaDevicesParser.SCANSTATUS_SUCCESS) {
Slog.e(TAG, "Error parsing ALSA devices file.");
return null;
}
@@ -530,6 +532,9 @@
//
// called by UsbService.dump
public void dump(IndentingPrintWriter pw) {
+ pw.println("Parsers Scan Status:");
+ pw.println(" Cards Parser: " + mCardsParser.getScanStatus());
+ pw.println(" Devices Parser: " + mDevicesParser.getScanStatus());
pw.println("USB Audio Devices:");
for (UsbDevice device : mAudioDevices.keySet()) {
pw.println(" " + device.getDeviceName() + ": " + mAudioDevices.get(device));
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index c657a1b..095fdc6 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -376,6 +376,8 @@
}
}
}
+
+ mUsbAlsaManager.dump(pw);
}
private native void monitorUsbHostBus();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 689ce95..72685fa 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1573,6 +1573,13 @@
public static final String KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL =
"show_ims_registration_status_bool";
+ /**
+ * The flag to disable the popup dialog which warns the user of data charges.
+ * @hide
+ */
+ public static final String KEY_DISABLE_CHARGE_INDICATION_BOOL =
+ "disable_charge_indication_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -1840,6 +1847,7 @@
sDefaults.putStringArray(KEY_NON_ROAMING_OPERATOR_STRING_ARRAY, null);
sDefaults.putStringArray(KEY_ROAMING_OPERATOR_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
+ sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index 764b7b2..9a9877a 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -77,8 +77,9 @@
* Integer extra that Android will attach to the intent supplied via
* {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
* Indicates the result code of the download. One of
- * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, {@link #RESULT_CANCELLED}, or
- * {@link #RESULT_IO_ERROR}.
+ * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, {@link #RESULT_CANCELLED},
+ * {@link #RESULT_IO_ERROR}, {@link #RESULT_DOWNLOAD_FAILURE}, {@link #RESULT_OUT_OF_STORAGE},
+ * {@link #RESULT_SERVICE_ID_NOT_DEFINED}, or {@link #RESULT_FILE_ROOT_UNREACHABLE}.
*
* This extra may also be used by the middleware when it is sending intents to the app.
*/
@@ -142,11 +143,41 @@
/**
* Indicates that the download will not be completed due to an I/O error incurred while
- * writing to temp files. This commonly indicates that the device is out of storage space,
- * but may indicate other conditions as well (such as an SD card being removed).
+ * writing to temp files.
+ *
+ * This is likely a transient error and another {@link DownloadRequest} should be sent to try
+ * the download again.
*/
public static final int RESULT_IO_ERROR = 4;
- // TODO - more results!
+
+ /**
+ * Indicates that the Service ID specified in the {@link DownloadRequest} is incorrect due to
+ * the Id being incorrect, stale, expired, or similar.
+ */
+ public static final int RESULT_SERVICE_ID_NOT_DEFINED = 5;
+
+ /**
+ * Indicates that there was an error while processing downloaded files, such as a file repair or
+ * file decoding error and is not due to a file I/O error.
+ *
+ * This is likely a transient error and another {@link DownloadRequest} should be sent to try
+ * the download again.
+ */
+ public static final int RESULT_DOWNLOAD_FAILURE = 6;
+
+ /**
+ * Indicates that the file system is full and the {@link DownloadRequest} can not complete.
+ * Either space must be made on the current file system or the temp file root location must be
+ * changed to a location that is not full to download the temp files.
+ */
+ public static final int RESULT_OUT_OF_STORAGE = 7;
+
+ /**
+ * Indicates that the file root that was set is currently unreachable. This can happen if the
+ * temp files are set to be stored on external storage and the SD card was removed, for example.
+ * The temp file root should be changed before sending another DownloadRequest.
+ */
+ public static final int RESULT_FILE_ROOT_UNREACHABLE = 8;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
index fe27537..9af1eb9 100644
--- a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
+++ b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
@@ -287,7 +287,7 @@
return;
}
- List<Uri> tempFiles = intent.getParcelableExtra(VendorUtils.EXTRA_TEMP_LIST);
+ List<Uri> tempFiles = intent.getParcelableArrayListExtra(VendorUtils.EXTRA_TEMP_LIST);
if (tempFiles == null) {
return;
}
@@ -309,7 +309,7 @@
return;
}
int fdCount = intent.getIntExtra(VendorUtils.EXTRA_FD_COUNT, 0);
- List<Uri> pausedList = intent.getParcelableExtra(VendorUtils.EXTRA_PAUSED_LIST);
+ List<Uri> pausedList = intent.getParcelableArrayListExtra(VendorUtils.EXTRA_PAUSED_LIST);
if (fdCount == 0 && (pausedList == null || pausedList.size() == 0)) {
Log.i(LOG_TAG, "No temp files actually requested. Ending.");
@@ -492,9 +492,14 @@
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException("Package manager couldn't find " + context.getPackageName());
}
+ if (appInfo.metaData == null) {
+ throw new RuntimeException("App must declare the file provider authority as metadata " +
+ "in the manifest.");
+ }
String authority = appInfo.metaData.getString(MBMS_FILE_PROVIDER_META_DATA_KEY);
if (authority == null) {
- throw new RuntimeException("Must declare the file provider authority as meta data");
+ throw new RuntimeException("App must declare the file provider authority as metadata " +
+ "in the manifest.");
}
return authority;
}
diff --git a/tests/CantSaveState1/Android.mk b/tests/CantSaveState1/Android.mk
new file mode 100644
index 0000000..6e9db6e
--- /dev/null
+++ b/tests/CantSaveState1/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := CantSaveState1
+
+include $(BUILD_PACKAGE)
diff --git a/tests/CantSaveState1/AndroidManifest.xml b/tests/CantSaveState1/AndroidManifest.xml
new file mode 100644
index 0000000..fadcaeb
--- /dev/null
+++ b/tests/CantSaveState1/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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"
+ package="com.android.test.cantsavestate1">
+ <application android:label="Can't Save 1" android:cantSaveState="true">
+ <activity android:name="CantSave1Activity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/CantSaveState1/res/layout/cant_save_1_activity.xml b/tests/CantSaveState1/res/layout/cant_save_1_activity.xml
new file mode 100644
index 0000000..c5bf657
--- /dev/null
+++ b/tests/CantSaveState1/res/layout/cant_save_1_activity.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="25dp"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="This app #1 can't save its state"
+ />
+
+</LinearLayout>
diff --git a/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java b/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java
new file mode 100644
index 0000000..8879ed0
--- /dev/null
+++ b/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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.test.cantsavestate1;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class CantSave1Activity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.cant_save_1_activity);
+ }
+}
diff --git a/tests/CantSaveState2/Android.mk b/tests/CantSaveState2/Android.mk
new file mode 100644
index 0000000..add9214
--- /dev/null
+++ b/tests/CantSaveState2/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := CantSaveState2
+
+include $(BUILD_PACKAGE)
diff --git a/tests/CantSaveState2/AndroidManifest.xml b/tests/CantSaveState2/AndroidManifest.xml
new file mode 100644
index 0000000..8f4f01d
--- /dev/null
+++ b/tests/CantSaveState2/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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"
+ package="com.android.test.cantsavestate2">
+ <application android:label="Can't Save 2" android:cantSaveState="true">
+ <activity android:name="CantSave2Activity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/CantSaveState2/res/layout/cant_save_2_activity.xml b/tests/CantSaveState2/res/layout/cant_save_2_activity.xml
new file mode 100644
index 0000000..c5b8e3d
--- /dev/null
+++ b/tests/CantSaveState2/res/layout/cant_save_2_activity.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="25dp"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="This app #2 can't save its state"
+ />
+
+</LinearLayout>
diff --git a/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java b/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java
new file mode 100644
index 0000000..3ce63c7
--- /dev/null
+++ b/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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.test.cantsavestate2;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class CantSave2Activity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.cant_save_2_activity);
+ }
+}
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 8210403..163250d 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -296,6 +296,7 @@
Notification n = new Notification.Builder(NotificationTestList.this, "min")
.setSmallIcon(R.drawable.icon2)
.setContentTitle("Min priority")
+ .setTicker("Min priority")
.build();
mNM.notify("min", 7000, n);
}
@@ -306,6 +307,7 @@
Notification n = new Notification.Builder(NotificationTestList.this, "low")
.setSmallIcon(R.drawable.icon2)
.setContentTitle("Low priority")
+ .setTicker("Low priority")
.build();
mNM.notify("low", 7002, n);
}
@@ -326,6 +328,7 @@
Notification n = new Notification.Builder(NotificationTestList.this, "high")
.setSmallIcon(R.drawable.icon2)
.setContentTitle("High priority")
+ .setTicker("High priority")
.build();
mNM.notify("high", 7006, n);
}
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
index 9f31d27..ccb0f3b 100644
--- a/tests/net/java/android/net/IpSecManagerTest.java
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -31,19 +31,21 @@
import static org.mockito.Mockito.when;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.system.Os;
-import android.test.AndroidTestCase;
+
import com.android.server.IpSecService;
+
import java.net.InetAddress;
import java.net.UnknownHostException;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
/** Unit tests for {@link IpSecManager}. */
@SmallTest
-@RunWith(JUnit4.class)
+@RunWith(AndroidJUnit4.class)
public class IpSecManagerTest {
private static final int TEST_UDP_ENCAP_PORT = 34567;
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/tests/net/java/android/net/LinkPropertiesTest.java
similarity index 80%
rename from core/tests/coretests/src/android/net/LinkPropertiesTest.java
rename to tests/net/java/android/net/LinkPropertiesTest.java
index 1cb0ecd..52da79a 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/tests/net/java/android/net/LinkPropertiesTest.java
@@ -16,19 +16,22 @@
package android.net;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties.CompareResult;
import android.net.LinkProperties.ProvisioningChange;
import android.net.RouteInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.system.OsConstants;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
import android.util.ArraySet;
-import junit.framework.TestCase;
-
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
@@ -37,8 +40,12 @@
import java.util.List;
import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class LinkPropertiesTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LinkPropertiesTest {
private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334");
@@ -92,7 +99,7 @@
assertEquals(source.hashCode(), target.hashCode());
}
- @SmallTest
+ @Test
public void testEqualsNull() {
LinkProperties source = new LinkProperties();
LinkProperties target = new LinkProperties();
@@ -101,155 +108,141 @@
assertLinkPropertiesEqual(source, target);
}
- @SmallTest
- public void testEqualsSameOrder() {
- try {
- LinkProperties source = new LinkProperties();
- source.setInterfaceName(NAME);
- // set 2 link addresses
- source.addLinkAddress(LINKADDRV4);
- source.addLinkAddress(LINKADDRV6);
- // set 2 dnses
- source.addDnsServer(DNS1);
- source.addDnsServer(DNS2);
- // set 2 gateways
- source.addRoute(new RouteInfo(GATEWAY1));
- source.addRoute(new RouteInfo(GATEWAY2));
- source.setMtu(MTU);
+ @Test
+ public void testEqualsSameOrder() throws Exception {
+ LinkProperties source = new LinkProperties();
+ source.setInterfaceName(NAME);
+ // set 2 link addresses
+ source.addLinkAddress(LINKADDRV4);
+ source.addLinkAddress(LINKADDRV6);
+ // set 2 dnses
+ source.addDnsServer(DNS1);
+ source.addDnsServer(DNS2);
+ // set 2 gateways
+ source.addRoute(new RouteInfo(GATEWAY1));
+ source.addRoute(new RouteInfo(GATEWAY2));
+ source.setMtu(MTU);
- LinkProperties target = new LinkProperties();
+ LinkProperties target = new LinkProperties();
- // All fields are same
- target.setInterfaceName(NAME);
- target.addLinkAddress(LINKADDRV4);
- target.addLinkAddress(LINKADDRV6);
- target.addDnsServer(DNS1);
- target.addDnsServer(DNS2);
- target.addRoute(new RouteInfo(GATEWAY1));
- target.addRoute(new RouteInfo(GATEWAY2));
- target.setMtu(MTU);
+ // All fields are same
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
+ target.setMtu(MTU);
- assertLinkPropertiesEqual(source, target);
+ assertLinkPropertiesEqual(source, target);
- target.clear();
- // change Interface Name
- target.setInterfaceName("qmi1");
- target.addLinkAddress(LINKADDRV4);
- target.addLinkAddress(LINKADDRV6);
- target.addDnsServer(DNS1);
- target.addDnsServer(DNS2);
- target.addRoute(new RouteInfo(GATEWAY1));
- target.addRoute(new RouteInfo(GATEWAY2));
- target.setMtu(MTU);
- assertFalse(source.equals(target));
+ target.clear();
+ // change Interface Name
+ target.setInterfaceName("qmi1");
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
+ target.setMtu(MTU);
+ assertFalse(source.equals(target));
- target.clear();
- target.setInterfaceName(NAME);
- // change link addresses
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
- target.addLinkAddress(LINKADDRV6);
- target.addDnsServer(DNS1);
- target.addDnsServer(DNS2);
- target.addRoute(new RouteInfo(GATEWAY1));
- target.addRoute(new RouteInfo(GATEWAY2));
- target.setMtu(MTU);
- assertFalse(source.equals(target));
+ target.clear();
+ target.setInterfaceName(NAME);
+ // change link addresses
+ target.addLinkAddress(new LinkAddress(
+ NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
+ target.addLinkAddress(LINKADDRV6);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
+ target.setMtu(MTU);
+ assertFalse(source.equals(target));
- target.clear();
- target.setInterfaceName(NAME);
- target.addLinkAddress(LINKADDRV4);
- target.addLinkAddress(LINKADDRV6);
- // change dnses
- target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
- target.addDnsServer(DNS2);
- target.addRoute(new RouteInfo(GATEWAY1));
- target.addRoute(new RouteInfo(GATEWAY2));
- target.setMtu(MTU);
- assertFalse(source.equals(target));
+ target.clear();
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ // change dnses
+ target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
+ target.addDnsServer(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
+ target.setMtu(MTU);
+ assertFalse(source.equals(target));
- target.clear();
- target.setInterfaceName(NAME);
- target.addLinkAddress(LINKADDRV4);
- target.addLinkAddress(LINKADDRV6);
- target.addDnsServer(DNS1);
- target.addDnsServer(DNS2);
- // change gateway
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
- target.addRoute(new RouteInfo(GATEWAY2));
- target.setMtu(MTU);
- assertFalse(source.equals(target));
+ target.clear();
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
+ // change gateway
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
+ target.addRoute(new RouteInfo(GATEWAY2));
+ target.setMtu(MTU);
+ assertFalse(source.equals(target));
- target.clear();
- target.setInterfaceName(NAME);
- target.addLinkAddress(LINKADDRV4);
- target.addLinkAddress(LINKADDRV6);
- target.addDnsServer(DNS1);
- target.addDnsServer(DNS2);
- target.addRoute(new RouteInfo(GATEWAY1));
- target.addRoute(new RouteInfo(GATEWAY2));
- // change mtu
- target.setMtu(1440);
- assertFalse(source.equals(target));
-
- } catch (Exception e) {
- throw new RuntimeException(e.toString());
- //fail();
- }
+ target.clear();
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
+ // change mtu
+ target.setMtu(1440);
+ assertFalse(source.equals(target));
}
- @SmallTest
- public void testEqualsDifferentOrder() {
- try {
- LinkProperties source = new LinkProperties();
- source.setInterfaceName(NAME);
- // set 2 link addresses
- source.addLinkAddress(LINKADDRV4);
- source.addLinkAddress(LINKADDRV6);
- // set 2 dnses
- source.addDnsServer(DNS1);
- source.addDnsServer(DNS2);
- // set 2 gateways
- source.addRoute(new RouteInfo(GATEWAY1));
- source.addRoute(new RouteInfo(GATEWAY2));
- source.setMtu(MTU);
+ @Test
+ public void testEqualsDifferentOrder() throws Exception {
+ LinkProperties source = new LinkProperties();
+ source.setInterfaceName(NAME);
+ // set 2 link addresses
+ source.addLinkAddress(LINKADDRV4);
+ source.addLinkAddress(LINKADDRV6);
+ // set 2 dnses
+ source.addDnsServer(DNS1);
+ source.addDnsServer(DNS2);
+ // set 2 gateways
+ source.addRoute(new RouteInfo(GATEWAY1));
+ source.addRoute(new RouteInfo(GATEWAY2));
+ source.setMtu(MTU);
- LinkProperties target = new LinkProperties();
- // Exchange order
- target.setInterfaceName(NAME);
- target.addLinkAddress(LINKADDRV6);
- target.addLinkAddress(LINKADDRV4);
- target.addDnsServer(DNS2);
- target.addDnsServer(DNS1);
- target.addRoute(new RouteInfo(GATEWAY2));
- target.addRoute(new RouteInfo(GATEWAY1));
- target.setMtu(MTU);
+ LinkProperties target = new LinkProperties();
+ // Exchange order
+ target.setInterfaceName(NAME);
+ target.addLinkAddress(LINKADDRV6);
+ target.addLinkAddress(LINKADDRV4);
+ target.addDnsServer(DNS2);
+ target.addDnsServer(DNS1);
+ target.addRoute(new RouteInfo(GATEWAY2));
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.setMtu(MTU);
- assertLinkPropertiesEqual(source, target);
- } catch (Exception e) {
- fail();
- }
+ assertLinkPropertiesEqual(source, target);
}
- @SmallTest
- public void testEqualsDuplicated() {
- try {
- LinkProperties source = new LinkProperties();
- // set 3 link addresses, eg, [A, A, B]
- source.addLinkAddress(LINKADDRV4);
- source.addLinkAddress(LINKADDRV4);
- source.addLinkAddress(LINKADDRV6);
+ @Test
+ public void testEqualsDuplicated() throws Exception {
+ LinkProperties source = new LinkProperties();
+ // set 3 link addresses, eg, [A, A, B]
+ source.addLinkAddress(LINKADDRV4);
+ source.addLinkAddress(LINKADDRV4);
+ source.addLinkAddress(LINKADDRV6);
- LinkProperties target = new LinkProperties();
- // set 3 link addresses, eg, [A, B, B]
- target.addLinkAddress(LINKADDRV4);
- target.addLinkAddress(LINKADDRV6);
- target.addLinkAddress(LINKADDRV6);
+ LinkProperties target = new LinkProperties();
+ // set 3 link addresses, eg, [A, B, B]
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addLinkAddress(LINKADDRV6);
- assertLinkPropertiesEqual(source, target);
- } catch (Exception e) {
- fail();
- }
+ assertLinkPropertiesEqual(source, target);
}
private void assertAllRoutesHaveInterface(String iface, LinkProperties lp) {
@@ -258,7 +251,7 @@
}
}
- @SmallTest
+ @Test
public void testRouteInterfaces() {
LinkAddress prefix = new LinkAddress(
NetworkUtils.numericToInetAddress("2001:db8::"), 32);
@@ -317,7 +310,7 @@
assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
}
- @SmallTest
+ @Test
public void testStackedInterfaces() {
LinkProperties rmnet0 = new LinkProperties();
rmnet0.setInterfaceName("rmnet0");
@@ -373,7 +366,7 @@
return lp.getLinkAddresses().iterator().next();
}
- @SmallTest
+ @Test
public void testAddressMethods() {
LinkProperties lp = new LinkProperties();
@@ -460,7 +453,7 @@
assertEquals(0, lp.getLinkAddresses().size());
}
- @SmallTest
+ @Test
public void testSetLinkAddresses() {
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(LINKADDRV4);
@@ -475,7 +468,7 @@
assertTrue(lp.equals(lp));
}
- @SmallTest
+ @Test
public void testIsProvisioned() {
LinkProperties lp4 = new LinkProperties();
assertFalse("v4only:empty", lp4.isProvisioned());
@@ -529,7 +522,7 @@
assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned());
}
- @SmallTest
+ @Test
public void testCompareProvisioning() {
LinkProperties v4lp = new LinkProperties();
v4lp.addLinkAddress(LINKADDRV4);
@@ -589,8 +582,7 @@
LinkProperties.compareProvisioning(v6lp, v6lp2));
}
- @SmallTest
- @Suppress // Failing.
+ @Test
public void testIsReachable() {
final LinkProperties v4lp = new LinkProperties();
assertFalse(v4lp.isReachable(DNS1));
@@ -687,7 +679,7 @@
assertTrue(v6lp.isReachable(DNS1));
}
- @SmallTest
+ @Test
public void testLinkPropertiesEnsureDirectlyConnectedRoutes() {
// IPv4 case: no route added initially
LinkProperties rmnet0 = new LinkProperties();
@@ -750,25 +742,25 @@
}
- @SmallTest
+ @Test
public void testCompareResult() {
// Either adding or removing items
- testCompareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1),
+ compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1),
Arrays.asList(2, 3, 4), new ArrayList<>());
- testCompareResult(Arrays.asList(1, 2), Arrays.asList(3, 2, 1, 4),
+ compareResult(Arrays.asList(1, 2), Arrays.asList(3, 2, 1, 4),
new ArrayList<>(), Arrays.asList(3, 4));
// adding and removing items at the same time
- testCompareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(2, 3, 4, 5),
+ compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(2, 3, 4, 5),
Arrays.asList(1), Arrays.asList(5));
- testCompareResult(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6),
+ compareResult(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6),
Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6));
// null cases
- testCompareResult(Arrays.asList(1, 2, 3), null, Arrays.asList(1, 2, 3), new ArrayList<>());
- testCompareResult(null, Arrays.asList(3, 2, 1), new ArrayList<>(), Arrays.asList(1, 2, 3));
- testCompareResult(null, null, new ArrayList<>(), new ArrayList<>());
+ compareResult(Arrays.asList(1, 2, 3), null, Arrays.asList(1, 2, 3), new ArrayList<>());
+ compareResult(null, Arrays.asList(3, 2, 1), new ArrayList<>(), Arrays.asList(1, 2, 3));
+ compareResult(null, null, new ArrayList<>(), new ArrayList<>());
}
private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) {
@@ -780,7 +772,7 @@
assertEquals(expectedSet, actualSet);
}
- private <T> void testCompareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved,
+ private <T> void compareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved,
List<T> expectAdded) {
CompareResult<T> result = new CompareResult<>(oldItems, newItems);
assertEquals(new ArraySet<>(expectAdded), new ArraySet<>(result.added));
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index eb85eb4..25289ba 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -30,23 +30,30 @@
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import com.google.android.collect.Sets;
-import junit.framework.TestCase;
-
import java.util.HashSet;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
@SmallTest
-public class NetworkStatsTest extends TestCase {
+public class NetworkStatsTest {
private static final String TEST_IFACE = "test0";
private static final String TEST_IFACE2 = "test2";
private static final int TEST_UID = 1001;
private static final long TEST_START = 1194220800000L;
+ @Test
public void testFindIndex() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 5)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
@@ -74,6 +81,7 @@
ROAMING_NO));
}
+ @Test
public void testFindIndexHinted() {
final NetworkStats stats = new NetworkStats(TEST_START, 3)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
@@ -116,6 +124,7 @@
}
}
+ @Test
public void testAddEntryGrow() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 4);
@@ -168,6 +177,7 @@
ROAMING_YES, 7L, 70L, 5L, 50L, 11);
}
+ @Test
public void testCombineExisting() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 10);
@@ -190,6 +200,7 @@
256L, 2L, 256L, 2L, 6);
}
+ @Test
public void testSubtractIdenticalData() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
@@ -208,6 +219,7 @@
0L, 0L, 0L, 0);
}
+ @Test
public void testSubtractIdenticalRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
@@ -226,6 +238,7 @@
1L, 4L, 1L, 8);
}
+ @Test
public void testSubtractNewRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
@@ -247,6 +260,7 @@
1024L, 8L, 1024L, 8L, 20);
}
+ @Test
public void testSubtractMissingRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
.addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
@@ -264,6 +278,7 @@
assertEquals(4L, result.getTotalBytes());
}
+ @Test
public void testTotalBytes() throws Exception {
final NetworkStats iface = new NetworkStats(TEST_START, 2)
.addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
@@ -304,6 +319,7 @@
assertEquals(96L, uidRoaming.getTotalBytes());
}
+ @Test
public void testGroupedByIfaceEmpty() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 3);
final NetworkStats grouped = uidStats.groupedByIface();
@@ -312,6 +328,7 @@
assertEquals(0, grouped.size());
}
+ @Test
public void testGroupedByIfaceAll() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
.addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L, 0L,
@@ -329,6 +346,7 @@
384L, 24L, 0L, 6L, 0L);
}
+ @Test
public void testGroupedByIface() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 7)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L,
@@ -357,6 +375,7 @@
1024L, 64L, 0L, 0L, 0L);
}
+ @Test
public void testAddAllValues() {
final NetworkStats first = new NetworkStats(TEST_START, 5)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
@@ -387,6 +406,7 @@
32L, 0L, 0L, 0L, 0L);
}
+ @Test
public void testGetTotal() {
final NetworkStats stats = new NetworkStats(TEST_START, 7)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L,
@@ -415,6 +435,7 @@
assertValues(stats.getTotal(null, ifaces), 1024L, 64L, 0L, 0L, 0L);
}
+ @Test
public void testWithoutUid() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 3)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
@@ -433,6 +454,7 @@
8L, 0L, 0L, 0L);
}
+ @Test
public void testClone() throws Exception {
final NetworkStats original = new NetworkStats(TEST_START, 5)
.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
@@ -449,6 +471,7 @@
assertEquals(128L + 512L, clone.getTotalBytes());
}
+ @Test
public void testAddWhenEmpty() throws Exception {
final NetworkStats red = new NetworkStats(TEST_START, -1);
final NetworkStats blue = new NetworkStats(TEST_START, 5)
@@ -459,6 +482,7 @@
red.combineAllValues(blue);
}
+ @Test
public void testMigrateTun() throws Exception {
final int tunUid = 10030;
final String tunIface = "tun0";
@@ -556,6 +580,7 @@
// interface by the vpn app before it's sent out of the underlying interface. The VPN app should
// not be charged for the echoed data but it should still be charged for any extra data it sends
// via the underlying interface.
+ @Test
public void testMigrateTun_VpnAsLoopback() {
final int tunUid = 10030;
final String tunIface = "tun0";
diff --git a/core/tests/coretests/src/android/net/NetworkTest.java b/tests/net/java/android/net/NetworkTest.java
similarity index 89%
rename from core/tests/coretests/src/android/net/NetworkTest.java
rename to tests/net/java/android/net/NetworkTest.java
index 74b6d98..bacf986 100644
--- a/core/tests/coretests/src/android/net/NetworkTest.java
+++ b/tests/net/java/android/net/NetworkTest.java
@@ -16,13 +16,17 @@
package android.net;
-import static android.test.MoreAsserts.assertNotEqual;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.Network;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import java.io.File;
import java.io.FileDescriptor;
@@ -32,13 +36,17 @@
import java.net.InetAddress;
import java.net.Inet6Address;
import java.net.SocketException;
+import java.util.Objects;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class NetworkTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkTest {
final Network mNetwork = new Network(99);
- @SmallTest
+ @Test
public void testBindSocketOfInvalidFdThrows() throws Exception {
final FileDescriptor fd = new FileDescriptor();
@@ -50,7 +58,7 @@
} catch (SocketException expected) {}
}
- @SmallTest
+ @Test
public void testBindSocketOfNonSocketFdThrows() throws Exception {
final File devNull = new File("/dev/null");
assertTrue(devNull.canRead());
@@ -65,7 +73,7 @@
} catch (SocketException expected) {}
}
- @SmallTest
+ @Test
public void testBindSocketOfConnectedDatagramSocketThrows() throws Exception {
final DatagramSocket mDgramSocket = new DatagramSocket(0, (InetAddress) Inet6Address.ANY);
mDgramSocket.connect((InetAddress) Inet6Address.LOOPBACK, 53);
@@ -77,7 +85,7 @@
} catch (SocketException expected) {}
}
- @SmallTest
+ @Test
public void testBindSocketOfLocalSocketThrows() throws Exception {
final LocalSocket mLocalClient = new LocalSocket();
mLocalClient.bind(new LocalSocketAddress("testClient"));
@@ -98,7 +106,7 @@
} catch (SocketException expected) {}
}
- @SmallTest
+ @Test
public void testZeroIsObviousForDebugging() {
Network zero = new Network(0);
assertEquals(0, zero.hashCode());
@@ -106,7 +114,7 @@
assertEquals("0", zero.toString());
}
- @SmallTest
+ @Test
public void testGetNetworkHandle() {
Network one = new Network(1);
Network two = new Network(2);
@@ -143,4 +151,8 @@
assertEquals(8606370526L, two.getNetworkHandle());
assertEquals(12901337822L, three.getNetworkHandle());
}
+
+ private static <T> void assertNotEqual(T t1, T t2) {
+ assertFalse(Objects.equals(t1, t2));
+ }
}
diff --git a/core/tests/coretests/src/android/net/StaticIpConfigurationTest.java b/tests/net/java/android/net/StaticIpConfigurationTest.java
similarity index 89%
rename from core/tests/coretests/src/android/net/StaticIpConfigurationTest.java
rename to tests/net/java/android/net/StaticIpConfigurationTest.java
index 59f780f..5bb5734 100644
--- a/core/tests/coretests/src/android/net/StaticIpConfigurationTest.java
+++ b/tests/net/java/android/net/StaticIpConfigurationTest.java
@@ -16,22 +16,26 @@
package android.net;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.RouteInfo;
-import android.net.StaticIpConfiguration;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import java.net.InetAddress;
import java.util.HashSet;
+import java.util.Objects;
-import junit.framework.TestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-
-
-public class StaticIpConfigurationTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class StaticIpConfigurationTest {
private static final String ADDRSTR = "192.0.2.2/25";
private static final LinkAddress ADDR = new LinkAddress(ADDRSTR);
@@ -53,16 +57,8 @@
assertEquals(0, s.dnsServers.size());
}
- private boolean isEqual(StaticIpConfiguration s1, StaticIpConfiguration s2) {
- return s1.equals(s2);
- }
-
- private void assertEquals(StaticIpConfiguration s1, StaticIpConfiguration s2) {
- assertTrue(isEqual(s1, s2));
- }
-
- private void assertNotEquals(StaticIpConfiguration s1, StaticIpConfiguration s2) {
- assertFalse(isEqual(s1, s2));
+ private static <T> void assertNotEquals(T t1, T t2) {
+ assertFalse(Objects.equals(t1, t2));
}
private StaticIpConfiguration makeTestObject() {
@@ -76,13 +72,13 @@
return s;
}
- @SmallTest
+ @Test
public void testConstructor() {
StaticIpConfiguration s = new StaticIpConfiguration();
checkEmpty(s);
}
- @SmallTest
+ @Test
public void testCopyAndClear() {
StaticIpConfiguration empty = new StaticIpConfiguration((StaticIpConfiguration) null);
checkEmpty(empty);
@@ -94,7 +90,7 @@
assertEquals(empty, s2);
}
- @SmallTest
+ @Test
public void testHashCodeAndEquals() {
HashSet<Integer> hashCodes = new HashSet();
hashCodes.add(0);
@@ -143,7 +139,7 @@
assertNotEquals(s, s2);
}
- @SmallTest
+ @Test
public void testToLinkProperties() {
LinkProperties expected = new LinkProperties();
expected.setInterfaceName(IFACE);
@@ -215,11 +211,10 @@
return s2;
}
- @SmallTest
+ @Test
public void testParceling() {
StaticIpConfiguration s = makeTestObject();
StaticIpConfiguration s2 = passThroughParcel(s);
assertEquals(s, s2);
}
}
-
diff --git a/tests/net/java/android/net/UidRangeTest.java b/tests/net/java/android/net/UidRangeTest.java
index 0a56e1b..1d1013e 100644
--- a/tests/net/java/android/net/UidRangeTest.java
+++ b/tests/net/java/android/net/UidRangeTest.java
@@ -16,14 +16,20 @@
package android.net;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
-public class UidRangeTest extends TestCase {
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class UidRangeTest {
static {
System.loadLibrary("frameworksnettestsjni");
@@ -33,7 +39,7 @@
private static native int getStart(byte[] inParcel);
private static native int getStop(byte[] inParcel);
- @SmallTest
+ @Test
public void testNativeParcelUnparcel() {
UidRange original = new UidRange(1234, Integer.MAX_VALUE);
@@ -45,7 +51,7 @@
assertArrayEquals(inParcel, outParcel);
}
- @SmallTest
+ @Test
public void testIndividualNativeFields() {
UidRange original = new UidRange(0x11115678, 0x22224321);
byte[] originalBytes = marshall(original);
@@ -54,14 +60,14 @@
assertEquals(original.stop, getStop(originalBytes));
}
- @SmallTest
+ @Test
public void testSingleItemUidRangeAllowed() {
new UidRange(123, 123);
new UidRange(0, 0);
new UidRange(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
- @SmallTest
+ @Test
public void testNegativeUidsDisallowed() {
try {
new UidRange(-2, 100);
@@ -76,7 +82,7 @@
}
}
- @SmallTest
+ @Test
public void testStopLessThanStartDisallowed() {
final int x = 4195000;
try {
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 5008a41..99a2ad9 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -16,6 +16,16 @@
package android.net.apf;
+import static android.system.OsConstants.*;
+import static com.android.internal.util.BitUtils.bytesToBEInt;
+import static com.android.internal.util.BitUtils.put;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.verify;
+
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkUtils;
@@ -30,23 +40,22 @@
import android.os.ConditionVariable;
import android.os.Parcelable;
import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import android.system.ErrnoException;
import android.system.Os;
-import android.test.AndroidTestCase;
import android.text.format.DateUtils;
-import android.test.suitebuilder.annotation.SmallTest;
-import static android.system.OsConstants.*;
import com.android.frameworks.tests.net.R;
import com.android.internal.util.HexDump;
-import static com.android.internal.util.BitUtils.bytesToBEInt;
-import static com.android.internal.util.BitUtils.put;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.verify;
import java.io.File;
import java.io.FileDescriptor;
@@ -69,14 +78,15 @@
* Build, install and run with:
* runtest frameworks-net -c android.net.apf.ApfTest
*/
-public class ApfTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ApfTest {
private static final int TIMEOUT_MS = 500;
@Mock IpConnectivityLog mLog;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
MockitoAnnotations.initMocks(this);
// Load up native shared library containing APF interpreter exposed via JNI.
System.loadLibrary("frameworksnettestsjni");
@@ -161,7 +171,7 @@
* generating bytecode for that program and running it through the
* interpreter to verify it functions correctly.
*/
- @SmallTest
+ @Test
public void testApfInstructions() throws IllegalInstructionException {
// Empty program should pass because having the program counter reach the
// location immediately after the program indicates the packet should be
@@ -569,7 +579,7 @@
* Generate some BPF programs, translate them to APF, then run APF and BPF programs
* over packet traces and verify both programs filter out the same packets.
*/
- @SmallTest
+ @Test
public void testApfAgainstBpf() throws Exception {
String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
"arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
@@ -739,7 +749,7 @@
private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2};
private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0};
- @SmallTest
+ @Test
public void testApfFilterIPv4() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
@@ -796,7 +806,7 @@
apfFilter.shutdown();
}
- @SmallTest
+ @Test
public void testApfFilterIPv6() throws Exception {
final int[] ethTypeBlackList = {};
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
@@ -830,7 +840,7 @@
apfFilter.shutdown();
}
- @SmallTest
+ @Test
public void testApfFilterMulticast() throws Exception {
final byte[] unicastIpv4Addr = {(byte)192,0,2,63};
final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
@@ -922,7 +932,7 @@
apfFilter.shutdown();
}
- @SmallTest
+ @Test
public void testApfFilter802_3() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
@@ -973,7 +983,7 @@
apfFilter.shutdown();
}
- @SmallTest
+ @Test
public void testApfFilterEthTypeBL() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
@@ -1058,7 +1068,7 @@
assertDrop(program, garpReply());
}
- @SmallTest
+ @Test
public void testApfFilterArp() throws Exception {
final int[] ethTypeBlackList = {};
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
@@ -1136,7 +1146,7 @@
// Test that when ApfFilter is shown the given packet, it generates a program to filter it
// for the given lifetime.
- private void testRaLifetime(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
+ private void verifyRaLifetime(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
// Verify new program generated if ApfFilter witnesses RA
ipManagerCallback.resetApfProgramWait();
@@ -1181,7 +1191,7 @@
ipManagerCallback.assertNoProgramUpdate();
}
- @SmallTest
+ @Test
public void testApfFilterRa() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
final int[] ethTypeBlackList = {};
@@ -1212,7 +1222,7 @@
basePacket.put(IPV6_ALL_NODES_ADDRESS);
assertPass(program, basePacket.array());
- testRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME);
+ verifyRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
@@ -1247,7 +1257,8 @@
prefixOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
PREFIX_VALID_LIFETIME);
- testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
+ verifyRaLifetime(
+ apfFilter, ipManagerCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
verifyRaEvent(new RaEvent(
ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
@@ -1259,7 +1270,7 @@
rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
rdnssOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
- testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, RDNSS_LIFETIME);
+ verifyRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, RDNSS_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
@@ -1270,7 +1281,7 @@
routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
routeInfoOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
- testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
+ verifyRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
@@ -1281,7 +1292,7 @@
dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
dnsslOptionPacket.putInt(
ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
- testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, ROUTER_LIFETIME);
+ verifyRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, ROUTER_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
// Verify that current program filters all five RAs:
@@ -1301,12 +1312,12 @@
* copy that resource into the app's data directory and return the path to it.
*/
private String stageFile(int rawId) throws Exception {
- File file = new File(getContext().getFilesDir(), "staged_file");
+ File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file");
new File(file.getParent()).mkdirs();
InputStream in = null;
OutputStream out = null;
try {
- in = getContext().getResources().openRawResource(rawId);
+ in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
out = new FileOutputStream(file);
Streams.copy(in, out);
} finally {
@@ -1323,7 +1334,7 @@
buffer.position(original);
}
- @SmallTest
+ @Test
public void testRaParsing() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
@@ -1343,7 +1354,7 @@
}
}
- @SmallTest
+ @Test
public void testRaProcessing() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
@@ -1383,7 +1394,7 @@
private native static boolean compareBpfApf(String filter, String pcap_filename,
byte[] apf_program);
- @SmallTest
+ @Test
public void testBroadcastAddress() throws Exception {
assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
diff --git a/tests/net/java/android/net/dhcp/DhcpPacketTest.java b/tests/net/java/android/net/dhcp/DhcpPacketTest.java
index d79c312..050183c 100644
--- a/tests/net/java/android/net/dhcp/DhcpPacketTest.java
+++ b/tests/net/java/android/net/dhcp/DhcpPacketTest.java
@@ -16,23 +16,36 @@
package android.net.dhcp;
+import static android.net.dhcp.DhcpPacket.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import android.net.DhcpResults;
import android.net.LinkAddress;
import android.net.NetworkUtils;
import android.net.metrics.DhcpErrorEvent;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import android.system.OsConstants;
-import android.test.suitebuilder.annotation.SmallTest;
+
import com.android.internal.util.HexDump;
+
import java.net.Inet4Address;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
-import junit.framework.TestCase;
-import static android.net.dhcp.DhcpPacket.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class DhcpPacketTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DhcpPacketTest {
private static Inet4Address SERVER_ADDR = v4Address("192.0.2.1");
private static Inet4Address CLIENT_ADDR = v4Address("192.0.2.234");
@@ -46,6 +59,7 @@
return (Inet4Address) NetworkUtils.numericToInetAddress(addrString);
}
+ @Before
public void setUp() {
DhcpPacket.testOverrideVendorId = "android-dhcp-???";
DhcpPacket.testOverrideHostname = "android-01234567890abcde";
@@ -131,7 +145,7 @@
assertEquals(expectedVendorInfo, offerPacket.mVendorInfo);
}
- @SmallTest
+ @Test
public void testDomainName() throws Exception {
byte[] nullByte = new byte[] { 0x00 };
byte[] twoNullBytes = new byte[] { 0x00, 0x00 };
@@ -186,7 +200,7 @@
assertEquals(leaseTimeMillis, offerPacket.getLeaseTimeMillis());
}
- @SmallTest
+ @Test
public void testLeaseTime() throws Exception {
byte[] noLease = null;
byte[] tooShortLease = new byte[] { 0x00, 0x00 };
@@ -234,7 +248,7 @@
}
}
- @SmallTest
+ @Test
public void testIpAddress() throws Exception {
byte[] slash11Netmask = new byte[] { (byte) 0xff, (byte) 0xe0, 0x00, 0x00 };
byte[] slash24Netmask = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00 };
@@ -278,11 +292,11 @@
assertEquals(mtu, dhcpResults.mtu);
}
- @SmallTest
+ @Test
public void testOffer1() throws Exception {
- // TODO: Turn all of these into golden files. This will probably require modifying
- // Android.mk appropriately, making this into an AndroidTestCase, and adding code to read
- // the golden files from the test APK's assets via mContext.getAssets().
+ // TODO: Turn all of these into golden files. This will probably require using
+ // android.support.test.InstrumentationRegistry for obtaining a Context object
+ // to read such golden files, along with an appropriate Android.mk.
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"451001480000000080118849c0a89003c0a89ff7" +
@@ -311,7 +325,7 @@
null, "192.168.144.3", null, 7200, false, 0, dhcpResults);
}
- @SmallTest
+ @Test
public void testOffer2() throws Exception {
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
@@ -343,7 +357,7 @@
assertTrue(dhcpResults.hasMeteredHint());
}
- @SmallTest
+ @Test
public void testBadIpPacket() throws Exception {
final byte[] packet = HexDump.hexStringToByteArray(
// IP header.
@@ -358,7 +372,7 @@
fail("Dhcp packet parsing should have failed");
}
- @SmallTest
+ @Test
public void testBadDhcpPacket() throws Exception {
final byte[] packet = HexDump.hexStringToByteArray(
// IP header.
@@ -377,7 +391,7 @@
fail("Dhcp packet parsing should have failed");
}
- @SmallTest
+ @Test
public void testBadTruncatedOffer() throws Exception {
final byte[] packet = HexDump.hexStringToByteArray(
// IP header.
@@ -406,7 +420,7 @@
fail("Dhcp packet parsing should have failed");
}
- @SmallTest
+ @Test
public void testBadOfferWithoutACookie() throws Exception {
final byte[] packet = HexDump.hexStringToByteArray(
// IP header.
@@ -437,7 +451,7 @@
fail("Dhcp packet parsing should have failed");
}
- @SmallTest
+ @Test
public void testOfferWithBadCookie() throws Exception {
final byte[] packet = HexDump.hexStringToByteArray(
// IP header.
@@ -473,7 +487,7 @@
assertEquals(Integer.toHexString(expected), Integer.toHexString(got));
}
- @SmallTest
+ @Test
public void testTruncatedOfferPackets() throws Exception {
final byte[] packet = HexDump.hexStringToByteArray(
// IP header.
@@ -507,7 +521,7 @@
}
}
- @SmallTest
+ @Test
public void testRandomPackets() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
@@ -547,7 +561,7 @@
null, "192.168.144.3", null, 7200, false, expectedMtu, dhcpResults);
}
- @SmallTest
+ @Test
public void testMtu() throws Exception {
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
@@ -583,7 +597,7 @@
checkMtu(packet, 0, mtuBytes(-1));
}
- @SmallTest
+ @Test
public void testBadHwaddrLength() throws Exception {
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
@@ -652,7 +666,7 @@
assertEquals(expectedClientMac, HexDump.toHexString(offerPacket.getClientMac()));
}
- @SmallTest
+ @Test
public void testPadAndOverloadedOptionsOffer() throws Exception {
// A packet observed in the real world that is interesting for two reasons:
//
@@ -691,7 +705,7 @@
null, "1.1.1.1", null, 43200, false, 0, dhcpResults);
}
- @SmallTest
+ @Test
public void testBug2111() throws Exception {
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
@@ -721,7 +735,7 @@
"domain123.co.uk", "192.0.2.254", null, 49094, false, 0, dhcpResults);
}
- @SmallTest
+ @Test
public void testBug2136() throws Exception {
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
@@ -754,7 +768,7 @@
"lancs.ac.uk", "10.32.255.128", null, 7200, false, 0, dhcpResults);
}
- @SmallTest
+ @Test
public void testUdpServerAnySourcePort() throws Exception {
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
@@ -789,7 +803,7 @@
"wvm.edu", "10.1.105.252", null, 86400, false, 0, dhcpResults);
}
- @SmallTest
+ @Test
public void testUdpInvalidDstPort() throws Exception {
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
@@ -821,7 +835,7 @@
} catch (ParseException expected) {}
}
- @SmallTest
+ @Test
public void testMultipleRouters() throws Exception {
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
@@ -854,7 +868,7 @@
null, "192.171.189.2", null, 28800, false, 0, dhcpResults);
}
- @SmallTest
+ @Test
public void testDiscoverPacket() throws Exception {
short secs = 7;
int transactionId = 0xdeadbeef;
diff --git a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
index 5deba27..6647760 100644
--- a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
+++ b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
@@ -19,20 +19,30 @@
import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.StructNlMsgErr;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import android.util.Log;
+
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import junit.framework.TestCase;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
import libcore.util.HexEncoding;
-public class NetlinkErrorMessageTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetlinkErrorMessageTest {
private final String TAG = "NetlinkErrorMessageTest";
// Hexadecimal representation of packet capture.
@@ -54,7 +64,7 @@
public static final byte[] NLM_ERROR_OK =
HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false);
- @SmallTest
+ @Test
public void testParseNlmErrorOk() {
final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
diff --git a/tests/net/java/android/net/netlink/NetlinkSocketTest.java b/tests/net/java/android/net/netlink/NetlinkSocketTest.java
index 78b3b70..bd36bac8 100644
--- a/tests/net/java/android/net/netlink/NetlinkSocketTest.java
+++ b/tests/net/java/android/net/netlink/NetlinkSocketTest.java
@@ -16,25 +16,35 @@
package android.net.netlink;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
import android.net.netlink.NetlinkSocket;
import android.net.netlink.RtNetlinkNeighborMessage;
import android.net.netlink.StructNdMsg;
import android.net.netlink.StructNlMsgHdr;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import android.system.ErrnoException;
import android.system.NetlinkSocketAddress;
import android.system.OsConstants;
import android.util.Log;
+
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import junit.framework.TestCase;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
-public class NetlinkSocketTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetlinkSocketTest {
private final String TAG = "NetlinkSocketTest";
- @SmallTest
+ @Test
public void testBasicWorkingGetNeighborsQuery() throws Exception {
NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE);
assertNotNull(s);
@@ -93,7 +103,7 @@
s.close();
}
- @SmallTest
+ @Test
public void testRepeatedCloseCallsAreQuiet() throws Exception {
// Create a working NetlinkSocket.
NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE);
diff --git a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
index 029758e..c9fd74f 100644
--- a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
@@ -16,15 +16,19 @@
package android.net.netlink;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.RtNetlinkNeighborMessage;
import android.net.netlink.StructNdMsg;
import android.net.netlink.StructNlMsgHdr;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import android.system.OsConstants;
import android.util.Log;
-import libcore.util.HexEncoding;
import java.net.Inet4Address;
import java.net.InetAddress;
@@ -32,10 +36,15 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
-import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
-public class RtNetlinkNeighborMessageTest extends TestCase {
+import libcore.util.HexEncoding;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class RtNetlinkNeighborMessageTest {
private final String TAG = "RtNetlinkNeighborMessageTest";
// Hexadecimal representation of packet capture.
@@ -136,7 +145,7 @@
public static final byte[] RTM_GETNEIGH_RESPONSE =
HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false);
- @SmallTest
+ @Test
public void testParseRtmDelNeigh() {
final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
@@ -163,7 +172,7 @@
assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination);
}
- @SmallTest
+ @Test
public void testParseRtmNewNeigh() {
final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
@@ -190,7 +199,7 @@
assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination);
}
- @SmallTest
+ @Test
public void testParseRtmGetNeighResponse() {
final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
@@ -215,7 +224,7 @@
assertEquals(14, messageCount);
}
- @SmallTest
+ @Test
public void testCreateRtmNewNeighMessage() {
final int seqNo = 2635;
final int ifIndex = 14;
diff --git a/tests/net/java/android/net/util/BlockingSocketReaderTest.java b/tests/net/java/android/net/util/BlockingSocketReaderTest.java
index 1aad453..29dfa4c 100644
--- a/tests/net/java/android/net/util/BlockingSocketReaderTest.java
+++ b/tests/net/java/android/net/util/BlockingSocketReaderTest.java
@@ -18,15 +18,19 @@
import static android.net.util.BlockingSocketReader.DEFAULT_RECV_BUF_SIZE;
import static android.system.OsConstants.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.os.Handler;
import android.os.HandlerThread;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructTimeval;
-import libcore.io.IoBridge;
-
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
@@ -41,15 +45,21 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import libcore.io.IoBridge;
/**
* Tests for BlockingSocketReader.
*
* @hide
*/
-public class BlockingSocketReaderTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BlockingSocketReaderTest {
static final InetAddress LOOPBACK6 = Inet6Address.getLoopbackAddress();
static final StructTimeval TIMEO = StructTimeval.fromMillis(500);
@@ -103,7 +113,7 @@
}
};
- @Override
+ @Before
public void setUp() {
resetLatch();
mLocalSocket = null;
@@ -115,7 +125,7 @@
mHandlerThread.start();
}
- @Override
+ @After
public void tearDown() throws Exception {
if (mReceiver != null) {
mHandlerThread.getThreadHandler().post(() -> { mReceiver.stop(); });
@@ -143,6 +153,7 @@
sender.close();
}
+ @Test
public void testBasicWorking() throws Exception {
final Handler h = mHandlerThread.getThreadHandler();
mReceiver = new UdpLoopbackReader(h);
@@ -186,6 +197,7 @@
public FileDescriptor createFd() { return null; }
}
+ @Test
public void testMinimalRecvBufSize() throws Exception {
final Handler h = mHandlerThread.getThreadHandler();
diff --git a/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
index dd679bc..38d3d74 100644
--- a/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
+++ b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
@@ -17,18 +17,25 @@
package android.net.util;
import static android.net.util.NetworkConstants.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
import libcore.util.HexEncoding;
-import junit.framework.TestCase;
-
-
/**
* Tests for ConnectivityPacketSummary.
*
* @hide
*/
-public class ConnectivityPacketSummaryTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ConnectivityPacketSummaryTest {
private static final byte[] MYHWADDR = {
asByte(0x80), asByte(0x7a), asByte(0xbf), asByte(0x6f), asByte(0x48), asByte(0xf3)
};
@@ -39,6 +46,7 @@
return ConnectivityPacketSummary.summarize(MYHWADDR, bytes);
}
+ @Test
public void testParseICMPv6DADProbe() {
final String packet =
// Ethernet
@@ -60,6 +68,7 @@
assertEquals(expected, getSummary(packet));
}
+ @Test
public void testParseICMPv6RS() {
final String packet =
// Ethernet
@@ -81,6 +90,7 @@
assertEquals(expected, getSummary(packet));
}
+ @Test
public void testParseICMPv6RA() {
final String packet =
// Ethernet
@@ -113,6 +123,7 @@
assertEquals(expected, getSummary(packet));
}
+ @Test
public void testParseICMPv6NS() {
final String packet =
// Ethernet
@@ -135,6 +146,7 @@
assertEquals(expected, getSummary(packet));
}
+ @Test
public void testInvalidICMPv6NDLength() {
final String packet =
// Ethernet
@@ -159,6 +171,7 @@
assertEquals(expected, getSummary(packet));
}
+ @Test
public void testParseICMPv6NA() {
final String packet =
// Ethernet
@@ -179,6 +192,7 @@
assertEquals(expected, getSummary(packet));
}
+ @Test
public void testParseARPRequest() {
final String packet =
// Ethernet
@@ -197,6 +211,7 @@
assertEquals(expected, getSummary(packet));
}
+ @Test
public void testParseARPReply() {
final String packet =
// Ethernet
@@ -217,6 +232,7 @@
assertEquals(expected, getSummary(packet));
}
+ @Test
public void testParseDHCPv4Discover() {
final String packet =
// Ethernet
@@ -262,6 +278,7 @@
assertTrue(getSummary(packet).startsWith(expectedPrefix));
}
+ @Test
public void testParseDHCPv4Offer() {
final String packet =
// Ethernet
@@ -307,6 +324,7 @@
assertTrue(getSummary(packet).startsWith(expectedPrefix));
}
+ @Test
public void testParseDHCPv4Request() {
final String packet =
// Ethernet
@@ -354,6 +372,7 @@
assertTrue(getSummary(packet).startsWith(expectedPrefix));
}
+ @Test
public void testParseDHCPv4Ack() {
final String packet =
// Ethernet
diff --git a/tests/net/java/android/net/util/IpUtilsTest.java b/tests/net/java/android/net/util/IpUtilsTest.java
index c2d1608..8903bf9 100644
--- a/tests/net/java/android/net/util/IpUtilsTest.java
+++ b/tests/net/java/android/net/util/IpUtilsTest.java
@@ -16,15 +16,19 @@
package android.net.util;
-import android.net.util.IpUtils;
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import java.nio.ByteBuffer;
-import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
-
-public class IpUtilsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpUtilsTest {
private static final int IPV4_HEADER_LENGTH = 20;
private static final int IPV6_HEADER_LENGTH = 40;
@@ -67,7 +71,7 @@
// "hello")
// print JavaPacketDefinition(str(packet))
- @SmallTest
+ @Test
public void testIpv6TcpChecksum() throws Exception {
// packet = (scapy.IPv6(src="2001:db8::1", dst="2001:db8::2", tc=0x80) /
// scapy.TCP(sport=12345, dport=7,
@@ -115,7 +119,7 @@
assertEquals(0, IpUtils.tcpChecksum(packet, 0, IPV6_HEADER_LENGTH, transportLen));
}
- @SmallTest
+ @Test
public void testIpv4UdpChecksum() {
// packet = (scapy.IP(src="192.0.2.1", dst="192.0.2.2", tos=0x40) /
// scapy.UDP(sport=32012, dport=4500) /
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index a423c2a..fb2bd79 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -24,12 +24,15 @@
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import android.content.res.Resources;
import android.net.NetworkStats;
import android.net.TrafficStats;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
+import android.support.test.runner.AndroidJUnit4;
import com.android.frameworks.tests.net.R;
@@ -42,19 +45,23 @@
import libcore.io.IoUtils;
import libcore.io.Streams;
+import org.junit.runner.RunWith;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
/**
* Tests for {@link NetworkStatsFactory}.
*/
+@RunWith(AndroidJUnit4.class)
@SmallTest
-public class NetworkStatsFactoryTest extends AndroidTestCase {
+public class NetworkStatsFactoryTest {
private File mTestProc;
private NetworkStatsFactory mFactory;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
-
- mTestProc = new File(getContext().getFilesDir(), "proc");
+ mTestProc = new File(InstrumentationRegistry.getContext().getFilesDir(), "proc");
if (mTestProc.exists()) {
IoUtils.deleteContents(mTestProc);
}
@@ -62,17 +69,16 @@
mFactory = new NetworkStatsFactory(mTestProc);
}
- @Override
+ @After
public void tearDown() throws Exception {
mFactory = null;
if (mTestProc.exists()) {
IoUtils.deleteContents(mTestProc);
}
-
- super.tearDown();
}
+ @Test
public void testNetworkStatsDetail() throws Exception {
final NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_typical);
@@ -84,6 +90,7 @@
assertStatsEntry(stats, "rmnet2", 10001, SET_DEFAULT, 0x0, 1125899906842624L, 984L);
}
+ @Test
public void testKernelTags() throws Exception {
assertEquals(0, kernelToTag("0x0000000000000000"));
assertEquals(0x32, kernelToTag("0x0000003200000000"));
@@ -98,6 +105,7 @@
assertEquals(TrafficStats.TAG_SYSTEM_DOWNLOAD, kernelToTag("0xffffff0100000000"));
}
+ @Test
public void testNetworkStatsWithSet() throws Exception {
final NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_typical);
assertEquals(70, stats.size());
@@ -106,6 +114,7 @@
assertStatsEntry(stats, "rmnet1", 10021, SET_FOREGROUND, 0x30100000, 742L, 3L, 1265L, 3L);
}
+ @Test
public void testNetworkStatsSingle() throws Exception {
stageFile(R.raw.xt_qtaguid_iface_typical, file("net/xt_qtaguid/iface_stat_all"));
@@ -116,6 +125,7 @@
assertStatsEntry(stats, "test2", UID_ALL, SET_ALL, TAG_NONE, 1L, 2L, 3L, 4L);
}
+ @Test
public void testNetworkStatsXt() throws Exception {
stageFile(R.raw.xt_qtaguid_iface_fmt_typical, file("net/xt_qtaguid/iface_stat_fmt"));
@@ -127,6 +137,7 @@
assertStatsEntry(stats, "rmnet2", UID_ALL, SET_ALL, TAG_NONE, 4968L, 35L, 3081L, 39L);
}
+ @Test
public void testDoubleClatAccounting() throws Exception {
NetworkStatsFactory.noteStackedIface("v4-wlan0", "wlan0");
@@ -161,6 +172,7 @@
NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
}
+ @Test
public void testDoubleClatAccounting100MBDownload() throws Exception {
// Downloading 100mb from an ipv4 only destination in a foreground activity
@@ -197,7 +209,7 @@
InputStream in = null;
OutputStream out = null;
try {
- in = getContext().getResources().openRawResource(rawId);
+ in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
out = new FileOutputStream(file);
Streams.copy(in, out);
} finally {
@@ -251,5 +263,4 @@
assertEquals("unexpected txBytes", txBytes, entry.txBytes);
assertEquals("unexpected txPackets", txPackets, entry.txPackets);
}
-
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 335e6240..d9586c2 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -26,8 +26,13 @@
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.NetworkCapabilities.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
import static com.android.internal.util.TestUtils.waitForIdleHandler;
-
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
@@ -87,9 +92,10 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-import android.test.AndroidTestCase;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -105,7 +111,11 @@
import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPolicyManagerInternal;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
@@ -123,13 +133,16 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
+
/**
* Tests for {@link ConnectivityService}.
*
* Build, install and run with:
* runtest frameworks-net -c com.android.server.ConnectivityServiceTest
*/
-public class ConnectivityServiceTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ConnectivityServiceTest {
private static final String TAG = "ConnectivityServiceTest";
private static final int TIMEOUT_MS = 500;
@@ -141,6 +154,7 @@
private MockNetworkAgent mWiFiNetworkAgent;
private MockNetworkAgent mCellNetworkAgent;
private MockNetworkAgent mEthernetNetworkAgent;
+ private Context mContext;
// This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
// do not go through ConnectivityService but talk to netd directly, so they don't automatically
@@ -242,7 +256,7 @@
waitForIdle(TIMEOUT_MS);
}
- @SmallTest
+ @Test
public void testWaitForIdle() {
final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
@@ -743,7 +757,8 @@
// Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
// can have odd side-effects, like network validations succeeding.
- final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
+ Context context = InstrumentationRegistry.getContext();
+ final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
boolean overlaps = false;
for (Network network : networks) {
if (netId == network.netId) {
@@ -814,9 +829,9 @@
fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
}
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
+ mContext = InstrumentationRegistry.getContext();
// InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
// http://b/25897652 .
@@ -824,7 +839,7 @@
Looper.prepare();
}
- mServiceContext = new MockContext(getContext());
+ mServiceContext = new MockContext(InstrumentationRegistry.getContext());
LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
LocalServices.addService(
NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
@@ -835,7 +850,7 @@
mock(IpConnectivityLog.class));
mService.systemReady();
- mCm = new WrappedConnectivityManager(getContext(), mService);
+ mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
mCm.bindProcessToNetwork(null);
// Ensure that the default setting for Captive Portals is used for most tests
@@ -843,6 +858,7 @@
setMobileDataAlwaysOn(false);
}
+ @After
public void tearDown() throws Exception {
setMobileDataAlwaysOn(false);
if (mCellNetworkAgent != null) {
@@ -857,7 +873,6 @@
mEthernetNetworkAgent.disconnect();
mEthernetNetworkAgent = null;
}
- super.tearDown();
}
private static int transportToLegacyType(int transport) {
@@ -931,6 +946,7 @@
return cv;
}
+ @Test
public void testNetworkTypes() {
// Ensure that our mocks for the networkAttributes config variable work as expected. If they
// don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
@@ -946,7 +962,7 @@
assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
}
- @SmallTest
+ @Test
public void testLingering() throws Exception {
verifyNoNetwork();
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -987,7 +1003,7 @@
verifyNoNetwork();
}
- @SmallTest
+ @Test
public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
// Test bringing up unvalidated WiFi
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -1022,7 +1038,7 @@
verifyNoNetwork();
}
- @SmallTest
+ @Test
public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
// Test bringing up unvalidated cellular.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1048,7 +1064,7 @@
verifyNoNetwork();
}
- @SmallTest
+ @Test
public void testUnlingeringDoesNotValidate() throws Exception {
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -1076,7 +1092,7 @@
NET_CAPABILITY_VALIDATED));
}
- @SmallTest
+ @Test
public void testCellularOutscoresWeakWifi() throws Exception {
// Test bringing up validated cellular.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1102,7 +1118,7 @@
verifyActiveNetwork(TRANSPORT_WIFI);
}
- @SmallTest
+ @Test
public void testReapingNetwork() throws Exception {
// Test bringing up WiFi without NET_CAPABILITY_INTERNET.
// Expect it to be torn down immediately because it satisfies no requests.
@@ -1135,7 +1151,7 @@
waitFor(cv);
}
- @SmallTest
+ @Test
public void testCellularFallback() throws Exception {
// Test bringing up validated cellular.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1173,7 +1189,7 @@
verifyActiveNetwork(TRANSPORT_WIFI);
}
- @SmallTest
+ @Test
public void testWiFiFallback() throws Exception {
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -1387,7 +1403,7 @@
}
}
- @SmallTest
+ @Test
public void testStateChangeNetworkCallbacks() throws Exception {
final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
@@ -1477,7 +1493,7 @@
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
}
- @SmallTest
+ @Test
public void testMultipleLingering() {
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
@@ -1705,7 +1721,7 @@
mCm.unregisterNetworkCallback(trackDefaultCallback);
}
- @SmallTest
+ @Test
public void testExplicitlySelected() {
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
@@ -1872,7 +1888,7 @@
handlerThread.quit();
}
- @SmallTest
+ @Test
public void testNetworkFactoryRequests() throws Exception {
tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
@@ -1892,7 +1908,7 @@
// Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
}
- @SmallTest
+ @Test
public void testNoMutableNetworkRequests() throws Exception {
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
NetworkRequest request1 = new NetworkRequest.Builder()
@@ -1909,7 +1925,7 @@
assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
}
- @SmallTest
+ @Test
public void testMMSonWiFi() throws Exception {
// Test bringing up cellular without MMS NetworkRequest gets reaped
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1948,7 +1964,7 @@
verifyActiveNetwork(TRANSPORT_WIFI);
}
- @SmallTest
+ @Test
public void testMMSonCell() throws Exception {
// Test bringing up cellular without MMS
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1977,7 +1993,7 @@
verifyActiveNetwork(TRANSPORT_CELLULAR);
}
- @SmallTest
+ @Test
public void testCaptivePortal() {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
@@ -2028,7 +2044,7 @@
validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
}
- @SmallTest
+ @Test
public void testCaptivePortalApp() {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
@@ -2074,7 +2090,7 @@
mCm.unregisterNetworkCallback(captivePortalCallback);
}
- @SmallTest
+ @Test
public void testAvoidOrIgnoreCaptivePortals() {
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
@@ -2119,7 +2135,7 @@
return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
}
- @SmallTest
+ @Test
public void testNetworkSpecifier() {
NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
@@ -2180,7 +2196,7 @@
assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
}
- @SmallTest
+ @Test
public void testInvalidNetworkSpecifier() {
try {
NetworkRequest.Builder builder = new NetworkRequest.Builder();
@@ -2241,7 +2257,7 @@
}
}
- @SmallTest
+ @Test
public void testNetworkSpecifierUidSpoofSecurityException() {
class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
@Override
@@ -2275,7 +2291,7 @@
}
}
- @SmallTest
+ @Test
public void testRegisterDefaultNetworkCallback() throws Exception {
final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
@@ -2324,7 +2340,7 @@
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
}
- @SmallTest
+ @Test
public void testAdditionalStateCallbacks() throws Exception {
// File a network request for mobile.
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
@@ -2385,7 +2401,7 @@
return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
}
- @SmallTest
+ @Test
public void testBackgroundNetworks() throws Exception {
// Create a background request. We can't do this ourselves because ConnectivityService
// doesn't have an API for it. So just turn on mobile data always on.
@@ -2554,7 +2570,7 @@
return false;
}
- @SmallTest
+ @Test
public void testMobileDataAlwaysOn() throws Exception {
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
final NetworkRequest cellRequest = new NetworkRequest.Builder()
@@ -2619,7 +2635,7 @@
handlerThread.quit();
}
- @SmallTest
+ @Test
public void testAvoidBadWifiSetting() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
@@ -2657,7 +2673,7 @@
assertTrue(tracker.shouldNotifyWifiUnvalidated());
}
- @SmallTest
+ @Test
public void testAvoidBadWifi() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
@@ -2784,7 +2800,7 @@
mCm.unregisterNetworkCallback(defaultCallback);
}
- @SmallTest
+ @Test
public void testMeteredMultipathPreferenceSetting() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
@@ -2808,7 +2824,7 @@
* Validate that a satisfied network request does not trigger onUnavailable() once the
* time-out period expires.
*/
- @SmallTest
+ @Test
public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
@@ -2828,7 +2844,7 @@
* Validate that a satisfied network request followed by a disconnected (lost) network does
* not trigger onUnavailable() once the time-out period expires.
*/
- @SmallTest
+ @Test
public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
@@ -2852,7 +2868,7 @@
* callback is called when time-out expires. Then validate that if network request is
* (somehow) satisfied - the callback isn't called later.
*/
- @SmallTest
+ @Test
public void testTimedoutNetworkRequest() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
@@ -2873,7 +2889,7 @@
* Validate that when a network request is unregistered (cancelled), no posterior event can
* trigger the callback.
*/
- @SmallTest
+ @Test
public void testNoCallbackAfterUnregisteredNetworkRequest() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
@@ -2981,7 +2997,7 @@
return mWiFiNetworkAgent.getNetwork();
}
- @SmallTest
+ @Test
public void testPacketKeepalives() throws Exception {
InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
@@ -3105,7 +3121,7 @@
callback3.expectStopped();
}
- @SmallTest
+ @Test
public void testGetCaptivePortalServerUrl() throws Exception {
String url = mCm.getCaptivePortalServerUrl();
assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
@@ -3150,7 +3166,7 @@
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
}
- @SmallTest
+ @Test
public void testNetworkPinner() {
NetworkRequest wifiRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI)
@@ -3210,7 +3226,7 @@
assertPinnedToWifiWithCellDefault();
}
- @SmallTest
+ @Test
public void testNetworkCallbackMaximum() {
final int MAX_REQUESTS = 100;
final int CALLBACKS = 90;
@@ -3302,7 +3318,7 @@
}
}
- @SmallTest
+ @Test
public void testNetworkInfoOfTypeNone() {
ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
@@ -3342,7 +3358,7 @@
}
}
- @SmallTest
+ @Test
public void testDeprecatedAndUnsupportedOperations() throws Exception {
final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
assertNull(mCm.getNetworkInfo(TYPE_NONE));
@@ -3363,7 +3379,7 @@
assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
}
- @SmallTest
+ @Test
public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
final NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI).build();
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index efc58cc..83ee361 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -36,6 +36,7 @@
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.system.ErrnoException;
import android.system.Os;
@@ -48,11 +49,10 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
/** Unit tests for {@link IpSecService}. */
@SmallTest
-@RunWith(JUnit4.class)
+@RunWith(AndroidJUnit4.class)
public class IpSecServiceTest {
private static final int DROID_SPI = 0xD1201D;
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 77956be..354cf2f 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -16,24 +16,8 @@
package com.android.server.connectivity;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkMisc;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.format.DateUtils;
-import com.android.internal.R;
-import com.android.server.ConnectivityService;
-import com.android.server.connectivity.NetworkNotificationManager;
-import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
-import junit.framework.TestCase;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
@@ -44,7 +28,32 @@
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.reset;
-public class LingerMonitorTest extends TestCase {
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkMisc;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
+import android.text.format.DateUtils;
+
+import com.android.internal.R;
+import com.android.server.ConnectivityService;
+import com.android.server.connectivity.NetworkNotificationManager;
+import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LingerMonitorTest {
static final String CELLULAR = "CELLULAR";
static final String WIFI = "WIFI";
@@ -62,6 +71,7 @@
@Mock NetworkNotificationManager mNotifier;
@Mock Resources mResources;
+ @Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mCtx.getResources()).thenReturn(mResources);
@@ -71,7 +81,7 @@
mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT);
}
- @SmallTest
+ @Test
public void testTransitions() {
setNotificationSwitch(transition(WIFI, CELLULAR));
NetworkAgentInfo nai1 = wifiNai(100);
@@ -81,7 +91,7 @@
assertFalse(mMonitor.isNotificationEnabled(nai2, nai1));
}
- @SmallTest
+ @Test
public void testNotificationOnLinger() {
setNotificationSwitch(transition(WIFI, CELLULAR));
setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -92,7 +102,7 @@
verifyNotification(from, to);
}
- @SmallTest
+ @Test
public void testToastOnLinger() {
setNotificationSwitch(transition(WIFI, CELLULAR));
setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
@@ -103,7 +113,7 @@
verifyToast(from, to);
}
- @SmallTest
+ @Test
public void testNotificationClearedAfterDisconnect() {
setNotificationSwitch(transition(WIFI, CELLULAR));
setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -117,7 +127,7 @@
verify(mNotifier, times(1)).clearNotification(100);
}
- @SmallTest
+ @Test
public void testNotificationClearedAfterSwitchingBack() {
setNotificationSwitch(transition(WIFI, CELLULAR));
setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -131,7 +141,7 @@
verify(mNotifier, times(1)).clearNotification(100);
}
- @SmallTest
+ @Test
public void testUniqueToast() {
setNotificationSwitch(transition(WIFI, CELLULAR));
setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
@@ -149,7 +159,7 @@
verifyNoNotifications();
}
- @SmallTest
+ @Test
public void testMultipleNotifications() {
setNotificationSwitch(transition(WIFI, CELLULAR));
setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -168,7 +178,7 @@
verifyNotification(wifi2, cell);
}
- @SmallTest
+ @Test
public void testRateLimiting() throws InterruptedException {
mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, LOW_RATE_LIMIT);
@@ -194,7 +204,7 @@
verifyNoNotifications();
}
- @SmallTest
+ @Test
public void testDailyLimiting() throws InterruptedException {
mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT);
@@ -221,7 +231,7 @@
verifyNoNotifications();
}
- @SmallTest
+ @Test
public void testUniqueNotification() {
setNotificationSwitch(transition(WIFI, CELLULAR));
setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -238,7 +248,7 @@
verifyNotification(from, to);
}
- @SmallTest
+ @Test
public void testIgnoreNeverValidatedNetworks() {
setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
setNotificationSwitch(transition(WIFI, CELLULAR));
@@ -250,7 +260,7 @@
verifyNoNotifications();
}
- @SmallTest
+ @Test
public void testIgnoreCurrentlyValidatedNetworks() {
setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
setNotificationSwitch(transition(WIFI, CELLULAR));
@@ -262,7 +272,7 @@
verifyNoNotifications();
}
- @SmallTest
+ @Test
public void testNoNotificationType() {
setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
setNotificationSwitch();
@@ -273,7 +283,7 @@
verifyNoNotifications();
}
- @SmallTest
+ @Test
public void testNoTransitionToNotify() {
setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE);
setNotificationSwitch(transition(WIFI, CELLULAR));
@@ -284,7 +294,7 @@
verifyNoNotifications();
}
- @SmallTest
+ @Test
public void testDifferentTransitionToNotify() {
setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
setNotificationSwitch(transition(CELLULAR, WIFI));
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 911347c..125fe725 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -34,20 +34,29 @@
import android.content.res.Resources;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
+
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import junit.framework.TestCase;
+
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-public class NetworkNotificationManagerTest extends TestCase {
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkNotificationManagerTest {
static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
@@ -71,6 +80,7 @@
NetworkNotificationManager mManager;
+ @Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mCaptor = ArgumentCaptor.forClass(Notification.class);
@@ -87,7 +97,7 @@
mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
}
- @SmallTest
+ @Test
public void testNotificationsShownAndCleared() {
final int NETWORK_ID_BASE = 100;
List<NotificationType> types = Arrays.asList(NotificationType.values());
@@ -117,7 +127,7 @@
}
}
- @SmallTest
+ @Test
public void testNoInternetNotificationsNotShownForCellular() {
mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
@@ -131,7 +141,7 @@
verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
}
- @SmallTest
+ @Test
public void testNotificationsNotShownIfNoInternetCapability() {
mWifiNai.networkCapabilities = new NetworkCapabilities();
mWifiNai.networkCapabilities .addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
@@ -142,7 +152,7 @@
verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
}
- @SmallTest
+ @Test
public void testDuplicatedNotificationsNoInternetThenSignIn() {
final int id = 101;
final String tag = NetworkNotificationManager.tagFor(id);
@@ -164,7 +174,7 @@
verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
}
- @SmallTest
+ @Test
public void testDuplicatedNotificationsSignInThenNoInternet() {
final int id = 101;
final String tag = NetworkNotificationManager.tagFor(id);
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 4f18da7..fe396c3 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -20,6 +20,9 @@
import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
import static android.content.pm.UserInfo.FLAG_PRIMARY;
import static android.content.pm.UserInfo.FLAG_RESTRICTED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalMatchers.*;
import static org.mockito.Mockito.*;
@@ -42,14 +45,17 @@
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.R;
import com.android.internal.net.VpnConfig;
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.Test;
import org.mockito.Answers;
import org.mockito.InOrder;
import org.mockito.Mock;
@@ -61,13 +67,16 @@
import java.util.Map;
import java.util.Set;
+
/**
* Tests for {@link Vpn}.
*
* Build, install and run with:
- * runtest --path java/com/android/server/connectivity/VpnTest.java
+ * runtest frameworks-net -c com.android.server.connectivity.VpnTest
*/
-public class VpnTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VpnTest {
private static final String TAG = "VpnTest";
// Mock users
@@ -106,7 +115,7 @@
@Mock private NotificationManager mNotificationManager;
@Mock private Vpn.SystemServices mSystemServices;
- @Override
+ @Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -130,7 +139,7 @@
doNothing().when(mNetService).registerObserver(any());
}
- @SmallTest
+ @Test
public void testRestrictedProfilesAreAddedToVpn() {
setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
@@ -144,7 +153,7 @@
})), ranges);
}
- @SmallTest
+ @Test
public void testManagedProfilesAreNotAddedToVpn() {
setMockedUsers(primaryUser, managedProfileA);
@@ -157,7 +166,7 @@
})), ranges);
}
- @SmallTest
+ @Test
public void testAddUserToVpnOnlyAddsOneUser() {
setMockedUsers(primaryUser, restrictedProfileA, managedProfileA);
@@ -170,7 +179,7 @@
})), ranges);
}
- @SmallTest
+ @Test
public void testUidWhiteAndBlacklist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id);
@@ -195,7 +204,7 @@
})), disallow);
}
- @SmallTest
+ @Test
public void testLockdownChangingPackage() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id);
@@ -230,7 +239,7 @@
assertUnblocked(vpn, user.start + PKG_UIDS[3]);
}
- @SmallTest
+ @Test
public void testLockdownAddingAProfile() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
setMockedUsers(primaryUser);
@@ -270,7 +279,7 @@
}));
}
- @SmallTest
+ @Test
public void testLockdownRuleRepeatability() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
@@ -293,7 +302,7 @@
verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class));
}
- @SmallTest
+ @Test
public void testLockdownRuleReversibility() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
@@ -322,7 +331,7 @@
order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser));
}
- @SmallTest
+ @Test
public void testIsAlwaysOnPackageSupported() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
@@ -356,7 +365,7 @@
assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0]));
}
- @SmallTest
+ @Test
public void testNotificationShownForAlwaysOnApp() {
final UserHandle userHandle = UserHandle.of(primaryUser.id);
final Vpn vpn = createVpn(primaryUser.id);
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 4aeae70..9c4da1f 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -24,7 +24,6 @@
import android.view.IWindowManager;
import junit.framework.TestCase;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
/**
diff --git a/tools/incident_report/main.cpp b/tools/incident_report/main.cpp
index d4ad340..cc25264 100644
--- a/tools/incident_report/main.cpp
+++ b/tools/incident_report/main.cpp
@@ -97,8 +97,8 @@
message->addInt64(fieldId, value64);
break;
} else {
- fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d\n", tag, tag,
- in->CurrentPosition());
+ fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d of field %s\n",
+ tag, tag, in->CurrentPosition(), descriptor->name().c_str());
return false;
}
case WireFormatLite::WIRETYPE_FIXED64:
@@ -106,14 +106,14 @@
message->addInt64(fieldId, value64);
break;
} else {
- fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d\n", tag, tag,
- in->CurrentPosition());
+ fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d of field %s\n",
+ tag, tag, in->CurrentPosition(), descriptor->name().c_str());
return false;
}
case WireFormatLite::WIRETYPE_LENGTH_DELIMITED:
if (!read_length_delimited(in, fieldId, descriptor, message)) {
- fprintf(stderr, "bad LENGTH_DELIMITED: 0x%x (%d) at index %d\n",
- tag, tag, in->CurrentPosition());
+ fprintf(stderr, "bad LENGTH_DELIMITED: 0x%x (%d) at index %d of field %s\n",
+ tag, tag, in->CurrentPosition(), descriptor->name().c_str());
return false;
}
break;
@@ -122,13 +122,13 @@
message->addInt32(fieldId, value32);
break;
} else {
- fprintf(stderr, "bad FIXED32: 0x%x (%d) at index %d\n", tag, tag,
- in->CurrentPosition());
+ fprintf(stderr, "bad FIXED32: 0x%x (%d) at index %d of field %s\n",
+ tag, tag, in->CurrentPosition(), descriptor->name().c_str());
return false;
}
default:
- fprintf(stderr, "bad tag: 0x%x (%d) at index %d\n", tag, tag,
- in->CurrentPosition());
+ fprintf(stderr, "bad tag: 0x%x (%d) at index %d of field %s\n", tag, tag,
+ in->CurrentPosition(), descriptor->name().c_str());
return false;
}
}
@@ -153,7 +153,8 @@
out->printf("%f", *(float*)&node.value32);
break;
default:
- out->printf("(unexpected value32 %d (0x%x)", node.value32, node.value32);
+ out->printf("(unexpected type %d: value32 %d (0x%x)",
+ type, node.value32, node.value32);
break;
}
break;
@@ -194,7 +195,8 @@
}
break;
default:
- out->printf("(unexpected value64 %lld (0x%x))", node.value64, node.value64);
+ out->printf("(unexpected type %d: value64 %lld (0x%x))",
+ type, node.value64, node.value64);
break;
}
break;
diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp
index 24068e9..756549c 100644
--- a/tools/streaming_proto/Android.bp
+++ b/tools/streaming_proto/Android.bp
@@ -17,13 +17,31 @@
// ==========================================================
// Build the host executable: protoc-gen-javastream
// ==========================================================
-cc_binary_host {
- name: "protoc-gen-javastream",
+cc_defaults {
+ name: "protoc-gen-stream-defaults",
srcs: [
"Errors.cpp",
"string_utils.cpp",
- "main.cpp",
+ ],
+}
+
+
+cc_binary_host {
+ name: "protoc-gen-javastream",
+ srcs: [
+ "java/main.cpp",
],
+ defaults: ["protoc-gen-stream-defaults"],
+ shared_libs: ["libprotoc"],
+}
+
+cc_binary_host {
+ name: "protoc-gen-cppstream",
+ srcs: [
+ "cpp/main.cpp",
+ ],
+
+ defaults: ["protoc-gen-stream-defaults"],
shared_libs: ["libprotoc"],
}
diff --git a/tools/streaming_proto/Errors.cpp b/tools/streaming_proto/Errors.cpp
index 91c6b92..0cd9037 100644
--- a/tools/streaming_proto/Errors.cpp
+++ b/tools/streaming_proto/Errors.cpp
@@ -3,7 +3,7 @@
#include <stdlib.h>
namespace android {
-namespace javastream_proto {
+namespace stream_proto {
Errors ERRORS;
@@ -82,6 +82,6 @@
return m_errors.size() > 0;
}
-} // namespace javastream_proto
+} // namespace stream_proto
} // namespace android
diff --git a/tools/streaming_proto/Errors.h b/tools/streaming_proto/Errors.h
index 109195a..f14bbfd 100644
--- a/tools/streaming_proto/Errors.h
+++ b/tools/streaming_proto/Errors.h
@@ -4,7 +4,7 @@
#include <vector>
namespace android {
-namespace javastream_proto {
+namespace stream_proto {
using namespace std;
@@ -44,5 +44,5 @@
extern const int UNKNOWN_LINE;
-} // namespace javastream_proto
+} // namespace stream_proto
} // namespace android
diff --git a/tools/streaming_proto/cpp/main.cpp b/tools/streaming_proto/cpp/main.cpp
new file mode 100644
index 0000000..d4e1b7a
--- /dev/null
+++ b/tools/streaming_proto/cpp/main.cpp
@@ -0,0 +1,273 @@
+#include "Errors.h"
+#include "string_utils.h"
+
+#include "google/protobuf/compiler/plugin.pb.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/text_format.h"
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+using namespace android::stream_proto;
+using namespace google::protobuf;
+using namespace google::protobuf::compiler;
+using namespace google::protobuf::io;
+using namespace std;
+
+/**
+ * Position of the field type in a (long long) fieldId.
+ */
+const uint64_t FIELD_TYPE_SHIFT = 32;
+
+//
+// FieldId flags for whether the field is single, repeated or packed.
+// TODO: packed is not supported yet.
+//
+const uint64_t FIELD_COUNT_SHIFT = 40;
+const uint64_t FIELD_COUNT_MASK = 0x0fULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_UNKNOWN = 0;
+const uint64_t FIELD_COUNT_SINGLE = 1ULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_REPEATED = 2ULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_PACKED = 4ULL << FIELD_COUNT_SHIFT;
+
+// Indent
+const string INDENT = " ";
+
+/**
+ * See if this is the file for this request, and not one of the imported ones.
+ */
+static bool
+should_generate_for_file(const CodeGeneratorRequest& request, const string& file)
+{
+ const int N = request.file_to_generate_size();
+ for (int i=0; i<N; i++) {
+ if (request.file_to_generate(i) == file) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static string
+make_filename(const FileDescriptorProto& file_descriptor)
+{
+ return file_descriptor.name() + ".h";
+}
+
+static string
+get_proto_type(const FieldDescriptorProto& field)
+{
+ switch (field.type()) {
+ case FieldDescriptorProto::TYPE_DOUBLE:
+ return "double";
+ case FieldDescriptorProto::TYPE_FLOAT:
+ return "float";
+ case FieldDescriptorProto::TYPE_INT64:
+ return "int64";
+ case FieldDescriptorProto::TYPE_UINT64:
+ return "uint64";
+ case FieldDescriptorProto::TYPE_INT32:
+ return "int32";
+ case FieldDescriptorProto::TYPE_FIXED64:
+ return "fixed64";
+ case FieldDescriptorProto::TYPE_FIXED32:
+ return "fixed32";
+ case FieldDescriptorProto::TYPE_BOOL:
+ return "bool";
+ case FieldDescriptorProto::TYPE_STRING:
+ return "string";
+ case FieldDescriptorProto::TYPE_GROUP:
+ return "group<unsupported!>";
+ case FieldDescriptorProto::TYPE_MESSAGE:
+ return field.type_name();
+ case FieldDescriptorProto::TYPE_BYTES:
+ return "bytes";
+ case FieldDescriptorProto::TYPE_UINT32:
+ return "uint32";
+ case FieldDescriptorProto::TYPE_ENUM:
+ return field.type_name();
+ case FieldDescriptorProto::TYPE_SFIXED32:
+ return "sfixed32";
+ case FieldDescriptorProto::TYPE_SFIXED64:
+ return "sfixed64";
+ case FieldDescriptorProto::TYPE_SINT32:
+ return "sint32";
+ case FieldDescriptorProto::TYPE_SINT64:
+ return "sint64";
+ default:
+ // won't happen
+ return "void";
+ }
+}
+
+static void
+write_enum(stringstream& text, const EnumDescriptorProto& enu, const string& indent)
+{
+ const int N = enu.value_size();
+ text << indent << "// enum " << enu.name() << endl;
+ for (int i=0; i<N; i++) {
+ const EnumValueDescriptorProto& value = enu.value(i);
+ text << indent << "const uint32_t "
+ << make_constant_name(value.name())
+ << " = " << value.number() << ";" << endl;
+ }
+ text << endl;
+}
+
+static uint64_t
+get_field_id(const FieldDescriptorProto& field)
+{
+ // Number
+ uint64_t result = (uint64_t)field.number();
+
+ // Type
+ result |= (uint64_t)field.type() << FIELD_TYPE_SHIFT;
+
+ // Count
+ if (field.options().packed()) {
+ result |= FIELD_COUNT_PACKED;
+ } else if (field.label() == FieldDescriptorProto::LABEL_REPEATED) {
+ result |= FIELD_COUNT_REPEATED;
+ } else {
+ result |= FIELD_COUNT_SINGLE;
+ }
+
+ return result;
+}
+
+static void
+write_field(stringstream& text, const FieldDescriptorProto& field, const string& indent)
+{
+ string optional_comment = field.label() == FieldDescriptorProto::LABEL_OPTIONAL
+ ? "optional " : "";
+ string repeated_comment = field.label() == FieldDescriptorProto::LABEL_REPEATED
+ ? "repeated " : "";
+ string proto_type = get_proto_type(field);
+ string packed_comment = field.options().packed()
+ ? " [packed=true]" : "";
+ text << indent << "// " << optional_comment << repeated_comment << proto_type << ' '
+ << field.name() << " = " << field.number() << packed_comment << ';' << endl;
+
+ text << indent << "const uint64_t " << make_constant_name(field.name()) << " = 0x";
+
+ ios::fmtflags fmt(text.flags());
+ text << setfill('0') << setw(16) << hex << get_field_id(field);
+ text.flags(fmt);
+
+ text << "LL;" << endl;
+
+ text << endl;
+}
+
+static void
+write_message(stringstream& text, const DescriptorProto& message, const string& indent)
+{
+ int N;
+ const string indented = indent + INDENT;
+
+ text << indent << "// message " << message.name() << endl;
+ text << indent << "class " << message.name() << " {" << endl;
+ text << indent << "public:" << endl;
+
+ // Enums
+ N = message.enum_type_size();
+ for (int i=0; i<N; i++) {
+ write_enum(text, message.enum_type(i), indented);
+ }
+
+ // Nested classes
+ N = message.nested_type_size();
+ for (int i=0; i<N; i++) {
+ write_message(text, message.nested_type(i), indented);
+ }
+
+ // Fields
+ N = message.field_size();
+ for (int i=0; i<N; i++) {
+ write_field(text, message.field(i), indented);
+ }
+
+ text << indent << "};" << endl;
+ text << endl;
+}
+
+static void
+write_cpp_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor)
+{
+ stringstream text;
+
+ text << "// Generated by protoc-gen-cppstream. DO NOT MODIFY." << endl;
+ text << "// source: " << file_descriptor.name() << endl << endl;
+
+ string header = "ANDROID_" + replace_string(file_descriptor.name(), '/', '_');
+ header = replace_string(header, '.', '_') + "_stream_h";
+ header = make_constant_name(header);
+
+ text << "#ifndef " << header << endl;
+ text << "#define " << header << endl;
+ text << endl;
+
+ vector<string> namespaces = split(file_descriptor.package(), '.');
+ for (vector<string>::iterator it = namespaces.begin(); it != namespaces.end(); it++) {
+ text << "namespace " << *it << " {" << endl;
+ }
+ text << endl;
+
+ size_t N;
+ N = file_descriptor.enum_type_size();
+ for (size_t i=0; i<N; i++) {
+ write_enum(text, file_descriptor.enum_type(i), "");
+ }
+
+ N = file_descriptor.message_type_size();
+ for (size_t i=0; i<N; i++) {
+ write_message(text, file_descriptor.message_type(i), "");
+ }
+
+ for (vector<string>::iterator it = namespaces.begin(); it != namespaces.end(); it++) {
+ text << "} // " << *it << endl;
+ }
+
+ text << endl;
+ text << "#endif // " << header << endl;
+
+ CodeGeneratorResponse::File* file_response = response->add_file();
+ file_response->set_name(make_filename(file_descriptor));
+ file_response->set_content(text.str());
+}
+
+int main(int argc, char const *argv[])
+{
+ (void)argc;
+ (void)argv;
+
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ CodeGeneratorRequest request;
+ CodeGeneratorResponse response;
+
+ // Read the request
+ request.ParseFromIstream(&cin);
+
+ // Build the files we need.
+ const int N = request.proto_file_size();
+ for (int i=0; i<N; i++) {
+ const FileDescriptorProto& file_descriptor = request.proto_file(i);
+ if (should_generate_for_file(request, file_descriptor.name())) {
+ write_cpp_file(&response, file_descriptor);
+ }
+ }
+
+ // If we had errors, don't write the response. Print the errors and exit.
+ if (ERRORS.HasErrors()) {
+ ERRORS.Print();
+ return 1;
+ }
+
+ // If we didn't have errors, write the response and exit happily.
+ response.SerializeToOstream(&cout);
+
+ /* code */
+ return 0;
+}
\ No newline at end of file
diff --git a/tools/streaming_proto/main.cpp b/tools/streaming_proto/java/main.cpp
similarity index 99%
rename from tools/streaming_proto/main.cpp
rename to tools/streaming_proto/java/main.cpp
index 5b4ba04..b7d594b 100644
--- a/tools/streaming_proto/main.cpp
+++ b/tools/streaming_proto/java/main.cpp
@@ -12,7 +12,7 @@
#include <sstream>
#include <map>
-using namespace android::javastream_proto;
+using namespace android::stream_proto;
using namespace google::protobuf;
using namespace google::protobuf::compiler;
using namespace google::protobuf::io;
diff --git a/tools/streaming_proto/string_utils.cpp b/tools/streaming_proto/string_utils.cpp
index cc738c4..bd34ab7 100644
--- a/tools/streaming_proto/string_utils.cpp
+++ b/tools/streaming_proto/string_utils.cpp
@@ -3,7 +3,7 @@
#include <iostream>
namespace android {
-namespace javastream_proto {
+namespace stream_proto {
using namespace std;
@@ -89,7 +89,26 @@
return result;
}
-} // namespace javastream_proto
+vector<string>
+split(const string& str, const char delimiter)
+{
+ vector<string> result;
+ size_t base = 0, found = 0;
+ while (true) {
+ found = str.find_first_of(delimiter, base);
+ if (found != base) {
+ string part = str.substr(base, found - base);
+ if (!part.empty()) {
+ result.push_back(part);
+ }
+ }
+ if (found == str.npos) break;
+ base = found + 1;
+ }
+ return result;
+}
+
+} // namespace stream_proto
} // namespace android
diff --git a/tools/streaming_proto/string_utils.h b/tools/streaming_proto/string_utils.h
index ffe83ca..03284d1 100644
--- a/tools/streaming_proto/string_utils.h
+++ b/tools/streaming_proto/string_utils.h
@@ -1,7 +1,8 @@
#include <string>
+#include <vector>
namespace android {
-namespace javastream_proto {
+namespace stream_proto {
using namespace std;
@@ -26,7 +27,11 @@
*/
string replace_string(const string& str, const char replace, const char with);
+/**
+ * Split a string to parts by delimiter.
+ */
+vector<string> split(const string& str, const char delimiter);
-} // namespace javastream_proto
+} // namespace stream_proto
} // namespace android