Merge "Remove WifiNetworkScoreCache fake"
diff --git a/Android.mk b/Android.mk
index 75e9a24..6186c55 100644
--- a/Android.mk
+++ b/Android.mk
@@ -618,8 +618,6 @@
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 6504271..79816ac 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6674,6 +6674,9 @@
method public int getInputType();
method public int getLeft();
method public android.os.LocaleList getLocaleList();
+ method public int getMaxTextEms();
+ method public int getMaxTextLength();
+ method public int getMinTextEms();
method public int getScrollX();
method public int getScrollY();
method public java.lang.CharSequence getText();
@@ -47015,6 +47018,9 @@
method public abstract void setInputType(int);
method public abstract void setLocaleList(android.os.LocaleList);
method public abstract void setLongClickable(boolean);
+ method public abstract void setMaxTextEms(int);
+ method public abstract void setMaxTextLength(int);
+ method public abstract void setMinTextEms(int);
method public abstract void setOpaque(boolean);
method public abstract void setSelected(boolean);
method public abstract void setText(java.lang.CharSequence);
diff --git a/api/system-current.txt b/api/system-current.txt
index 0d1e8f05..40683d3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6925,6 +6925,9 @@
method public int getInputType();
method public int getLeft();
method public android.os.LocaleList getLocaleList();
+ method public int getMaxTextEms();
+ method public int getMaxTextLength();
+ method public int getMinTextEms();
method public int getScrollX();
method public int getScrollY();
method public java.lang.CharSequence getText();
@@ -50740,6 +50743,9 @@
method public abstract void setInputType(int);
method public abstract void setLocaleList(android.os.LocaleList);
method public abstract void setLongClickable(boolean);
+ method public abstract void setMaxTextEms(int);
+ method public abstract void setMaxTextLength(int);
+ method public abstract void setMinTextEms(int);
method public abstract void setOpaque(boolean);
method public abstract void setSelected(boolean);
method public abstract void setText(java.lang.CharSequence);
diff --git a/api/test-current.txt b/api/test-current.txt
index f55d9db..4458710 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6743,6 +6743,9 @@
method public int getInputType();
method public int getLeft();
method public android.os.LocaleList getLocaleList();
+ method public int getMaxTextEms();
+ method public int getMaxTextLength();
+ method public int getMinTextEms();
method public int getScrollX();
method public int getScrollY();
method public java.lang.CharSequence getText();
@@ -47596,6 +47599,9 @@
method public abstract void setInputType(int);
method public abstract void setLocaleList(android.os.LocaleList);
method public abstract void setLongClickable(boolean);
+ method public abstract void setMaxTextEms(int);
+ method public abstract void setMaxTextLength(int);
+ method public abstract void setMinTextEms(int);
method public abstract void setOpaque(boolean);
method public abstract void setSelected(boolean);
method public abstract void setText(java.lang.CharSequence);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index dff43ed..027e811 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1829,22 +1829,6 @@
}
/**
- * Completely remove the given task.
- *
- * @param taskId Identifier of the task to be removed.
- * @return Returns true if the given task was found and removed.
- *
- * @hide
- */
- public boolean removeTask(int taskId) throws SecurityException {
- try {
- return getService().removeTask(taskId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Sets the windowing mode for a specific task. Only works on tasks of type
* {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}
* @param taskId The id of the task to set the windowing mode for.
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 402e209..895d12a 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -77,7 +77,7 @@
}
@Override
- public void onTaskRemovalStarted(int taskId) {
+ public void onTaskRemovalStarted(int taskId) throws RemoteException {
}
@Override
@@ -91,11 +91,10 @@
}
@Override
- public void onTaskProfileLocked(int taskId, int userId) {
+ public void onTaskProfileLocked(int taskId, int userId) throws RemoteException {
}
@Override
- public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot)
- throws RemoteException {
+ public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) throws RemoteException {
}
}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index d9b7cd7..e491a4f 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -616,6 +616,9 @@
CharSequence[] mAutofillOptions;
boolean mSanitized;
HtmlInfo mHtmlInfo;
+ int mMinEms = -1;
+ int mMaxEms = -1;
+ int mMaxLength = -1;
// POJO used to override some autofill-related values when the node is parcelized.
// Not written to parcel.
@@ -713,6 +716,9 @@
if (p instanceof HtmlInfo) {
mHtmlInfo = (HtmlInfo) p;
}
+ mMinEms = in.readInt();
+ mMaxEms = in.readInt();
+ mMaxLength = in.readInt();
}
if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
mX = in.readInt();
@@ -876,6 +882,9 @@
} else {
out.writeParcelable(null, 0);
}
+ out.writeInt(mMinEms);
+ out.writeInt(mMaxEms);
+ out.writeInt(mMaxLength);
}
if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
out.writeInt(mX);
@@ -1444,6 +1453,39 @@
public ViewNode getChildAt(int index) {
return mChildren[index];
}
+
+ /**
+ * Returns the minimum width in ems of the text associated with this node, or {@code -1}
+ * if not supported by the node.
+ *
+ * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
+ * not for assist purposes.
+ */
+ public int getMinTextEms() {
+ return mMinEms;
+ }
+
+ /**
+ * Returns the maximum width in ems of the text associated with this node, or {@code -1}
+ * if not supported by the node.
+ *
+ * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
+ * not for assist purposes.
+ */
+ public int getMaxTextEms() {
+ return mMaxEms;
+ }
+
+ /**
+ * Returns the maximum length of the text associated with this node node, or {@code -1}
+ * if not supported by the node or not set.
+ *
+ * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
+ * not for assist purposes.
+ */
+ public int getMaxTextLength() {
+ return mMaxLength;
+ }
}
/**
@@ -1776,6 +1818,21 @@
}
@Override
+ public void setMinTextEms(int minEms) {
+ mNode.mMinEms = minEms;
+ }
+
+ @Override
+ public void setMaxTextEms(int maxEms) {
+ mNode.mMaxEms = maxEms;
+ }
+
+ @Override
+ public void setMaxTextLength(int maxLength) {
+ mNode.mMaxLength = maxLength;
+ }
+
+ @Override
public void setDataIsSensitive(boolean sensitive) {
mNode.mSanitized = !sensitive;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2ee83bc..c043dca 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2342,9 +2342,9 @@
private static final int PFLAG_HOVERED = 0x10000000;
/**
- * no longer needed, should be reused
+ * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
*/
- private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
+ private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
/** {@hide} */
static final int PFLAG_ACTIVATED = 0x40000000;
@@ -6397,33 +6397,24 @@
return null;
}
- /**
- * 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;
+ if (notify) {
+ mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
+ } else {
+ mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
+ }
}
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;
+ if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
+ try {
+ getAutofillManager().notifyViewClicked(this);
+ } finally {
+ // Set it to already called so it's not called twice when called by
+ // performClickInternal()
+ mPrivateFlags |= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
+ }
}
}
@@ -6434,21 +6425,12 @@
* 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;
+ return performClick();
}
/**
@@ -6463,14 +6445,9 @@
// 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;
- }
+ // We still need to call this method to handle the cases where performClick() was called
+ // externally, instead of through performClickInternal()
+ notifyAutofillManagerOnClick();
final boolean result;
final ListenerInfo li = mListenerInfo;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6d4995e..99438d8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -72,6 +72,7 @@
import android.util.Log;
import android.util.MergedConfiguration;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
@@ -1668,8 +1669,6 @@
host.dispatchAttachedToWindow(mAttachInfo, 0);
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
dispatchApplyInsets(host);
- //Log.i(mTag, "Screen on initialized: " + attachInfo.mKeepScreenOn);
-
} else {
desiredWindowWidth = frame.width();
desiredWindowHeight = frame.height();
@@ -2827,7 +2826,7 @@
try {
mWindowDrawCountDown.await();
} catch (InterruptedException e) {
- Log.e(mTag, "Window redraw count down interruped!");
+ Log.e(mTag, "Window redraw count down interrupted!");
}
mWindowDrawCountDown = null;
}
@@ -2897,8 +2896,6 @@
final float appScale = mAttachInfo.mApplicationScale;
final boolean scalingRequired = mAttachInfo.mScalingRequired;
- int resizeAlpha = 0;
-
final Rect dirty = mDirty;
if (mSurfaceHolder != null) {
// The app owns the surface, we won't draw.
@@ -3469,6 +3466,7 @@
}
void dispatchDetachedFromWindow() {
+ mFirstInputStage.onDetachedFromWindow();
if (mView != null && mView.mAttachInfo != null) {
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
mView.dispatchDetachedFromWindow();
@@ -3739,7 +3737,7 @@
(View.AttachInfo.InvalidateInfo) msg.obj;
info.target.invalidate(info.left, info.top, info.right, info.bottom);
info.recycle();
- break;
+ break;
case MSG_PROCESS_INPUT_EVENTS:
mProcessInputEventsScheduled = false;
doProcessInputEvents();
@@ -3830,8 +3828,8 @@
}
break;
case MSG_WINDOW_FOCUS_CHANGED: {
+ final boolean hasWindowFocus = msg.arg1 != 0;
if (mAdded) {
- boolean hasWindowFocus = msg.arg1 != 0;
mAttachInfo.mHasWindowFocus = hasWindowFocus;
profileRendering(hasWindowFocus);
@@ -3839,7 +3837,6 @@
if (hasWindowFocus) {
boolean inTouchMode = msg.arg2 != 0;
ensureTouchModeLocally(inTouchMode);
-
if (mAttachInfo.mThreadedRenderer != null && mSurface.isValid()) {
mFullRedrawNeeded = true;
try {
@@ -3851,8 +3848,8 @@
Log.e(mTag, "OutOfResourcesException locking surface", e);
try {
if (!mWindowSession.outOfMemory(mWindow)) {
- Slog.w(mTag,
- "No processes killed for memory; killing self");
+ Slog.w(mTag, "No processes killed for memory;"
+ + " killing self");
Process.killProcess(Process.myPid());
}
} catch (RemoteException ex) {
@@ -3905,6 +3902,7 @@
}
}
}
+ mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
} break;
case MSG_DIE:
doDie();
@@ -3929,8 +3927,8 @@
// The IME is trying to say this event is from the
// system! Bad bad bad!
//noinspection UnusedAssignment
- event = KeyEvent.changeFlags(event, event.getFlags()
- & ~KeyEvent.FLAG_FROM_SYSTEM);
+ event = KeyEvent.changeFlags(event,
+ event.getFlags() & ~KeyEvent.FLAG_FROM_SYSTEM);
}
enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
} break;
@@ -4210,6 +4208,18 @@
}
}
+ protected void onWindowFocusChanged(boolean hasWindowFocus) {
+ if (mNext != null) {
+ mNext.onWindowFocusChanged(hasWindowFocus);
+ }
+ }
+
+ protected void onDetachedFromWindow() {
+ if (mNext != null) {
+ mNext.onDetachedFromWindow();
+ }
+ }
+
protected boolean shouldDropInputEvent(QueuedInputEvent q) {
if (mView == null || !mAdded) {
Slog.w(mTag, "Dropping event due to root view being removed: " + q.mEvent);
@@ -4963,9 +4973,9 @@
final MotionEvent event = (MotionEvent)q.mEvent;
final int source = event.getSource();
if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
- mTrackball.cancel(event);
+ mTrackball.cancel();
} else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
- mJoystick.cancel(event);
+ mJoystick.cancel();
} else if ((source & InputDevice.SOURCE_TOUCH_NAVIGATION)
== InputDevice.SOURCE_TOUCH_NAVIGATION) {
mTouchNavigation.cancel(event);
@@ -4974,6 +4984,18 @@
}
super.onDeliverToNext(q);
}
+
+ @Override
+ protected void onWindowFocusChanged(boolean hasWindowFocus) {
+ if (!hasWindowFocus) {
+ mJoystick.cancel();
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mJoystick.cancel();
+ }
}
/**
@@ -5086,7 +5108,7 @@
}
}
- public void cancel(MotionEvent event) {
+ public void cancel() {
mLastTime = Integer.MIN_VALUE;
// If we reach this, we consumed a trackball event.
@@ -5270,14 +5292,11 @@
* Creates dpad events from unhandled joystick movements.
*/
final class SyntheticJoystickHandler extends Handler {
- private final static String TAG = "SyntheticJoystickHandler";
private final static int MSG_ENQUEUE_X_AXIS_KEY_REPEAT = 1;
private final static int MSG_ENQUEUE_Y_AXIS_KEY_REPEAT = 2;
- private int mLastXDirection;
- private int mLastYDirection;
- private int mLastXKeyCode;
- private int mLastYKeyCode;
+ private final JoystickAxesState mJoystickAxesState = new JoystickAxesState();
+ private final SparseArray<KeyEvent> mDeviceKeyEvents = new SparseArray<>();
public SyntheticJoystickHandler() {
super(true);
@@ -5288,11 +5307,10 @@
switch (msg.what) {
case MSG_ENQUEUE_X_AXIS_KEY_REPEAT:
case MSG_ENQUEUE_Y_AXIS_KEY_REPEAT: {
- KeyEvent oldEvent = (KeyEvent)msg.obj;
- KeyEvent e = KeyEvent.changeTimeRepeat(oldEvent,
- SystemClock.uptimeMillis(),
- oldEvent.getRepeatCount() + 1);
if (mAttachInfo.mHasWindowFocus) {
+ KeyEvent oldEvent = (KeyEvent) msg.obj;
+ KeyEvent e = KeyEvent.changeTimeRepeat(oldEvent,
+ SystemClock.uptimeMillis(), oldEvent.getRepeatCount() + 1);
enqueueInputEvent(e);
Message m = obtainMessage(msg.what, e);
m.setAsynchronous(true);
@@ -5304,97 +5322,176 @@
public void process(MotionEvent event) {
switch(event.getActionMasked()) {
- case MotionEvent.ACTION_CANCEL:
- cancel(event);
- break;
- case MotionEvent.ACTION_MOVE:
- update(event, true);
- break;
- default:
- Log.w(mTag, "Unexpected action: " + event.getActionMasked());
+ case MotionEvent.ACTION_CANCEL:
+ cancel();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ update(event);
+ break;
+ default:
+ Log.w(mTag, "Unexpected action: " + event.getActionMasked());
}
}
- private void cancel(MotionEvent event) {
+ private void cancel() {
removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
- update(event, false);
+ for (int i = 0; i < mDeviceKeyEvents.size(); i++) {
+ final KeyEvent keyEvent = mDeviceKeyEvents.valueAt(i);
+ if (keyEvent != null) {
+ enqueueInputEvent(KeyEvent.changeTimeRepeat(keyEvent,
+ SystemClock.uptimeMillis(), 0));
+ }
+ }
+ mDeviceKeyEvents.clear();
+ mJoystickAxesState.resetState();
}
- private void update(MotionEvent event, boolean synthesizeNewKeys) {
+ private void update(MotionEvent event) {
+ final int historySize = event.getHistorySize();
+ for (int h = 0; h < historySize; h++) {
+ final long time = event.getHistoricalEventTime(h);
+ mJoystickAxesState.updateStateForAxis(event, time, MotionEvent.AXIS_X,
+ event.getHistoricalAxisValue(MotionEvent.AXIS_X, 0, h));
+ mJoystickAxesState.updateStateForAxis(event, time, MotionEvent.AXIS_Y,
+ event.getHistoricalAxisValue(MotionEvent.AXIS_Y, 0, h));
+ mJoystickAxesState.updateStateForAxis(event, time, MotionEvent.AXIS_HAT_X,
+ event.getHistoricalAxisValue(MotionEvent.AXIS_HAT_X, 0, h));
+ mJoystickAxesState.updateStateForAxis(event, time, MotionEvent.AXIS_HAT_Y,
+ event.getHistoricalAxisValue(MotionEvent.AXIS_HAT_Y, 0, h));
+ }
final long time = event.getEventTime();
- final int metaState = event.getMetaState();
- final int deviceId = event.getDeviceId();
- final int source = event.getSource();
-
- int xDirection = joystickAxisValueToDirection(
+ mJoystickAxesState.updateStateForAxis(event, time, MotionEvent.AXIS_X,
+ event.getAxisValue(MotionEvent.AXIS_X));
+ mJoystickAxesState.updateStateForAxis(event, time, MotionEvent.AXIS_Y,
+ event.getAxisValue(MotionEvent.AXIS_Y));
+ mJoystickAxesState.updateStateForAxis(event, time, MotionEvent.AXIS_HAT_X,
event.getAxisValue(MotionEvent.AXIS_HAT_X));
- if (xDirection == 0) {
- xDirection = joystickAxisValueToDirection(event.getX());
- }
-
- int yDirection = joystickAxisValueToDirection(
+ mJoystickAxesState.updateStateForAxis(event, time, MotionEvent.AXIS_HAT_Y,
event.getAxisValue(MotionEvent.AXIS_HAT_Y));
- if (yDirection == 0) {
- yDirection = joystickAxisValueToDirection(event.getY());
- }
-
- if (xDirection != mLastXDirection) {
- if (mLastXKeyCode != 0) {
- removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
- enqueueInputEvent(new KeyEvent(time, time,
- KeyEvent.ACTION_UP, mLastXKeyCode, 0, metaState,
- deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
- mLastXKeyCode = 0;
- }
-
- mLastXDirection = xDirection;
-
- if (xDirection != 0 && synthesizeNewKeys) {
- mLastXKeyCode = xDirection > 0
- ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT;
- final KeyEvent e = new KeyEvent(time, time,
- KeyEvent.ACTION_DOWN, mLastXKeyCode, 0, metaState,
- deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
- enqueueInputEvent(e);
- Message m = obtainMessage(MSG_ENQUEUE_X_AXIS_KEY_REPEAT, e);
- m.setAsynchronous(true);
- sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
- }
- }
-
- if (yDirection != mLastYDirection) {
- if (mLastYKeyCode != 0) {
- removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
- enqueueInputEvent(new KeyEvent(time, time,
- KeyEvent.ACTION_UP, mLastYKeyCode, 0, metaState,
- deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
- mLastYKeyCode = 0;
- }
-
- mLastYDirection = yDirection;
-
- if (yDirection != 0 && synthesizeNewKeys) {
- mLastYKeyCode = yDirection > 0
- ? KeyEvent.KEYCODE_DPAD_DOWN : KeyEvent.KEYCODE_DPAD_UP;
- final KeyEvent e = new KeyEvent(time, time,
- KeyEvent.ACTION_DOWN, mLastYKeyCode, 0, metaState,
- deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
- enqueueInputEvent(e);
- Message m = obtainMessage(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT, e);
- m.setAsynchronous(true);
- sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
- }
- }
}
- private int joystickAxisValueToDirection(float value) {
- if (value >= 0.5f) {
- return 1;
- } else if (value <= -0.5f) {
- return -1;
- } else {
- return 0;
+ final class JoystickAxesState {
+ // State machine: from neutral state (no button press) can go into
+ // button STATE_UP_OR_LEFT or STATE_DOWN_OR_RIGHT state, emitting an ACTION_DOWN event.
+ // From STATE_UP_OR_LEFT or STATE_DOWN_OR_RIGHT state can go into neutral state,
+ // emitting an ACTION_UP event.
+ private static final int STATE_UP_OR_LEFT = -1;
+ private static final int STATE_NEUTRAL = 0;
+ private static final int STATE_DOWN_OR_RIGHT = 1;
+
+ final int[] mAxisStatesHat = {STATE_NEUTRAL, STATE_NEUTRAL}; // {AXIS_HAT_X, AXIS_HAT_Y}
+ final int[] mAxisStatesStick = {STATE_NEUTRAL, STATE_NEUTRAL}; // {AXIS_X, AXIS_Y}
+
+ void resetState() {
+ mAxisStatesHat[0] = STATE_NEUTRAL;
+ mAxisStatesHat[1] = STATE_NEUTRAL;
+ mAxisStatesStick[0] = STATE_NEUTRAL;
+ mAxisStatesStick[1] = STATE_NEUTRAL;
+ }
+
+ void updateStateForAxis(MotionEvent event, long time, int axis, float value) {
+ // Emit KeyEvent if necessary
+ // axis can be AXIS_X, AXIS_Y, AXIS_HAT_X, AXIS_HAT_Y
+ final int axisStateIndex;
+ final int repeatMessage;
+ if (isXAxis(axis)) {
+ axisStateIndex = 0;
+ repeatMessage = MSG_ENQUEUE_X_AXIS_KEY_REPEAT;
+ } else if (isYAxis(axis)) {
+ axisStateIndex = 1;
+ repeatMessage = MSG_ENQUEUE_Y_AXIS_KEY_REPEAT;
+ } else {
+ Log.e(mTag, "Unexpected axis " + axis + " in updateStateForAxis!");
+ return;
+ }
+ final int newState = joystickAxisValueToState(value);
+
+ final int currentState;
+ if (axis == MotionEvent.AXIS_X || axis == MotionEvent.AXIS_Y) {
+ currentState = mAxisStatesStick[axisStateIndex];
+ } else {
+ currentState = mAxisStatesHat[axisStateIndex];
+ }
+
+ if (currentState == newState) {
+ return;
+ }
+
+ final int metaState = event.getMetaState();
+ final int deviceId = event.getDeviceId();
+ final int source = event.getSource();
+
+ if (currentState == STATE_DOWN_OR_RIGHT || currentState == STATE_UP_OR_LEFT) {
+ // send a button release event
+ final int keyCode = joystickAxisAndStateToKeycode(axis, currentState);
+ if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
+ enqueueInputEvent(new KeyEvent(time, time, KeyEvent.ACTION_UP, keyCode,
+ 0, metaState, deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
+ // remove the corresponding pending UP event if focus lost/view detached
+ mDeviceKeyEvents.put(deviceId, null);
+ }
+ removeMessages(repeatMessage);
+ }
+
+ if (newState == STATE_DOWN_OR_RIGHT || newState == STATE_UP_OR_LEFT) {
+ // send a button down event
+ final int keyCode = joystickAxisAndStateToKeycode(axis, newState);
+ if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
+ KeyEvent keyEvent = new KeyEvent(time, time, KeyEvent.ACTION_DOWN, keyCode,
+ 0, metaState, deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
+ enqueueInputEvent(keyEvent);
+ Message m = obtainMessage(repeatMessage, keyEvent);
+ m.setAsynchronous(true);
+ sendMessageDelayed(m, ViewConfiguration.getKeyRepeatTimeout());
+ // store the corresponding ACTION_UP event so that it can be sent
+ // if focus is lost or root view is removed
+ mDeviceKeyEvents.put(deviceId,
+ new KeyEvent(time, time, KeyEvent.ACTION_UP, keyCode,
+ 0, metaState, deviceId, 0,
+ KeyEvent.FLAG_FALLBACK | KeyEvent.FLAG_CANCELED,
+ source));
+ }
+ }
+ if (axis == MotionEvent.AXIS_X || axis == MotionEvent.AXIS_Y) {
+ mAxisStatesStick[axisStateIndex] = newState;
+ } else {
+ mAxisStatesHat[axisStateIndex] = newState;
+ }
+ }
+
+ private boolean isXAxis(int axis) {
+ return axis == MotionEvent.AXIS_X || axis == MotionEvent.AXIS_HAT_X;
+ }
+ private boolean isYAxis(int axis) {
+ return axis == MotionEvent.AXIS_Y || axis == MotionEvent.AXIS_HAT_Y;
+ }
+
+ private int joystickAxisAndStateToKeycode(int axis, int state) {
+ if (isXAxis(axis) && state == STATE_UP_OR_LEFT) {
+ return KeyEvent.KEYCODE_DPAD_LEFT;
+ }
+ if (isXAxis(axis) && state == STATE_DOWN_OR_RIGHT) {
+ return KeyEvent.KEYCODE_DPAD_RIGHT;
+ }
+ if (isYAxis(axis) && state == STATE_UP_OR_LEFT) {
+ return KeyEvent.KEYCODE_DPAD_UP;
+ }
+ if (isYAxis(axis) && state == STATE_DOWN_OR_RIGHT) {
+ return KeyEvent.KEYCODE_DPAD_DOWN;
+ }
+ Log.e(mTag, "Unknown axis " + axis + " or direction " + state);
+ return KeyEvent.KEYCODE_UNKNOWN; // should never happen
+ }
+
+ private int joystickAxisValueToState(float value) {
+ if (value >= 0.5f) {
+ return STATE_DOWN_OR_RIGHT;
+ } else if (value <= -0.5f) {
+ return STATE_UP_OR_LEFT;
+ } else {
+ return STATE_NEUTRAL;
+ }
}
}
}
@@ -6115,7 +6212,6 @@
if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
}
- //Log.d(mTag, ">>>>>> CALLING relayout");
if (params != null && mOrigWindowType != params.type) {
// For compatibility with old apps, don't crash here.
if (mTargetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
@@ -6136,7 +6232,6 @@
mPendingAlwaysConsumeNavBar =
(relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
- //Log.d(mTag, "<<<<<< BACK FROM relayout");
if (restore) {
params.restore();
}
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index f671c34..309366c 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -365,6 +365,30 @@
public abstract void setDataIsSensitive(boolean sensitive);
/**
+ * Sets the minimum width in ems of the text associated with this view, when supported.
+ *
+ * <p>Should only be set when the node is used for autofill purposes - it will be ignored
+ * when used for Assist.
+ */
+ public abstract void setMinTextEms(int minEms);
+
+ /**
+ * Sets the maximum width in ems of the text associated with this view, when supported.
+ *
+ * <p>Should only be set when the node is used for autofill purposes - it will be ignored
+ * when used for Assist.
+ */
+ public abstract void setMaxTextEms(int maxEms);
+
+ /**
+ * Sets the maximum length of the text associated with this view, when supported.
+ *
+ * <p>Should only be set when the node is used for autofill purposes - it will be ignored
+ * when used for Assist.
+ */
+ public abstract void setMaxTextLength(int maxLength);
+
+ /**
* Call when done populating a {@link ViewStructure} returned by
* {@link #asyncNewChild}.
*/
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 24ae03c..d9bc51f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10338,6 +10338,17 @@
// of the View (and can be any drawable) or a BackgroundColorSpan inside the text.
structure.setTextStyle(getTextSize(), getCurrentTextColor(),
AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
+ } else {
+ structure.setMinTextEms(getMinEms());
+ structure.setMaxTextEms(getMaxEms());
+ int maxLength = -1;
+ for (InputFilter filter: getFilters()) {
+ if (filter instanceof InputFilter.LengthFilter) {
+ maxLength = ((InputFilter.LengthFilter) filter).getMax();
+ break;
+ }
+ }
+ structure.setMaxTextLength(maxLength);
}
}
structure.setHint(getHint());
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 4abab28..2be6212 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -549,7 +549,7 @@
try {
dexoptNeeded = DexFile.getDexOptNeeded(
classPathElement, instructionSet, systemServerFilter,
- false /* newProfile */, false /* downgrade */);
+ null /* classLoaderContext */, false /* newProfile */, false /* downgrade */);
} catch (FileNotFoundException ignored) {
// Do not add to the classpath.
Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
diff --git a/core/res/res/values-large/strings.xml b/core/res/res/values-large/strings.xml
deleted file mode 100644
index e998b9a..0000000
--- a/core/res/res/values-large/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2011, 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">
-
- <!-- Do not translate. WebView User Agent targeted content -->
- <string name="web_user_agent_target_content" translatable="false"></string>
-
-</resources>
diff --git a/core/res/res/values-xlarge/strings.xml b/core/res/res/values-xlarge/strings.xml
deleted file mode 100644
index fc20be6..0000000
--- a/core/res/res/values-xlarge/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 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.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- Do not translate. WebView User Agent targeted content -->
- <string name="web_user_agent_target_content" translatable="false"></string>
-
-</resources>
\ No newline at end of file
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2fa3659..baede1a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2106,12 +2106,6 @@
<!-- Do not translate. datepicker mode, overridden for watch -->
<string name="date_picker_mode" translatable="false">"calendar"</string>
- <!-- Do not translate. WebView User Agent string -->
- <string name="web_user_agent" translatable="false">Mozilla/5.0 (Linux; U; <xliff:g id="x">Android %s</xliff:g>)
- AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.30</string>
- <!-- Do not translate. WebView User Agent targeted content -->
- <string name="web_user_agent_target_content" translatable="false">"Mobile "</string>
-
<!-- Title for a JavaScript dialog. "The page at <url of current page> says:" -->
<string name="js_dialog_title">The page at \"<xliff:g id="title">%s</xliff:g>\" says:</string>
<!-- Default title for a javascript dialog -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4bee398..1307ae2 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -994,8 +994,6 @@
<java-symbol type="string" name="volume_icon_description_notification" />
<java-symbol type="string" name="volume_icon_description_ringer" />
<java-symbol type="string" name="wait" />
- <java-symbol type="string" name="web_user_agent" />
- <java-symbol type="string" name="web_user_agent_target_content" />
<java-symbol type="string" name="webpage_unresponsive" />
<java-symbol type="string" name="whichApplication" />
<java-symbol type="string" name="whichHomeApplication" />
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 987096f..5484cf0 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -43,6 +43,7 @@
"AssetManager2.cpp",
"AttributeResolution.cpp",
"ChunkIterator.cpp",
+ "Idmap.cpp",
"LoadedArsc.cpp",
"LocaleData.cpp",
"misc.cpp",
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 0e577d1..158df13 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -20,64 +20,126 @@
#include <algorithm>
+#include "android-base/errors.h"
+#include "android-base/file.h"
#include "android-base/logging.h"
+#include "android-base/unique_fd.h"
+#include "android-base/utf8.h"
+#include "utils/Compat.h"
#include "utils/FileMap.h"
#include "utils/Trace.h"
#include "ziparchive/zip_archive.h"
#include "androidfw/Asset.h"
+#include "androidfw/Idmap.h"
+#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
namespace android {
-ApkAssets::ApkAssets() : zip_handle_(nullptr, ::CloseArchive) {}
+using base::SystemErrorCodeToString;
+using base::unique_fd;
+
+static const std::string kResourcesArsc("resources.arsc");
+
+ApkAssets::ApkAssets(void* unmanaged_handle, const std::string& path)
+ : zip_handle_(unmanaged_handle, ::CloseArchive), path_(path) {
+}
std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path, bool system) {
- return ApkAssets::LoadImpl(path, system, false /*load_as_shared_library*/);
+ return ApkAssets::LoadImpl(path, nullptr, nullptr, system, false /*load_as_shared_library*/);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadAsSharedLibrary(const std::string& path,
bool system) {
- return ApkAssets::LoadImpl(path, system, true /*load_as_shared_library*/);
+ return ApkAssets::LoadImpl(path, nullptr, nullptr, system, true /*load_as_shared_library*/);
}
-std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(const std::string& path, bool system,
- bool load_as_shared_library) {
+std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
+ bool system) {
+ std::unique_ptr<Asset> idmap_asset = CreateAssetFromFile(idmap_path);
+ if (idmap_asset == nullptr) {
+ return {};
+ }
+
+ const StringPiece idmap_data(
+ reinterpret_cast<const char*>(idmap_asset->getBuffer(true /*wordAligned*/)),
+ static_cast<size_t>(idmap_asset->getLength()));
+ std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(idmap_data);
+ if (loaded_idmap == nullptr) {
+ LOG(ERROR) << "failed to load IDMAP " << idmap_path;
+ return {};
+ }
+ return LoadImpl(loaded_idmap->OverlayApkPath(), std::move(idmap_asset), std::move(loaded_idmap),
+ system, false /*load_as_shared_library*/);
+}
+
+std::unique_ptr<Asset> ApkAssets::CreateAssetFromFile(const std::string& path) {
+ unique_fd fd(base::utf8::open(path.c_str(), O_RDONLY | O_BINARY | O_CLOEXEC));
+ if (fd == -1) {
+ LOG(ERROR) << "Failed to open file '" << path << "': " << SystemErrorCodeToString(errno);
+ return {};
+ }
+
+ const off64_t file_len = lseek64(fd, 0, SEEK_END);
+ if (file_len < 0) {
+ LOG(ERROR) << "Failed to get size of file '" << path << "': " << SystemErrorCodeToString(errno);
+ return {};
+ }
+
+ std::unique_ptr<FileMap> file_map = util::make_unique<FileMap>();
+ if (!file_map->create(path.c_str(), fd, 0, static_cast<size_t>(file_len), true /*readOnly*/)) {
+ LOG(ERROR) << "Failed to mmap file '" << path << "': " << SystemErrorCodeToString(errno);
+ return {};
+ }
+ return Asset::createFromUncompressedMap(std::move(file_map), Asset::AccessMode::ACCESS_RANDOM);
+}
+
+std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
+ const std::string& path, std::unique_ptr<Asset> idmap_asset,
+ std::unique_ptr<const LoadedIdmap> loaded_idmap, bool system, bool load_as_shared_library) {
ATRACE_CALL();
::ZipArchiveHandle unmanaged_handle;
int32_t result = ::OpenArchive(path.c_str(), &unmanaged_handle);
if (result != 0) {
- LOG(ERROR) << ::ErrorCodeString(result);
+ LOG(ERROR) << "Failed to open APK '" << path << "' " << ::ErrorCodeString(result);
return {};
}
// Wrap the handle in a unique_ptr so it gets automatically closed.
- std::unique_ptr<ApkAssets> loaded_apk(new ApkAssets());
- loaded_apk->zip_handle_.reset(unmanaged_handle);
+ std::unique_ptr<ApkAssets> loaded_apk(new ApkAssets(unmanaged_handle, path));
- ::ZipString entry_name("resources.arsc");
+ // Find the resource table.
+ ::ZipString entry_name(kResourcesArsc.c_str());
::ZipEntry entry;
result = ::FindEntry(loaded_apk->zip_handle_.get(), entry_name, &entry);
if (result != 0) {
- LOG(ERROR) << ::ErrorCodeString(result);
- return {};
+ // There is no resources.arsc, so create an empty LoadedArsc and return.
+ loaded_apk->loaded_arsc_ = LoadedArsc::CreateEmpty();
+ return std::move(loaded_apk);
}
if (entry.method == kCompressDeflated) {
- LOG(WARNING) << "resources.arsc is compressed.";
+ LOG(WARNING) << kResourcesArsc << " in APK '" << path << "' is compressed.";
}
- loaded_apk->path_ = path;
- loaded_apk->resources_asset_ =
- loaded_apk->Open("resources.arsc", Asset::AccessMode::ACCESS_BUFFER);
+ // Open the resource table via mmap unless it is compressed. This logic is taken care of by Open.
+ loaded_apk->resources_asset_ = loaded_apk->Open(kResourcesArsc, Asset::AccessMode::ACCESS_BUFFER);
if (loaded_apk->resources_asset_ == nullptr) {
+ LOG(ERROR) << "Failed to open '" << kResourcesArsc << "' in APK '" << path << "'.";
return {};
}
+ // Must retain ownership of the IDMAP Asset so that all pointers to its mmapped data remain valid.
+ loaded_apk->idmap_asset_ = std::move(idmap_asset);
+
+ const StringPiece data(
+ reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
+ loaded_apk->resources_asset_->getLength());
loaded_apk->loaded_arsc_ =
- LoadedArsc::Load(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/),
- loaded_apk->resources_asset_->getLength(), system, load_as_shared_library);
+ LoadedArsc::Load(data, loaded_idmap.get(), system, load_as_shared_library);
if (loaded_apk->loaded_arsc_ == nullptr) {
+ LOG(ERROR) << "Failed to load '" << kResourcesArsc << "' in APK '" << path << "'.";
return {};
}
@@ -93,7 +155,6 @@
::ZipEntry entry;
int32_t result = ::FindEntry(zip_handle_.get(), name, &entry);
if (result != 0) {
- LOG(ERROR) << "No entry '" << path << "' found in APK '" << path_ << "'";
return {};
}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index f1f2e2d..d4d9dcb 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -35,7 +35,9 @@
namespace android {
-AssetManager2::AssetManager2() { memset(&configuration_, 0, sizeof(configuration_)); }
+AssetManager2::AssetManager2() {
+ memset(&configuration_, 0, sizeof(configuration_));
+}
bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets,
bool invalidate_caches) {
@@ -55,9 +57,9 @@
int next_package_id = 0x02;
const size_t apk_assets_count = apk_assets_.size();
for (size_t i = 0; i < apk_assets_count; i++) {
- const ApkAssets* apk_asset = apk_assets_[i];
- for (const std::unique_ptr<const LoadedPackage>& package :
- apk_asset->GetLoadedArsc()->GetPackages()) {
+ const LoadedArsc* loaded_arsc = apk_assets_[i]->GetLoadedArsc();
+
+ for (const std::unique_ptr<const LoadedPackage>& package : loaded_arsc->GetPackages()) {
// Get the package ID or assign one if a shared library.
int package_id;
if (package->IsDynamic()) {
@@ -312,7 +314,8 @@
cumulated_flags |= current_flags;
- if (best_cookie == kInvalidCookie || current_config.isBetterThan(best_config, desired_config)) {
+ if (best_cookie == kInvalidCookie || current_config.isBetterThan(best_config, desired_config) ||
+ (loaded_package->IsOverlay() && current_config.compare(best_config) == 0)) {
best_entry = current_entry;
best_config = current_config;
best_cookie = package_group.cookies_[i];
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
new file mode 100644
index 0000000..7c1ee5c
--- /dev/null
+++ b/libs/androidfw/Idmap.cpp
@@ -0,0 +1,190 @@
+/*
+ * 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 ATRACE_TAG ATRACE_TAG_RESOURCES
+
+#include "androidfw/Idmap.h"
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+#include "utils/ByteOrder.h"
+#include "utils/Trace.h"
+
+#ifdef _WIN32
+#ifdef ERROR
+#undef ERROR
+#endif
+#endif
+
+#include "androidfw/ResourceTypes.h"
+
+using ::android::base::StringPrintf;
+
+namespace android {
+
+constexpr static inline bool is_valid_package_id(uint16_t id) {
+ return id != 0 && id <= 255;
+}
+
+constexpr static inline bool is_valid_type_id(uint16_t id) {
+ // Type IDs and package IDs have the same constraints in the IDMAP.
+ return is_valid_package_id(id);
+}
+
+bool LoadedIdmap::Lookup(const IdmapEntry_header* header, uint16_t input_entry_id,
+ uint16_t* output_entry_id) {
+ if (input_entry_id < dtohs(header->entry_id_offset)) {
+ // After applying the offset, the entry is not present.
+ return false;
+ }
+
+ input_entry_id -= dtohs(header->entry_id_offset);
+ if (input_entry_id >= dtohs(header->entry_count)) {
+ // The entry is not present.
+ return false;
+ }
+
+ uint32_t result = dtohl(header->entries[input_entry_id]);
+ if (result == 0xffffffffu) {
+ return false;
+ }
+ *output_entry_id = static_cast<uint16_t>(result);
+ return true;
+}
+
+static bool is_word_aligned(const void* data) {
+ return (reinterpret_cast<uintptr_t>(data) & 0x03) == 0;
+}
+
+static bool IsValidIdmapHeader(const StringPiece& data) {
+ if (!is_word_aligned(data.data())) {
+ LOG(ERROR) << "Idmap header is not word aligned.";
+ return false;
+ }
+
+ if (data.size() < sizeof(Idmap_header)) {
+ LOG(ERROR) << "Idmap header is too small.";
+ return false;
+ }
+
+ const Idmap_header* header = reinterpret_cast<const Idmap_header*>(data.data());
+ if (dtohl(header->magic) != kIdmapMagic) {
+ LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)",
+ dtohl(header->magic), kIdmapMagic);
+ return false;
+ }
+
+ if (dtohl(header->version) != kIdmapCurrentVersion) {
+ // We are strict about versions because files with this format are auto-generated and don't need
+ // backwards compatibility.
+ LOG(ERROR) << StringPrintf("Version mismatch in Idmap (was 0x%08x, expected 0x%08x)",
+ dtohl(header->version), kIdmapCurrentVersion);
+ return false;
+ }
+
+ if (!is_valid_package_id(dtohs(header->target_package_id))) {
+ LOG(ERROR) << StringPrintf("Target package ID in Idmap is invalid: 0x%02x",
+ dtohs(header->target_package_id));
+ return false;
+ }
+
+ if (dtohs(header->type_count) > 255) {
+ LOG(ERROR) << StringPrintf("Idmap has too many type mappings (was %d, max 255)",
+ (int)dtohs(header->type_count));
+ return false;
+ }
+ return true;
+}
+
+LoadedIdmap::LoadedIdmap(const Idmap_header* header) : header_(header) {
+ size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),
+ arraysize(header_->overlay_path));
+ overlay_apk_path_.assign(reinterpret_cast<const char*>(header_->overlay_path), length);
+}
+
+std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_data) {
+ ATRACE_CALL();
+ if (!IsValidIdmapHeader(idmap_data)) {
+ return {};
+ }
+
+ const Idmap_header* header = reinterpret_cast<const Idmap_header*>(idmap_data.data());
+
+ // Can't use make_unique because LoadedImpl constructor is private.
+ std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(new LoadedIdmap(header));
+
+ const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data()) + sizeof(*header);
+ size_t data_size = idmap_data.size() - sizeof(*header);
+
+ size_t type_maps_encountered = 0u;
+ while (data_size >= sizeof(IdmapEntry_header)) {
+ if (!is_word_aligned(data_ptr)) {
+ LOG(ERROR) << "Type mapping in Idmap is not word aligned";
+ return {};
+ }
+
+ // Validate the type IDs.
+ const IdmapEntry_header* entry_header = reinterpret_cast<const IdmapEntry_header*>(data_ptr);
+ if (!is_valid_type_id(dtohs(entry_header->target_type_id)) || !is_valid_type_id(dtohs(entry_header->overlay_type_id))) {
+ LOG(ERROR) << StringPrintf("Invalid type map (0x%02x -> 0x%02x)",
+ dtohs(entry_header->target_type_id),
+ dtohs(entry_header->overlay_type_id));
+ return {};
+ }
+
+ // Make sure there is enough space for the entries declared in the header.
+ if ((data_size - sizeof(*entry_header)) / sizeof(uint32_t) <
+ static_cast<size_t>(dtohs(entry_header->entry_count))) {
+ LOG(ERROR) << StringPrintf("Idmap too small for the number of entries (%d)",
+ (int)dtohs(entry_header->entry_count));
+ return {};
+ }
+
+ // Only add a non-empty overlay.
+ if (dtohs(entry_header->entry_count != 0)) {
+ loaded_idmap->type_map_[static_cast<uint8_t>(dtohs(entry_header->overlay_type_id))] =
+ entry_header;
+ }
+
+ const size_t entry_size_bytes =
+ sizeof(*entry_header) + (dtohs(entry_header->entry_count) * sizeof(uint32_t));
+ data_ptr += entry_size_bytes;
+ data_size -= entry_size_bytes;
+ type_maps_encountered++;
+ }
+
+ // Verify that we parsed all the type maps.
+ if (type_maps_encountered != static_cast<size_t>(dtohs(header->type_count))) {
+ LOG(ERROR) << "Parsed " << type_maps_encountered << " type maps but expected "
+ << (int)dtohs(header->type_count);
+ return {};
+ }
+ return std::move(loaded_idmap);
+}
+
+uint8_t LoadedIdmap::TargetPackageId() const {
+ return static_cast<uint8_t>(dtohs(header_->target_package_id));
+}
+
+const IdmapEntry_header* LoadedIdmap::GetEntryMapForType(uint8_t type_id) const {
+ auto iter = type_map_.find(type_id);
+ if (iter != type_map_.end()) {
+ return iter->second;
+ }
+ return nullptr;
+}
+
+} // namespace android
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index bd7b804..b62fc81 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -37,7 +37,7 @@
#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"
-using android::base::StringPrintf;
+using ::android::base::StringPrintf;
namespace android {
@@ -61,6 +61,10 @@
// and under which configurations it varies.
const ResTable_typeSpec* type_spec;
+ // Pointer to the mmapped data where the IDMAP mappings for this type
+ // exist. May be nullptr if no IDMAP exists.
+ const IdmapEntry_header* idmap_entries;
+
// The number of types that follow this struct.
// There is a type for each configuration
// that entries are defined for.
@@ -84,7 +88,10 @@
// the Type structs.
class TypeSpecPtrBuilder {
public:
- TypeSpecPtrBuilder(const ResTable_typeSpec* header) : header_(header) {}
+ explicit TypeSpecPtrBuilder(const ResTable_typeSpec* header,
+ const IdmapEntry_header* idmap_header)
+ : header_(header), idmap_header_(idmap_header) {
+ }
void AddType(const ResTable_type* type) {
ResTable_config config;
@@ -99,6 +106,7 @@
}
TypeSpec* type_spec = (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(Type)));
type_spec->type_spec = header_;
+ type_spec->idmap_entries = idmap_header_;
type_spec->type_count = types_.size();
memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(Type));
return TypeSpecPtr(type_spec);
@@ -108,6 +116,7 @@
DISALLOW_COPY_AND_ASSIGN(TypeSpecPtrBuilder);
const ResTable_typeSpec* header_;
+ const IdmapEntry_header* idmap_header_;
std::vector<Type> types_;
};
@@ -125,6 +134,14 @@
return false;
}
+ // If there is an IDMAP supplied with this package, translate the entry ID.
+ if (ptr->idmap_entries != nullptr) {
+ if (!LoadedIdmap::Lookup(ptr->idmap_entries, entry_idx, &entry_idx)) {
+ // There is no mapping, so the resource is not meant to be in this overlay package.
+ return false;
+ }
+ }
+
// Don't bother checking if the entry ID is larger than
// the number of entries.
if (entry_idx >= dtohl(ptr->type_spec->entryCount)) {
@@ -225,7 +242,7 @@
const size_t entries_offset = dtohl(header->entriesStart);
const size_t offsets_length = sizeof(uint32_t) * entry_count;
- if (offsets_offset + offsets_length > entries_offset) {
+ if (offsets_offset > entries_offset || entries_offset - offsets_offset < offsets_length) {
LOG(ERROR) << "Entry offsets overlap actual entry data.";
return false;
}
@@ -269,13 +286,13 @@
reinterpret_cast<const uint8_t*>(header) + offset);
const size_t entry_size = dtohs(entry->size);
if (entry_size < sizeof(*entry)) {
- LOG(ERROR) << "ResTable_entry size " << entry_size << " is too small.";
+ LOG(ERROR) << "ResTable_entry size " << entry_size << " at index " << i << " is too small.";
return false;
}
// Check the declared entrySize.
if (entry_size > chunk.size() || offset > chunk.size() - entry_size) {
- LOG(ERROR) << "ResTable_entry size " << entry_size << " is too large.";
+ LOG(ERROR) << "ResTable_entry size " << entry_size << " at index " << i << " is too large.";
return false;
}
@@ -286,13 +303,13 @@
size_t map_entries_start = offset + entry_size;
if (map_entries_start & 0x03) {
- LOG(ERROR) << "Map entries start at unaligned offset.";
+ LOG(ERROR) << "Map entries at index " << i << " start at unaligned offset.";
return false;
}
// Each entry is sizeof(ResTable_map) big.
if (map_entry_count > ((chunk.size() - map_entries_start) / sizeof(ResTable_map))) {
- LOG(ERROR) << "Too many map entries in ResTable_map_entry.";
+ LOG(ERROR) << "Too many map entries in ResTable_map_entry at index " << i << ".";
return false;
}
@@ -300,7 +317,9 @@
} else {
// There needs to be room for one Res_value struct.
if (offset + entry_size > chunk.size() - sizeof(Res_value)) {
- LOG(ERROR) << "No room for Res_value after ResTable_entry.";
+ LOG(ERROR) << "No room for Res_value after ResTable_entry at index " << i << " for type "
+ << (int)header->id << " with config " << header->config.toString().string()
+ << ".";
return false;
}
@@ -308,12 +327,12 @@
reinterpret_cast<const uint8_t*>(entry) + entry_size);
const size_t value_size = dtohs(value->size);
if (value_size < sizeof(Res_value)) {
- LOG(ERROR) << "Res_value is too small.";
+ LOG(ERROR) << "Res_value at index " << i << " is too small.";
return false;
}
if (value_size > chunk.size() || offset + entry_size > chunk.size() - value_size) {
- LOG(ERROR) << "Res_value size is too large.";
+ LOG(ERROR) << "Res_value size " << value_size << " at index " << i << " is too large.";
return false;
}
}
@@ -412,10 +431,13 @@
return 0u;
}
-std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
+std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
+ const LoadedIdmap* loaded_idmap) {
ATRACE_CALL();
std::unique_ptr<LoadedPackage> loaded_package{new LoadedPackage()};
+ // typeIdOffset was added at some point, but we still must recognize apps built before this
+ // was added.
constexpr size_t kMinPackageSize =
sizeof(ResTable_package) - sizeof(ResTable_package::typeIdOffset);
const ResTable_package* header = chunk.header<ResTable_package, kMinPackageSize>();
@@ -430,6 +452,12 @@
loaded_package->dynamic_ = true;
}
+ if (loaded_idmap != nullptr) {
+ // This is an overlay and so it needs to pretend to be the target package.
+ loaded_package->package_id_ = loaded_idmap->TargetPackageId();
+ loaded_package->overlay_ = true;
+ }
+
if (header->header.headerSize >= sizeof(ResTable_package)) {
uint32_t type_id_offset = dtohl(header->typeIdOffset);
if (type_id_offset > std::numeric_limits<uint8_t>::max()) {
@@ -490,7 +518,16 @@
LOG(ERROR) << "Too many type configurations, overflow detected.";
return {};
}
- loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
+
+ // We only add the type to the package if there is no IDMAP, or if the type is
+ // overlaying something.
+ if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
+ // If this is an overlay, insert it at the target type ID.
+ if (type_spec_ptr->idmap_entries != nullptr) {
+ last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
+ }
+ loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
+ }
types_builder = {};
last_type_idx = 0;
@@ -531,7 +568,15 @@
}
last_type_idx = type_spec->id - 1;
- types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec);
+
+ // If this is an overlay, associate the mapping of this type to the target type
+ // from the IDMAP.
+ const IdmapEntry_header* idmap_entry_header = nullptr;
+ if (loaded_idmap != nullptr) {
+ idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id);
+ }
+
+ types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
} break;
case RES_TABLE_TYPE_TYPE: {
@@ -608,7 +653,16 @@
LOG(ERROR) << "Too many type configurations, overflow detected.";
return {};
}
- loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
+
+ // We only add the type to the package if there is no IDMAP, or if the type is
+ // overlaying something.
+ if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
+ // If this is an overlay, insert it at the target type ID.
+ if (type_spec_ptr->idmap_entries != nullptr) {
+ last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
+ }
+ loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
+ }
}
if (iter.HadError()) {
@@ -618,7 +672,8 @@
return loaded_package;
}
-bool LoadedArsc::LoadTable(const Chunk& chunk, bool load_as_shared_library) {
+bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
+ bool load_as_shared_library) {
ATRACE_CALL();
const ResTable_header* header = chunk.header<ResTable_header>();
if (header == nullptr) {
@@ -652,13 +707,13 @@
case RES_TABLE_PACKAGE_TYPE: {
if (packages_seen + 1 > package_count) {
LOG(ERROR) << "More package chunks were found than the " << package_count
- << " declared in the "
- "header.";
+ << " declared in the header.";
return false;
}
packages_seen++;
- std::unique_ptr<LoadedPackage> loaded_package = LoadedPackage::Load(child_chunk);
+ std::unique_ptr<LoadedPackage> loaded_package =
+ LoadedPackage::Load(child_chunk, loaded_idmap);
if (!loaded_package) {
return false;
}
@@ -684,7 +739,8 @@
return true;
}
-std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const void* data, size_t len, bool system,
+std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const StringPiece& data,
+ const LoadedIdmap* loaded_idmap, bool system,
bool load_as_shared_library) {
ATRACE_CALL();
@@ -692,12 +748,12 @@
std::unique_ptr<LoadedArsc> loaded_arsc(new LoadedArsc());
loaded_arsc->system_ = system;
- ChunkIterator iter(data, len);
+ ChunkIterator iter(data.data(), data.size());
while (iter.HasNext()) {
const Chunk chunk = iter.Next();
switch (chunk.type()) {
case RES_TABLE_TYPE:
- if (!loaded_arsc->LoadTable(chunk, load_as_shared_library)) {
+ if (!loaded_arsc->LoadTable(chunk, loaded_idmap, load_as_shared_library)) {
return {};
}
break;
@@ -717,4 +773,8 @@
return std::move(loaded_arsc);
}
+std::unique_ptr<const LoadedArsc> LoadedArsc::CreateEmpty() {
+ return std::unique_ptr<LoadedArsc>(new LoadedArsc());
+}
+
} // namespace android
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 2e392d5..3a307fc 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -28,36 +28,63 @@
namespace android {
+class LoadedIdmap;
+
// Holds an APK.
class ApkAssets {
public:
+ // Creates an ApkAssets.
+ // If `system` is true, the package is marked as a system package, and allows some functions to
+ // filter out this package when computing what configurations/resources are available.
static std::unique_ptr<const ApkAssets> Load(const std::string& path, bool system = false);
+
+ // Creates an ApkAssets, but forces any package with ID 0x7f to be loaded as a shared library.
+ // If `system` is true, the package is marked as a system package, and allows some functions to
+ // filter out this package when computing what configurations/resources are available.
static std::unique_ptr<const ApkAssets> LoadAsSharedLibrary(const std::string& path,
bool system = false);
+ // Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay
+ // data.
+ // If `system` is true, the package is marked as a system package, and allows some functions to
+ // filter out this package when computing what configurations/resources are available.
+ static std::unique_ptr<const ApkAssets> LoadOverlay(const std::string& idmap_path,
+ bool system = false);
+
std::unique_ptr<Asset> Open(const std::string& path,
Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const;
bool ForEachFile(const std::string& path,
const std::function<void(const StringPiece&, FileType)>& f) const;
- inline const std::string& GetPath() const { return path_; }
+ inline const std::string& GetPath() const {
+ return path_;
+ }
- inline const LoadedArsc* GetLoadedArsc() const { return loaded_arsc_.get(); }
+ // This is never nullptr.
+ inline const LoadedArsc* GetLoadedArsc() const {
+ return loaded_arsc_.get();
+ }
private:
DISALLOW_COPY_AND_ASSIGN(ApkAssets);
- static std::unique_ptr<const ApkAssets> LoadImpl(const std::string& path, bool system,
- bool load_as_shared_library);
+ static std::unique_ptr<const ApkAssets> LoadImpl(const std::string& path,
+ std::unique_ptr<Asset> idmap_asset,
+ std::unique_ptr<const LoadedIdmap> loaded_idmap,
+ bool system, bool load_as_shared_library);
- ApkAssets();
+ // Creates an Asset from any file on the file system.
+ static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path);
+
+ ApkAssets(void* unmanaged_handle, const std::string& path);
using ZipArchivePtr = std::unique_ptr<void, void(*)(void*)>;
ZipArchivePtr zip_handle_;
- std::string path_;
+ const std::string path_;
std::unique_ptr<Asset> resources_asset_;
+ std::unique_ptr<Asset> idmap_asset_;
std::unique_ptr<const LoadedArsc> loaded_arsc_;
};
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index fd94144..b29bc3a 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -96,24 +96,29 @@
// new resource IDs.
bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true);
- inline const std::vector<const ApkAssets*> GetApkAssets() const { return apk_assets_; }
+ inline const std::vector<const ApkAssets*> GetApkAssets() const {
+ return apk_assets_;
+ }
// Returns the string pool for the given asset cookie.
- // Use the string pool returned here with a valid Res_value object of
- // type Res_value::TYPE_STRING.
+ // Use the string pool returned here with a valid Res_value object of type Res_value::TYPE_STRING.
const ResStringPool* GetStringPoolForCookie(ApkAssetsCookie cookie) const;
// Returns the DynamicRefTable for the given package ID.
+ // This may be nullptr if the APK represented by `cookie` has no resource table.
const DynamicRefTable* GetDynamicRefTableForPackage(uint32_t package_id) const;
// Returns the DynamicRefTable for the ApkAssets represented by the cookie.
+ // This may be nullptr if the APK represented by `cookie` has no resource table.
const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
// Sets/resets the configuration for this AssetManager. This will cause all
// caches that are related to the configuration change to be invalidated.
void SetConfiguration(const ResTable_config& configuration);
- inline const ResTable_config& GetConfiguration() const { return configuration_; }
+ inline const ResTable_config& GetConfiguration() const {
+ return configuration_;
+ }
// Returns all configurations for which there are resources defined. This includes resource
// configurations in all the ApkAssets set for this AssetManager.
@@ -227,6 +232,14 @@
// Creates a new Theme from this AssetManager.
std::unique_ptr<Theme> NewTheme();
+ template <typename Func>
+ void ForEachPackage(Func func) {
+ for (const PackageGroup& package_group : package_groups_) {
+ func(package_group.packages_.front()->GetPackageName(),
+ package_group.dynamic_ref_table.mAssignedPackageId);
+ }
+ }
+
void DumpToLog() const;
private:
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
new file mode 100644
index 0000000..fd02e6f
--- /dev/null
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -0,0 +1,76 @@
+/*
+ * 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 IDMAP_H_
+#define IDMAP_H_
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "android-base/macros.h"
+
+#include "androidfw/StringPiece.h"
+
+namespace android {
+
+struct Idmap_header;
+struct IdmapEntry_header;
+
+// Represents a loaded/parsed IDMAP for a Runtime Resource Overlay (RRO).
+// An RRO and its target APK have different resource IDs assigned to their resources. Overlaying
+// a resource is done by resource name. An IDMAP is a generated mapping between the resource IDs
+// of the RRO and the target APK for each resource with the same name.
+// A LoadedIdmap can be set alongside the overlay's LoadedArsc to allow the overlay ApkAssets to
+// masquerade as the target ApkAssets resources.
+class LoadedIdmap {
+ public:
+ // Loads an IDMAP from a chunk of memory. Returns nullptr if the IDMAP data was malformed.
+ static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_data);
+
+ // Performs a lookup of the expected entry ID for the given IDMAP entry header.
+ // Returns true if the mapping exists and fills `output_entry_id` with the result.
+ static bool Lookup(const IdmapEntry_header* header, uint16_t input_entry_id,
+ uint16_t* output_entry_id);
+
+ // Returns the package ID for which this overlay should apply.
+ uint8_t TargetPackageId() const;
+
+ // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
+ inline const std::string& OverlayApkPath() const {
+ return overlay_apk_path_;
+ }
+
+ // Returns the mapping of target entry ID to overlay entry ID for the given target type.
+ const IdmapEntry_header* GetEntryMapForType(uint8_t type_id) const;
+
+ protected:
+ // Exposed as protected so that tests can subclass and mock this class out.
+ LoadedIdmap() = default;
+
+ const Idmap_header* header_ = nullptr;
+ std::string overlay_apk_path_;
+ std::unordered_map<uint8_t, const IdmapEntry_header*> type_map_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);
+
+ explicit LoadedIdmap(const Idmap_header* header);
+};
+
+} // namespace android
+
+#endif // IDMAP_H_
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index f30b158..1f272e8 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -25,6 +25,7 @@
#include "androidfw/ByteBucketArray.h"
#include "androidfw/Chunk.h"
+#include "androidfw/Idmap.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
@@ -70,20 +71,36 @@
uint32_t* out_flags) const;
// Returns the string pool where type names are stored.
- inline const ResStringPool* GetTypeStringPool() const { return &type_string_pool_; }
+ inline const ResStringPool* GetTypeStringPool() const {
+ return &type_string_pool_;
+ }
// Returns the string pool where the names of resource entries are stored.
- inline const ResStringPool* GetKeyStringPool() const { return &key_string_pool_; }
+ inline const ResStringPool* GetKeyStringPool() const {
+ return &key_string_pool_;
+ }
- inline const std::string& GetPackageName() const { return package_name_; }
+ inline const std::string& GetPackageName() const {
+ return package_name_;
+ }
- inline int GetPackageId() const { return package_id_; }
+ inline int GetPackageId() const {
+ return package_id_;
+ }
// Returns true if this package is dynamic (shared library) and needs to have an ID assigned.
- inline bool IsDynamic() const { return dynamic_; }
+ inline bool IsDynamic() const {
+ return dynamic_;
+ }
// Returns true if this package originates from a system provided resource.
- inline bool IsSystem() const { return system_; }
+ inline bool IsSystem() const {
+ return system_;
+ }
+
+ inline bool IsOverlay() const {
+ return overlay_;
+ }
// Returns the map of package name to package ID used in this LoadedPackage. At runtime, a
// package could have been assigned a different package ID than what this LoadedPackage was
@@ -111,7 +128,7 @@
private:
DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
- static std::unique_ptr<LoadedPackage> Load(const Chunk& chunk);
+ static std::unique_ptr<LoadedPackage> Load(const Chunk& chunk, const LoadedIdmap* loaded_idmap);
LoadedPackage() = default;
@@ -122,6 +139,7 @@
int type_id_offset_ = 0;
bool dynamic_ = false;
bool system_ = false;
+ bool overlay_ = false;
ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
@@ -137,14 +155,21 @@
// If `load_as_shared_library` is set to true, the application package (0x7f) is treated
// as a shared library (0x00). When loaded into an AssetManager, the package will be assigned an
// ID.
- static std::unique_ptr<const LoadedArsc> Load(const void* data, size_t len, bool system = false,
+ static std::unique_ptr<const LoadedArsc> Load(const StringPiece& data,
+ const LoadedIdmap* loaded_idmap = nullptr,
+ bool system = false,
bool load_as_shared_library = false);
+ // Create an empty LoadedArsc. This is used when an APK has no resources.arsc.
+ static std::unique_ptr<const LoadedArsc> CreateEmpty();
+
~LoadedArsc();
// Returns the string pool where all string resource values
// (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
- inline const ResStringPool* GetStringPool() const { return &global_string_pool_; }
+ inline const ResStringPool* GetStringPool() const {
+ return &global_string_pool_;
+ }
// Finds the resource with ID `resid` with the best value for configuration `config`.
// The parameter `out_entry` will be filled with the resulting resource entry.
@@ -157,7 +182,9 @@
const LoadedPackage* GetPackageForId(uint32_t resid) const;
// Returns true if this is a system provided resource.
- inline bool IsSystem() const { return system_; }
+ inline bool IsSystem() const {
+ return system_;
+ }
// Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
@@ -168,7 +195,7 @@
DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
LoadedArsc() = default;
- bool LoadTable(const Chunk& chunk, bool load_as_shared_library);
+ bool LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library);
ResStringPool global_string_pool_;
std::vector<std::unique_ptr<const LoadedPackage>> packages_;
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 66c66c2..8f858b6 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -38,6 +38,9 @@
namespace android {
+constexpr const static uint32_t kIdmapMagic = 0x504D4449u;
+constexpr const static uint32_t kIdmapCurrentVersion = 0x00000001u;
+
/**
* In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
* casting on raw data and expect char16_t to be exactly 16 bits.
@@ -1583,6 +1586,30 @@
uint16_t packageName[128];
};
+struct alignas(uint32_t) Idmap_header {
+ // Always 0x504D4449 ('IDMP')
+ uint32_t magic;
+
+ uint32_t version;
+
+ uint32_t target_crc32;
+ uint32_t overlay_crc32;
+
+ uint8_t target_path[256];
+ uint8_t overlay_path[256];
+
+ uint16_t target_package_id;
+ uint16_t type_count;
+} __attribute__((packed));
+
+struct alignas(uint32_t) IdmapEntry_header {
+ uint16_t target_type_id;
+ uint16_t overlay_type_id;
+ uint16_t entry_count;
+ uint16_t entry_id_offset;
+ uint32_t entries[0];
+} __attribute__((packed));
+
class AssetManager2;
/**
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index c85b0b9..2766ce1 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -17,12 +17,14 @@
#include "androidfw/ApkAssets.h"
#include "android-base/file.h"
+#include "android-base/test_utils.h"
#include "android-base/unique_fd.h"
+#include "androidfw/Util.h"
#include "TestHelpers.h"
#include "data/basic/R.h"
-using com::android::basic::R;
+using ::com::android::basic::R;
namespace android {
@@ -54,6 +56,37 @@
EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
}
+TEST(ApkAssetsTest, LoadApkWithIdmap) {
+ std::string contents;
+ ResTable target_table;
+ const std::string target_path = GetTestDataPath() + "/basic/basic.apk";
+ ASSERT_TRUE(ReadFileFromZipToString(target_path, "resources.arsc", &contents));
+ ASSERT_EQ(NO_ERROR, target_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
+
+ ResTable overlay_table;
+ const std::string overlay_path = GetTestDataPath() + "/overlay/overlay.apk";
+ ASSERT_TRUE(ReadFileFromZipToString(overlay_path, "resources.arsc", &contents));
+ ASSERT_EQ(NO_ERROR, overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
+
+ util::unique_cptr<void> idmap_data;
+ void* temp_data;
+ size_t idmap_len;
+
+ ASSERT_EQ(NO_ERROR, target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
+ overlay_path.c_str(), &temp_data, &idmap_len));
+ idmap_data.reset(temp_data);
+
+ TemporaryFile tf;
+ ASSERT_TRUE(base::WriteFully(tf.fd, idmap_data.get(), idmap_len));
+ close(tf.fd);
+
+ // Open something so that the destructor of TemporaryFile closes a valid fd.
+ tf.fd = open("/dev/null", O_WRONLY);
+
+ std::unique_ptr<const ApkAssets> loaded_overlay_apk = ApkAssets::LoadOverlay(tf.path);
+ ASSERT_NE(nullptr, loaded_overlay_apk);
+}
+
TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index d12be18..9eb4a13 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -22,7 +22,7 @@
#include "TestHelpers.h"
#include "data/basic/R.h"
-using com::android::basic::R;
+using ::com::android::basic::R;
namespace android {
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 756869f..2b72d14 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -32,8 +32,7 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk", "resources.arsc",
&contents));
- std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
ASSERT_NE(nullptr, loaded_arsc);
const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
@@ -59,8 +58,7 @@
ASSERT_TRUE(
ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
- std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
ASSERT_NE(nullptr, loaded_arsc);
ResTable_config desired_config;
@@ -82,8 +80,7 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk", "resources.arsc",
&contents));
- std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
@@ -104,8 +101,7 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/libclient/libclient.apk",
"resources.arsc", &contents));
- std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
@@ -132,8 +128,9 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
"resources.arsc", &contents));
- std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(
- contents.data(), contents.size(), false /*system*/, true /*load_as_shared_library*/);
+ std::unique_ptr<const LoadedArsc> loaded_arsc =
+ LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
+ true /*load_as_shared_library*/);
ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
@@ -147,8 +144,7 @@
std::string contents;
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc",
&contents));
- std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
ASSERT_NE(nullptr, loaded_arsc);
ResTable_config desired_config;
@@ -174,6 +170,54 @@
EXPECT_EQ(std::string("string"), type_name);
}
+class MockLoadedIdmap : public LoadedIdmap {
+ public:
+ MockLoadedIdmap() : LoadedIdmap() {
+ local_header_.magic = kIdmapMagic;
+ local_header_.version = kIdmapCurrentVersion;
+ local_header_.target_package_id = 0x08;
+ local_header_.type_count = 1;
+ header_ = &local_header_;
+
+ entry_header = util::unique_cptr<IdmapEntry_header>(
+ (IdmapEntry_header*)::malloc(sizeof(IdmapEntry_header) + sizeof(uint32_t)));
+ entry_header->target_type_id = 0x03;
+ entry_header->overlay_type_id = 0x02;
+ entry_header->entry_id_offset = 1;
+ entry_header->entry_count = 1;
+ entry_header->entries[0] = 0x00000000u;
+ type_map_[entry_header->overlay_type_id] = entry_header.get();
+ }
+
+ private:
+ Idmap_header local_header_;
+ util::unique_cptr<IdmapEntry_header> entry_header;
+};
+
+TEST(LoadedArscTest, LoadOverlay) {
+ std::string contents, overlay_contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", "resources.arsc",
+ &overlay_contents));
+
+ MockLoadedIdmap loaded_idmap;
+
+ std::unique_ptr<const LoadedArsc> loaded_arsc =
+ LoadedArsc::Load(StringPiece(overlay_contents), &loaded_idmap);
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ ResTable_config desired_config;
+ memset(&desired_config, 0, sizeof(desired_config));
+
+ LoadedArscEntry entry;
+ ResTable_config selected_config;
+ uint32_t flags;
+
+ ASSERT_TRUE(
+ loaded_arsc->FindEntry(0x08030001u, desired_config, &entry, &selected_config, &flags));
+}
+
// structs with size fields (like Res_value, ResTable_entry) should be
// backwards and forwards compatible (aka checking the size field against
// sizeof(Res_value) might not be backwards compatible.
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 59a124f..7678490 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -917,7 +917,7 @@
*/
public void setNextOutputFile(File file) throws IOException
{
- RandomAccessFile f = new RandomAccessFile(file, "rws");
+ RandomAccessFile f = new RandomAccessFile(file, "rw");
try {
_setNextOutputFile(f.getFD());
} finally {
@@ -942,7 +942,7 @@
public void prepare() throws IllegalStateException, IOException
{
if (mPath != null) {
- RandomAccessFile file = new RandomAccessFile(mPath, "rws");
+ RandomAccessFile file = new RandomAccessFile(mPath, "rw");
try {
_setOutputFile(file.getFD());
} finally {
@@ -951,7 +951,7 @@
} else if (mFd != null) {
_setOutputFile(mFd);
} else if (mFile != null) {
- RandomAccessFile file = new RandomAccessFile(mFile, "rws");
+ RandomAccessFile file = new RandomAccessFile(mFile, "rw");
try {
_setOutputFile(file.getFD());
} finally {
diff --git a/packages/SystemUI/res/drawable/recents_dismiss_all_history.xml b/packages/SystemUI/res/drawable/recents_dismiss_all_history.xml
deleted file mode 100644
index 6a417e6..0000000
--- a/packages/SystemUI/res/drawable/recents_dismiss_all_history.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2 (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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="16dp"
- android:width="28dp"
- android:viewportHeight="48"
- android:viewportWidth="72" >
- <group
- android:name="dismiss_all"
- android:translateX="48"
- android:translateY="6" >
- <group
- android:name="3"
- android:translateX="-24"
- android:translateY="36" >
- <path
- android:name="rectangle_path_1_2"
- android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- <group
- android:name="2"
- android:translateX="-12"
- android:translateY="18" >
- <path
- android:name="rectangle_path_1_1"
- android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- <group
- android:name="1" >
- <path
- android:name="rectangle_path_1"
- android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index 5ee242d..1734506 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -66,14 +66,6 @@
android:alpha="0"
android:visibility="gone" />
- <!-- The progress indicator shows if auto-paging is enabled -->
- <ViewStub android:id="@+id/focus_timer_indicator_stub"
- android:inflatedId="@+id/focus_timer_indicator"
- android:layout="@layout/recents_task_view_header_progress_bar"
- android:layout_width="match_parent"
- android:layout_height="5dp"
- android:layout_gravity="bottom" />
-
<!-- The app overlay shows as the user long-presses on the app icon -->
<ViewStub android:id="@+id/app_overlay_stub"
android:inflatedId="@+id/app_overlay"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 8a1e0b9..0fe81d9 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -167,12 +167,6 @@
<!-- The animation duration for scrolling the stack to a particular item. -->
<integer name="recents_animate_task_stack_scroll_duration">200</integer>
- <!-- The animation duration for scrolling the stack to a particular item. -->
- <integer name="recents_auto_advance_duration">750</integer>
-
- <!-- The animation duration for subsequent scrolling the stack to a particular item. -->
- <integer name="recents_subsequent_auto_advance_duration">1000</integer>
-
<!-- The delay to enforce between each alt-tab key press. -->
<integer name="recents_alt_tab_key_delay">200</integer>
@@ -328,7 +322,7 @@
<integer name="config_showTemperatureWarning">0</integer>
<!-- Temp at which to show a warning notification if config_showTemperatureWarning is true.
- If < 0, uses the value from
+ If < 0, uses the skin temperature sensor shutdown value from
HardwarePropertiesManager#getDeviceTemperatures - config_warningTemperatureTolerance. -->
<integer name="config_warningTemperature">-1</integer>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d83a6c6..1030fd7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -52,7 +52,6 @@
import android.os.BatteryManager;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Message;
import android.os.RemoteException;
@@ -78,7 +77,7 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.recents.misc.TaskStackChangeListener;
import com.google.android.collect.Lists;
@@ -1771,7 +1770,7 @@
}
}
- private final TaskStackListener mTaskStackListener = new TaskStackListener() {
+ private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onTaskStackChangedBackground() {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index f198229..4c3d5ba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -16,7 +16,6 @@
package com.android.systemui.keyguard;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.IActivityManager;
@@ -29,9 +28,8 @@
import android.os.UserHandle;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.recents.misc.TaskStackChangeListener;
public class WorkLockActivityController {
private final Context mContext;
@@ -98,7 +96,7 @@
}
}
- private final TaskStackListener mLockListener = new TaskStackListener() {
+ private final TaskStackChangeListener mLockListener = new TaskStackChangeListener() {
@Override
public void onTaskProfileLocked(int taskId, int userId) {
startWorkChallengeInTask(taskId, userId);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index f8996aa..7e87666 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -41,8 +41,7 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.component.ExpandPipEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.recents.misc.TaskStackChangeListener;
import java.io.PrintWriter;
@@ -70,7 +69,7 @@
/**
* Handler for system task stack changes.
*/
- TaskStackListener mTaskStackListener = new TaskStackListener() {
+ TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
mTouchHandler.onActivityPinned();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index e0445c1..312b990 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -20,7 +20,6 @@
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.StackInfo;
import android.app.IActivityManager;
-import android.app.RemoteAction;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -47,7 +46,7 @@
import com.android.systemui.R;
import com.android.systemui.pip.BasePipManager;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.recents.misc.TaskStackChangeListener;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -621,7 +620,7 @@
return false;
}
- private TaskStackListener mTaskStackListener = new TaskStackListener() {
+ private TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onTaskStackChanged() {
if (DEBUG) Log.d(TAG, "onTaskStackChanged()");
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index f378268..c1a3623 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -28,8 +28,14 @@
import android.os.BatteryManager;
import android.os.Handler;
import android.os.HardwarePropertiesManager;
+import android.os.IBinder;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.Temperature;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.format.DateUtils;
@@ -75,6 +81,7 @@
private float[] mRecentTemps = new float[MAX_RECENT_TEMPS];
private int mNumTemps;
private long mNextLogTime;
+ private IThermalService mThermalService;
// We create a method reference here so that we are guaranteed that we can remove a callback
// by using the same instance (method references are not guaranteed to be the same object
@@ -263,7 +270,7 @@
resources.getInteger(R.integer.config_warningTemperature));
if (mThresholdTemp < 0f) {
- // Get the throttling temperature. No need to check if we're not throttling.
+ // Get the shutdown temperature, adjust for warning tolerance.
float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
@@ -276,6 +283,25 @@
resources.getInteger(R.integer.config_warningTemperatureTolerance);
}
+ if (mThermalService == null) {
+ // Enable push notifications of throttling from vendor thermal
+ // management subsystem via thermalservice, in addition to our
+ // usual polling, to react to temperature jumps more quickly.
+ IBinder b = ServiceManager.getService("thermalservice");
+
+ if (b != null) {
+ mThermalService = IThermalService.Stub.asInterface(b);
+ try {
+ mThermalService.registerThermalEventListener(
+ new ThermalEventListener());
+ } catch (RemoteException e) {
+ // Should never happen.
+ }
+ } else {
+ Slog.w(TAG, "cannot find thermalservice, no throttling push notifications");
+ }
+ }
+
setNextLogTime();
// This initialization method may be called on a configuration change. Only one set of
@@ -414,5 +440,15 @@
void dump(PrintWriter pw);
void userSwitched();
}
-}
+ // Thermal event received from vendor thermal management subsystem
+ private final class ThermalEventListener extends IThermalEventListener.Stub {
+ @Override public void notifyThrottling(boolean isThrottling, Temperature temp) {
+ // Trigger an update of the temperature warning. Only one
+ // callback can be enabled at a time, so remove any existing
+ // callback; updateTemperatureWarning will schedule another one.
+ mHandler.removeCallbacks(mUpdateTempCallback);
+ updateTemperatureWarning();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index ab2181c..711885c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -17,7 +17,6 @@
package com.android.systemui.recents;
import android.app.Activity;
-import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.TaskStackBuilder;
import android.app.WallpaperManager;
@@ -29,10 +28,10 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-import android.provider.Settings.Secure;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@@ -42,6 +41,7 @@
import android.view.WindowManager.LayoutParams;
import com.android.internal.colorextraction.ColorExtractor;
+import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.LatencyTracker;
@@ -53,7 +53,6 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
-import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
@@ -61,10 +60,10 @@
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.ExitRecentsWindowFirstAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
-import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
+import com.android.systemui.recents.events.activity.PackagesChangedEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
@@ -85,10 +84,8 @@
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
-import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
-import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
@@ -99,7 +96,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.List;
/**
* The main Recents activity that is started from RecentsComponent.
@@ -113,7 +109,23 @@
public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
public final static int INCOMPATIBLE_APP_ALPHA_DURATION = 150;
- private RecentsPackageMonitor mPackageMonitor;
+ private PackageMonitor mPackageMonitor = new PackageMonitor() {
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ RecentsActivity.this.onPackageChanged(packageName, getChangingUserId());
+ }
+
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ RecentsActivity.this.onPackageChanged(packageName, getChangingUserId());
+ return true;
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ RecentsActivity.this.onPackageChanged(packageName, getChangingUserId());
+ }
+ };
private Handler mHandler = new Handler();
private long mLastTabKeyEventTime;
private boolean mFinishedOnStartup;
@@ -132,7 +144,6 @@
// The trigger to automatically launch the current task
private int mFocusTimerDuration;
- private DozeTrigger mIterateTrigger;
private final UserInteractionEvent mUserInteractionEvent = new UserInteractionEvent();
// Theme and colors
@@ -304,8 +315,8 @@
EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
// Initialize the package monitor
- mPackageMonitor = new RecentsPackageMonitor();
- mPackageMonitor.register(this);
+ mPackageMonitor.register(this, Looper.getMainLooper(), UserHandle.ALL,
+ true /* externalStorage */);
// Select theme based on wallpaper colors
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
@@ -327,13 +338,6 @@
}
mLastConfig = new Configuration(Utilities.getAppConfiguration(this));
- mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
- mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
- @Override
- public void run() {
- dismissRecentsToFocusedTask(MetricsEvent.OVERVIEW_SELECT_TIMEOUT);
- }
- });
// Set the window background
mRecentsView.updateBackgroundScrim(getWindow(), isInMultiWindowMode());
@@ -502,7 +506,6 @@
super.onPause();
mIgnoreAltTabRelease = false;
- mIterateTrigger.stopDozing();
}
@Override
@@ -605,8 +608,7 @@
if (backward) {
EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
} else {
- EventBus.getDefault().send(
- new FocusNextTaskViewEvent(0 /* timerIndicatorDuration */));
+ EventBus.getDefault().send(new FocusNextTaskViewEvent());
}
mLastTabKeyEventTime = SystemClock.elapsedRealtime();
@@ -664,38 +666,10 @@
}
}
- public final void onBusEvent(IterateRecentsEvent event) {
- final RecentsDebugFlags debugFlags = Recents.getDebugFlags();
-
- // Start dozing after the recents button is clicked
- int timerIndicatorDuration = 0;
- if (debugFlags.isFastToggleRecentsEnabled()) {
- timerIndicatorDuration = getResources().getInteger(
- R.integer.recents_subsequent_auto_advance_duration);
-
- mIterateTrigger.setDozeDuration(timerIndicatorDuration);
- if (!mIterateTrigger.isDozing()) {
- mIterateTrigger.startDozing();
- } else {
- mIterateTrigger.poke();
- }
- }
-
- // Focus the next task
- EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
-
- MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
- }
-
public final void onBusEvent(RecentsActivityStartingEvent event) {
mRecentsStartRequested = true;
}
- public final void onBusEvent(UserInteractionEvent event) {
- // Stop the fast-toggle dozer
- mIterateTrigger.stopDozing();
- }
-
public final void onBusEvent(HideRecentsEvent event) {
if (event.triggeredFromAltTab) {
// If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
@@ -817,11 +791,6 @@
MetricsLogger.count(this, "overview_screen_pinned", 1);
}
- public final void onBusEvent(DebugFlagsChangedEvent event) {
- // Just finish recents so that we can reload the flags anew on the next instantiation
- finish();
- }
-
public final void onBusEvent(StackViewScrolledEvent event) {
// Once the user has scrolled while holding alt-tab, then we should ignore the release of
// the key
@@ -881,6 +850,11 @@
return true;
}
+ public void onPackageChanged(String packageName, int userId) {
+ Recents.getTaskLoader().onPackageChanged(packageName);
+ EventBus.getDefault().send(new PackagesChangedEvent(packageName, userId));
+ }
+
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index 5b8ed94..2c3a727 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -60,12 +60,6 @@
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
if (launchedFromApp) {
- if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled()) {
- // If fast toggling, focus the front most task so that the next tap will launch the
- // task
- return numTasks - 1;
- }
-
if (launchState.launchedFromBlacklistedApp) {
// If we are launching from a blacklisted app, focus the front most task so that the
// next tap will launch the task
@@ -80,12 +74,6 @@
// If coming from another app, focus the next task
return Math.max(0, numTasks - 2);
} else {
- if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled()) {
- // If fast toggling, defer focusing until the next tap (which will automatically
- // focus the front most task)
- return -1;
- }
-
// If coming from home, focus the front most task
return numTasks - 1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index cb00843..a8dafbf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -16,55 +16,16 @@
package com.android.systemui.recents;
-import android.content.Context;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.tuner.TunerService;
-
-/**
- * Tunable debug flags
- */
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 button above the stack
- public static final boolean EnableStackActionButton = true;
- // Overrides the Tuner flags and enables the timeout
- private static final boolean EnableFastToggleTimeout = false;
- // Overrides the Tuner flags and enables the paging via the Recents button
- private static final boolean EnablePaging = false;
+ // Enables debug thumbnail to be fetched
+ public static final boolean EnableThumbnailDebugMode = false;
+
// Disables enter and exit transitions for other tasks for low ram devices
public static final boolean DisableRecentsLowRamEnterExitAnimation = false;
- // Enables us to create mock recents tasks
- public static final boolean EnableMockTasks = false;
- // Defines the number of mock recents packages to create
- public static final int MockTasksPackageCount = 3;
- // Defines the number of mock recents tasks to create
- public static final int MockTaskCount = 100;
- }
-
- /**
- * @return whether we are enabling fast toggling.
- */
- public boolean isFastToggleRecentsEnabled() {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.isTouchExplorationEnabled()) {
- return false;
- }
- return Static.EnableFastToggleTimeout;
- }
-
- /**
- * @return whether we are enabling paging.
- */
- public boolean isPagingEnabled() {
- return Static.EnablePaging;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 4e721d7..3f8d53f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -18,7 +18,6 @@
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.view.View.MeasureSpec;
import android.app.ActivityManager;
@@ -56,7 +55,6 @@
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
-import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchMostRecentTaskRequestEvent;
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
@@ -72,7 +70,7 @@
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ForegroundThread;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.recents.misc.TaskStackChangeListener;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
@@ -84,7 +82,6 @@
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport;
import com.android.systemui.recents.views.TaskStackView;
-import com.android.systemui.recents.views.TaskStackViewScroller;
import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
@@ -116,10 +113,10 @@
public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
/**
- * An implementation of TaskStackListener, that allows us to listen for changes to the system
+ * An implementation of TaskStackChangeListener, that allows us to listen for changes to the system
* task stacks and update recents accordingly.
*/
- class TaskStackListenerImpl extends TaskStackListener {
+ class TaskStackListenerImpl extends TaskStackChangeListener {
@Override
public void onTaskStackChangedBackground() {
@@ -408,22 +405,17 @@
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!launchState.launchedWithAltTab) {
- // Has the user tapped quickly?
- boolean isQuickTap = elapsedTime < ViewConfiguration.getDoubleTapTimeout();
if (Recents.getConfiguration().isGridEnabled) {
+ // Has the user tapped quickly?
+ boolean isQuickTap = elapsedTime < ViewConfiguration.getDoubleTapTimeout();
if (isQuickTap) {
EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
} else {
EventBus.getDefault().post(new LaunchMostRecentTaskRequestEvent());
}
} else {
- if (!debugFlags.isPagingEnabled() || isQuickTap) {
- // Launch the next focused task
- EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
- } else {
- // Notify recents to move onto the next task
- EventBus.getDefault().post(new IterateRecentsEvent());
- }
+ // Launch the next focused task
+ EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
}
} else {
// If the user has toggled it too quickly, then just eat up the event here (it's
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DebugFlagsChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DebugFlagsChangedEvent.java
deleted file mode 100644
index fe3bf26..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DebugFlagsChangedEvent.java
+++ /dev/null
@@ -1,26 +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.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the SystemUI tuner changes a flag.
- */
-public class DebugFlagsChangedEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/IterateRecentsEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/IterateRecentsEvent.java
deleted file mode 100644
index f7b2706..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/IterateRecentsEvent.java
+++ /dev/null
@@ -1,27 +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.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the user taps on the Overview button to iterate to the next item in the
- * Recents list.
- */
-public class IterateRecentsEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
index 3b68574..47670e0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
@@ -17,22 +17,20 @@
package com.android.systemui.recents.events.activity;
import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.views.TaskStackView;
+import com.android.systemui.recents.RecentsActivity;
/**
- * This event is sent by {@link RecentsPackageMonitor} when a package on the the system changes.
+ * This event is sent by {@link RecentsActivity} when a package on the the system changes.
* {@link TaskStackView}s listen for this event, and remove the tasks associated with the removed
* packages.
*/
public class PackagesChangedEvent extends EventBus.Event {
- public final RecentsPackageMonitor monitor;
public final String packageName;
public final int userId;
- public PackagesChangedEvent(RecentsPackageMonitor monitor, String packageName, int userId) {
- this.monitor = monitor;
+ public PackagesChangedEvent(String packageName, int userId) {
this.packageName = packageName;
this.userId = userId;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
index a1e4957..171ab5e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
@@ -22,10 +22,5 @@
* Focuses the next task view in the stack.
*/
public class FocusNextTaskViewEvent extends EventBus.Event {
-
- public final int timerIndicatorDuration;
-
- public FocusNextTaskViewEvent(int timerIndicatorDuration) {
- this.timerIndicatorDuration = timerIndicatorDuration;
- }
+ // Simple event
}
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 b1eb77d..a392eff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -31,7 +31,6 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
-import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityManager;
@@ -55,15 +54,13 @@
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.IRemoteCallback;
-import android.os.Message;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -89,7 +86,7 @@
import com.android.systemui.UiOffloadThread;
import com.android.systemui.pip.tv.PipMenuActivity;
import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsDebugFlags;
+import com.android.systemui.recents.RecentsDebugFlags.Static;
import com.android.systemui.recents.RecentsImpl;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.ThumbnailData;
@@ -99,7 +96,6 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import java.util.Random;
/**
* Acts as a shim around the real system services that we need to access data from, and provides
@@ -138,17 +134,17 @@
UserManager mUm;
Display mDisplay;
String mRecentsPackage;
+ private TaskStackChangeListeners mTaskStackChangeListeners;
private int mCurrentUserId;
boolean mIsSafeMode;
- Bitmap mDummyIcon;
int mDummyThumbnailWidth;
int mDummyThumbnailHeight;
Paint mBgProtectionPaint;
Canvas mBgProtectionCanvas;
- private final Handler mHandler = new H();
+ private final Handler mHandler = new Handler();
private final Runnable mGcRunnable = new Runnable() {
@Override
public void run() {
@@ -159,144 +155,10 @@
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
- /**
- * An abstract class to track task stack changes.
- * Classes should implement this instead of {@link android.app.ITaskStackListener}
- * to reduce IPC calls from system services. These callbacks will be called on the main thread.
- */
- public abstract static class TaskStackListener {
- /**
- * NOTE: This call is made of the thread that the binder call comes in on.
- */
- public void onTaskStackChangedBackground() { }
- public void onTaskStackChanged() { }
- public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
- public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { }
- public void onActivityUnpinned() { }
- public void onPinnedActivityRestartAttempt(boolean clearedTask) { }
- public void onPinnedStackAnimationStarted() { }
- public void onPinnedStackAnimationEnded() { }
- public void onActivityForcedResizable(String packageName, int taskId, int reason) { }
- public void onActivityDismissingDockedStack() { }
- public void onActivityLaunchOnSecondaryDisplayFailed() { }
- public void onTaskProfileLocked(int taskId, int userId) { }
-
- /**
- * Checks that the current user matches the user's SystemUI process. Since
- * {@link android.app.ITaskStackListener} is not multi-user aware, handlers of
- * TaskStackListener should make this call to verify that we don't act on events from other
- * user's processes.
- */
- protected final boolean checkCurrentUserId(Context context, boolean debug) {
- int processUserId = UserHandle.myUserId();
- int currentUserId = SystemServicesProxy.getInstance(context).getCurrentUser();
- if (processUserId != currentUserId) {
- if (debug) {
- Log.d(TAG, "UID mismatch. SystemUI is running uid=" + processUserId
- + " and the current user is uid=" + currentUserId);
- }
- return false;
- }
- return true;
- }
- }
-
- /**
- * Implementation of {@link android.app.ITaskStackListener} to listen task stack changes from
- * ActivityManagerService.
- * This simply passes callbacks to listeners through {@link H}.
- * */
- private android.app.TaskStackListener mTaskStackListener = new android.app.TaskStackListener() {
-
- private final List<SystemServicesProxy.TaskStackListener> mTmpListeners = new ArrayList<>();
-
- @Override
- public void onTaskStackChanged() throws RemoteException {
- // Call the task changed callback for the non-ui thread listeners first
- synchronized (mTaskStackListeners) {
- mTmpListeners.clear();
- mTmpListeners.addAll(mTaskStackListeners);
- }
- for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
- mTmpListeners.get(i).onTaskStackChangedBackground();
- }
-
- mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
- mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
- }
-
- @Override
- public void onActivityPinned(String packageName, int userId, int taskId, int stackId)
- throws RemoteException {
- mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
- mHandler.obtainMessage(H.ON_ACTIVITY_PINNED,
- new PinnedActivityInfo(packageName, userId, taskId, stackId)).sendToTarget();
- }
-
- @Override
- public void onActivityUnpinned() throws RemoteException {
- mHandler.removeMessages(H.ON_ACTIVITY_UNPINNED);
- mHandler.sendEmptyMessage(H.ON_ACTIVITY_UNPINNED);
- }
-
- @Override
- public void onPinnedActivityRestartAttempt(boolean clearedTask)
- throws RemoteException{
- mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
- mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT, clearedTask ? 1 : 0, 0)
- .sendToTarget();
- }
-
- @Override
- public void onPinnedStackAnimationStarted() throws RemoteException {
- mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_STARTED);
- mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_STARTED);
- }
-
- @Override
- public void onPinnedStackAnimationEnded() throws RemoteException {
- mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED);
- mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED);
- }
-
- @Override
- public void onActivityForcedResizable(String packageName, int taskId, int reason)
- throws RemoteException {
- mHandler.obtainMessage(H.ON_ACTIVITY_FORCED_RESIZABLE, taskId, reason, packageName)
- .sendToTarget();
- }
-
- @Override
- public void onActivityDismissingDockedStack() throws RemoteException {
- mHandler.sendEmptyMessage(H.ON_ACTIVITY_DISMISSING_DOCKED_STACK);
- }
-
- @Override
- public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
- mHandler.sendEmptyMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED);
- }
-
- @Override
- public void onTaskProfileLocked(int taskId, int userId) {
- mHandler.obtainMessage(H.ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget();
- }
-
- @Override
- public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot)
- throws RemoteException {
- mHandler.obtainMessage(H.ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot).sendToTarget();
- }
- };
-
private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
(String name, Drawable picture, String userAccount) ->
mCurrentUserId = mAm.getCurrentUser();
- /**
- * List of {@link TaskStackListener} registered from {@link #registerTaskStackListener}.
- */
- private List<TaskStackListener> mTaskStackListeners = new ArrayList<>();
-
/** Private constructor */
private SystemServicesProxy(Context context) {
mContext = context.getApplicationContext();
@@ -317,6 +179,7 @@
mRecentsPackage = context.getPackageName();
mIsSafeMode = mPm.isSafeMode();
mCurrentUserId = mAm.getCurrentUser();
+ mTaskStackChangeListeners = new TaskStackChangeListeners(Looper.getMainLooper());
// Get the dummy thumbnail width/heights
Resources res = context.getResources();
@@ -337,12 +200,6 @@
UserInfoController userInfoController = Dependency.get(UserInfoController.class);
userInfoController.addCallback(mOnUserInfoChangedListener);
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- // Create a dummy icon
- mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
- mDummyIcon.eraseColor(0xFF999999);
- }
-
Collections.addAll(sRecentsBlacklist,
res.getStringArray(R.array.recents_blacklist_array));
}
@@ -378,39 +235,6 @@
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(numTasks, RecentsDebugFlags.Static.MockTaskCount);
- for (int i = 0; i < count; i++) {
- // Create a dummy component name
- int packageIndex = i % RecentsDebugFlags.Static.MockTasksPackageCount;
- ComponentName cn = new ComponentName("com.android.test" + packageIndex,
- "com.android.test" + i + ".Activity");
- String description = "" + i + " - " +
- Long.toString(Math.abs(new Random().nextLong()), 36);
- // Create the recent task info
- ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
- rti.id = rti.persistentId = rti.affiliatedTaskId = i;
- rti.baseIntent = new Intent();
- rti.baseIntent.setComponent(cn);
- rti.description = description;
- rti.lastActiveTime = i;
- if (i % 2 == 0) {
- rti.taskDescription = new ActivityManager.TaskDescription(description,
- Bitmap.createBitmap(mDummyIcon), null,
- 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
- 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
- 0, 0);
- } else {
- rti.taskDescription = new ActivityManager.TaskDescription();
- }
- tasks.add(rti);
- }
- return tasks;
- }
-
try {
List<ActivityManager.RecentTaskInfo> tasks = mIam.getRecentTasks(numTasks,
RECENT_IGNORE_UNAVAILABLE, userId).getList();
@@ -638,7 +462,7 @@
if (mAm == null) return null;
// If we are mocking, then just return a dummy thumbnail
- if (RecentsDebugFlags.Static.EnableMockTasks) {
+ if (Static.EnableTransitionThumbnailDebugMode) {
ThumbnailData thumbnailData = new ThumbnailData();
thumbnailData.thumbnail = Bitmap.createBitmap(mDummyThumbnailWidth,
mDummyThumbnailHeight, Bitmap.Config.ARGB_8888);
@@ -684,11 +508,14 @@
/** Removes the task */
public void removeTask(final int taskId) {
if (mAm == null) return;
- if (RecentsDebugFlags.Static.EnableMockTasks) return;
// Remove the task.
mUiOffloadThread.submit(() -> {
- mAm.removeTask(taskId);
+ try {
+ mIam.removeTask(taskId);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
});
}
@@ -712,7 +539,6 @@
*/
public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
if (mIpm == null) return null;
- if (RecentsDebugFlags.Static.EnableMockTasks) return new ActivityInfo();
try {
return mIpm.getActivityInfo(cn, PackageManager.GET_META_DATA, userId);
@@ -729,7 +555,6 @@
*/
public ActivityInfo getActivityInfo(ComponentName cn) {
if (mPm == null) return null;
- if (RecentsDebugFlags.Static.EnableMockTasks) return new ActivityInfo();
try {
return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
@@ -745,11 +570,6 @@
public String getBadgedActivityLabel(ActivityInfo info, int userId) {
if (mPm == null) return null;
- // If we are mocking, then return a mock label
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- return "Recent Task: " + userId;
- }
-
return getBadgedLabel(info.loadLabel(mPm).toString(), userId);
}
@@ -759,11 +579,6 @@
public String getBadgedApplicationLabel(ApplicationInfo appInfo, int userId) {
if (mPm == null) return null;
- // If we are mocking, then return a mock label
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- return "Recent Task App: " + userId;
- }
-
return getBadgedLabel(appInfo.loadLabel(mPm).toString(), userId);
}
@@ -773,11 +588,6 @@
*/
public String getBadgedContentDescription(ActivityInfo info, int userId,
ActivityManager.TaskDescription td, Resources res) {
- // If we are mocking, then return a mock label
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- return "Recent Task Content Description: " + userId;
- }
-
String activityLabel;
if (td != null && td.getLabel() != null) {
activityLabel = td.getLabel();
@@ -798,11 +608,6 @@
public Drawable getBadgedActivityIcon(ActivityInfo info, int userId) {
if (mPm == null) return null;
- // If we are mocking, then return a mock label
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- return new ColorDrawable(0xFF666666);
- }
-
return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId);
}
@@ -813,11 +618,6 @@
public Drawable getBadgedApplicationIcon(ApplicationInfo appInfo, int userId) {
if (mPm == null) return null;
- // If we are mocking, then return a mock label
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- return new ColorDrawable(0xFF666666);
- }
-
return mDrawableFactory.getBadgedIcon(appInfo, userId);
}
@@ -826,12 +626,6 @@
*/
public Drawable getBadgedTaskDescriptionIcon(ActivityManager.TaskDescription taskDescription,
int userId, Resources res) {
-
- // If we are mocking, then return a mock label
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- return new ColorDrawable(0xFF666666);
- }
-
Bitmap tdIcon = taskDescription.getInMemoryIcon();
if (tdIcon == null) {
tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon(
@@ -867,11 +661,6 @@
public Drawable getActivityBanner(ActivityInfo info) {
if (mPm == null) return null;
- // If we are mocking, then return a mock banner
- if (RecentsDebugFlags.Static.EnableMockTasks) {
- return new ColorDrawable(0xFF666666);
- }
-
Drawable banner = info.loadBanner(mPm);
return banner;
}
@@ -1084,19 +873,11 @@
* Registers a task stack listener with the system.
* This should be called on the main thread.
*/
- public void registerTaskStackListener(TaskStackListener listener) {
+ public void registerTaskStackListener(TaskStackChangeListener listener) {
if (mIam == null) return;
- synchronized (mTaskStackListeners) {
- mTaskStackListeners.add(listener);
- if (mTaskStackListeners.size() == 1) {
- // Register mTaskStackListener to IActivityManager only once if needed.
- try {
- mIam.registerTaskStackListener(mTaskStackListener);
- } catch (Exception e) {
- Log.w(TAG, "Failed to call registerTaskStackListener", e);
- }
- }
+ synchronized (mTaskStackChangeListeners) {
+ mTaskStackChangeListeners.addListener(mIam, listener);
}
}
@@ -1161,23 +942,27 @@
/**
* Updates the visibility of recents.
*/
- public void setRecentsVisibility(boolean visible) {
- try {
- mIwm.setRecentsVisibility(visible);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to reach window manager", e);
- }
+ public void setRecentsVisibility(final boolean visible) {
+ mUiOffloadThread.submit(() -> {
+ try {
+ mIwm.setRecentsVisibility(visible);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to reach window manager", e);
+ }
+ });
}
/**
* Updates the visibility of the picture-in-picture.
*/
- public void setPipVisibility(boolean visible) {
- try {
- mIwm.setPipVisibility(visible);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to reach window manager", e);
- }
+ public void setPipVisibility(final boolean visible) {
+ mUiOffloadThread.submit(() -> {
+ try {
+ mIwm.setPipVisibility(visible);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to reach window manager", e);
+ }
+ });
}
public boolean isDreaming() {
@@ -1202,115 +987,4 @@
public interface StartActivityFromRecentsResultListener {
void onStartActivityResult(boolean succeeded);
}
-
- private class PinnedActivityInfo {
- final String mPackageName;
- final int mUserId;
- final int mTaskId;
- final int mStackId;
-
- PinnedActivityInfo(String packageName, int userId, int taskId, int stackId) {
- mPackageName = packageName;
- mUserId = userId;
- mTaskId = taskId;
- mStackId = stackId;
- }
- }
-
- private final class H extends Handler {
- private static final int ON_TASK_STACK_CHANGED = 1;
- private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
- private static final int ON_ACTIVITY_PINNED = 3;
- private static final int ON_PINNED_ACTIVITY_RESTART_ATTEMPT = 4;
- private static final int ON_PINNED_STACK_ANIMATION_ENDED = 5;
- private static final int ON_ACTIVITY_FORCED_RESIZABLE = 6;
- private static final int ON_ACTIVITY_DISMISSING_DOCKED_STACK = 7;
- private static final int ON_TASK_PROFILE_LOCKED = 8;
- private static final int ON_PINNED_STACK_ANIMATION_STARTED = 9;
- private static final int ON_ACTIVITY_UNPINNED = 10;
- private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED = 11;
-
- @Override
- public void handleMessage(Message msg) {
- synchronized (mTaskStackListeners) {
- switch (msg.what) {
- case ON_TASK_STACK_CHANGED: {
- Trace.beginSection("onTaskStackChanged");
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskStackChanged();
- }
- Trace.endSection();
- break;
- }
- case ON_TASK_SNAPSHOT_CHANGED: {
- Trace.beginSection("onTaskSnapshotChanged");
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
- (TaskSnapshot) msg.obj);
- }
- Trace.endSection();
- break;
- }
- case ON_ACTIVITY_PINNED: {
- final PinnedActivityInfo info = (PinnedActivityInfo) msg.obj;
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityPinned(
- info.mPackageName, info.mUserId, info.mTaskId, info.mStackId);
- }
- break;
- }
- case ON_ACTIVITY_UNPINNED: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityUnpinned();
- }
- break;
- }
- case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(
- msg.arg1 != 0);
- }
- break;
- }
- case ON_PINNED_STACK_ANIMATION_STARTED: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onPinnedStackAnimationStarted();
- }
- break;
- }
- case ON_PINNED_STACK_ANIMATION_ENDED: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onPinnedStackAnimationEnded();
- }
- break;
- }
- case ON_ACTIVITY_FORCED_RESIZABLE: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityForcedResizable(
- (String) msg.obj, msg.arg1, msg.arg2);
- }
- break;
- }
- case ON_ACTIVITY_DISMISSING_DOCKED_STACK: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityDismissingDockedStack();
- }
- break;
- }
- case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed();
- }
- break;
- }
- case ON_TASK_PROFILE_LOCKED: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2);
- }
- break;
- }
- }
- }
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/TaskStackChangeListener.java b/packages/SystemUI/src/com/android/systemui/recents/misc/TaskStackChangeListener.java
new file mode 100644
index 0000000..6d0952a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/TaskStackChangeListener.java
@@ -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.
+ */
+
+package com.android.systemui.recents.misc;
+
+import android.app.ActivityManager.TaskSnapshot;
+import android.content.Context;
+import android.os.UserHandle;
+import android.util.Log;
+
+/**
+ * An abstract class to track task stack changes.
+ * Classes should implement this instead of {@link android.app.ITaskStackListener}
+ * to reduce IPC calls from system services. These callbacks will be called on the main thread.
+ */
+public abstract class TaskStackChangeListener {
+
+ /**
+ * NOTE: This call is made of the thread that the binder call comes in on.
+ */
+ public void onTaskStackChangedBackground() { }
+ public void onTaskStackChanged() { }
+ public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
+ public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { }
+ public void onActivityUnpinned() { }
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) { }
+ public void onPinnedStackAnimationStarted() { }
+ public void onPinnedStackAnimationEnded() { }
+ public void onActivityForcedResizable(String packageName, int taskId, int reason) { }
+ public void onActivityDismissingDockedStack() { }
+ public void onActivityLaunchOnSecondaryDisplayFailed() { }
+ public void onTaskProfileLocked(int taskId, int userId) { }
+
+ /**
+ * Checks that the current user matches the user's SystemUI process. Since
+ * {@link android.app.ITaskStackListener} is not multi-user aware, handlers of
+ * TaskStackChangeListener should make this call to verify that we don't act on events from other
+ * user's processes.
+ */
+ protected final boolean checkCurrentUserId(Context context, boolean debug) {
+ int processUserId = UserHandle.myUserId();
+ int currentUserId = SystemServicesProxy.getInstance(context).getCurrentUser();
+ if (processUserId != currentUserId) {
+ if (debug) {
+ Log.d(SystemServicesProxy.TAG, "UID mismatch. SystemUI is running uid=" + processUserId
+ + " and the current user is uid=" + currentUserId);
+ }
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/TaskStackChangeListeners.java b/packages/SystemUI/src/com/android/systemui/recents/misc/TaskStackChangeListeners.java
new file mode 100644
index 0000000..8eb70f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/TaskStackChangeListeners.java
@@ -0,0 +1,254 @@
+/*
+ * 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.systemui.recents.misc;
+
+import android.app.ActivityManager.TaskSnapshot;
+import android.app.IActivityManager;
+import android.app.TaskStackListener;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.Trace;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tracks all the task stack listeners
+ */
+public class TaskStackChangeListeners extends TaskStackListener {
+
+ private static final String TAG = TaskStackChangeListeners.class.getSimpleName();
+
+ /**
+ * List of {@link TaskStackChangeListener} registered from {@link #addListener}.
+ */
+ private final List<TaskStackChangeListener> mTaskStackListeners = new ArrayList<>();
+ private final List<TaskStackChangeListener> mTmpListeners = new ArrayList<>();
+
+ private final Handler mHandler;
+
+ public TaskStackChangeListeners(Looper looper) {
+ mHandler = new H(looper);
+ }
+
+ public void addListener(IActivityManager am, TaskStackChangeListener listener) {
+ mTaskStackListeners.add(listener);
+ if (mTaskStackListeners.size() == 1) {
+ // Register mTaskStackListener to IActivityManager only once if needed.
+ try {
+ am.registerTaskStackListener(this);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to call registerTaskStackListener", e);
+ }
+ }
+ }
+
+ @Override
+ public void onTaskStackChanged() throws RemoteException {
+ // Call the task changed callback for the non-ui thread listeners first
+ synchronized (mTaskStackListeners) {
+ mTmpListeners.clear();
+ mTmpListeners.addAll(mTaskStackListeners);
+ }
+ for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
+ mTmpListeners.get(i).onTaskStackChangedBackground();
+ }
+
+ mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
+ mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
+ }
+
+ @Override
+ public void onActivityPinned(String packageName, int userId, int taskId, int stackId)
+ throws RemoteException {
+ mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
+ mHandler.obtainMessage(H.ON_ACTIVITY_PINNED,
+ new PinnedActivityInfo(packageName, userId, taskId, stackId)).sendToTarget();
+ }
+
+ @Override
+ public void onActivityUnpinned() throws RemoteException {
+ mHandler.removeMessages(H.ON_ACTIVITY_UNPINNED);
+ mHandler.sendEmptyMessage(H.ON_ACTIVITY_UNPINNED);
+ }
+
+ @Override
+ public void onPinnedActivityRestartAttempt(boolean clearedTask)
+ throws RemoteException{
+ mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
+ mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT, clearedTask ? 1 : 0, 0)
+ .sendToTarget();
+ }
+
+ @Override
+ public void onPinnedStackAnimationStarted() throws RemoteException {
+ mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_STARTED);
+ mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_STARTED);
+ }
+
+ @Override
+ public void onPinnedStackAnimationEnded() throws RemoteException {
+ mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED);
+ mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED);
+ }
+
+ @Override
+ public void onActivityForcedResizable(String packageName, int taskId, int reason)
+ throws RemoteException {
+ mHandler.obtainMessage(H.ON_ACTIVITY_FORCED_RESIZABLE, taskId, reason, packageName)
+ .sendToTarget();
+ }
+
+ @Override
+ public void onActivityDismissingDockedStack() throws RemoteException {
+ mHandler.sendEmptyMessage(H.ON_ACTIVITY_DISMISSING_DOCKED_STACK);
+ }
+
+ @Override
+ public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
+ mHandler.sendEmptyMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED);
+ }
+
+ @Override
+ public void onTaskProfileLocked(int taskId, int userId) throws RemoteException {
+ mHandler.obtainMessage(H.ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget();
+ }
+
+ @Override
+ public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot)
+ throws RemoteException {
+ mHandler.obtainMessage(H.ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot).sendToTarget();
+ }
+
+ private final class H extends Handler {
+ private static final int ON_TASK_STACK_CHANGED = 1;
+ private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
+ private static final int ON_ACTIVITY_PINNED = 3;
+ private static final int ON_PINNED_ACTIVITY_RESTART_ATTEMPT = 4;
+ private static final int ON_PINNED_STACK_ANIMATION_ENDED = 5;
+ private static final int ON_ACTIVITY_FORCED_RESIZABLE = 6;
+ private static final int ON_ACTIVITY_DISMISSING_DOCKED_STACK = 7;
+ private static final int ON_TASK_PROFILE_LOCKED = 8;
+ private static final int ON_PINNED_STACK_ANIMATION_STARTED = 9;
+ private static final int ON_ACTIVITY_UNPINNED = 10;
+ private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED = 11;
+
+ public H(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ synchronized (mTaskStackListeners) {
+ switch (msg.what) {
+ case ON_TASK_STACK_CHANGED: {
+ Trace.beginSection("onTaskStackChanged");
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onTaskStackChanged();
+ }
+ Trace.endSection();
+ break;
+ }
+ case ON_TASK_SNAPSHOT_CHANGED: {
+ Trace.beginSection("onTaskSnapshotChanged");
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
+ (TaskSnapshot) msg.obj);
+ }
+ Trace.endSection();
+ break;
+ }
+ case ON_ACTIVITY_PINNED: {
+ final PinnedActivityInfo info = (PinnedActivityInfo) msg.obj;
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onActivityPinned(
+ info.mPackageName, info.mUserId, info.mTaskId, info.mStackId);
+ }
+ break;
+ }
+ case ON_ACTIVITY_UNPINNED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onActivityUnpinned();
+ }
+ break;
+ }
+ case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(
+ msg.arg1 != 0);
+ }
+ break;
+ }
+ case ON_PINNED_STACK_ANIMATION_STARTED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onPinnedStackAnimationStarted();
+ }
+ break;
+ }
+ case ON_PINNED_STACK_ANIMATION_ENDED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onPinnedStackAnimationEnded();
+ }
+ break;
+ }
+ case ON_ACTIVITY_FORCED_RESIZABLE: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onActivityForcedResizable(
+ (String) msg.obj, msg.arg1, msg.arg2);
+ }
+ break;
+ }
+ case ON_ACTIVITY_DISMISSING_DOCKED_STACK: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onActivityDismissingDockedStack();
+ }
+ break;
+ }
+ case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed();
+ }
+ break;
+ }
+ case ON_TASK_PROFILE_LOCKED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private static class PinnedActivityInfo {
+ final String mPackageName;
+ final int mUserId;
+ final int mTaskId;
+ final int mStackId;
+
+ PinnedActivityInfo(String packageName, int userId, int taskId, int stackId) {
+ mPackageName = packageName;
+ mUserId = userId;
+ mTaskId = taskId;
+ mStackId = stackId;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
deleted file mode 100644
index 308cece..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
+++ /dev/null
@@ -1,74 +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.model;
-
-import android.content.Context;
-import android.os.UserHandle;
-
-import com.android.internal.content.PackageMonitor;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.PackagesChangedEvent;
-import com.android.systemui.recents.misc.ForegroundThread;
-
-/**
- * The package monitor listens for changes from PackageManager to update the contents of the
- * Recents list.
- */
-public class RecentsPackageMonitor extends PackageMonitor {
-
- /** Registers the broadcast receivers with the specified callbacks. */
- public void register(Context context) {
- try {
- // We register for events from all users, but will cross-reference them with
- // packages for the current user and any profiles they have. Ensure that events are
- // handled in a background thread.
- register(context, ForegroundThread.get().getLooper(), UserHandle.ALL, true);
- } catch (IllegalStateException e) {
- e.printStackTrace();
- }
- }
-
- /** Unregisters the broadcast receivers. */
- @Override
- public void unregister() {
- try {
- super.unregister();
- } catch (IllegalStateException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onPackageRemoved(String packageName, int uid) {
- // Notify callbacks on the main thread that a package has changed
- final int eventUserId = getChangingUserId();
- EventBus.getDefault().post(new PackagesChangedEvent(this, packageName, eventUserId));
- }
-
- @Override
- public boolean onPackageChanged(String packageName, int uid, String[] components) {
- onPackageModified(packageName);
- return true;
- }
-
- @Override
- public void onPackageModified(String packageName) {
- // Notify callbacks on the main thread that a package has changed
- final int eventUserId = getChangingUserId();
- EventBus.getDefault().post(new PackagesChangedEvent(this, packageName, eventUserId));
- }
-}
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 94558c3..3494a00 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -256,7 +256,7 @@
// This activity info LruCache is useful because it can be expensive to retrieve ActivityInfos
// for many tasks, which we use to get the activity labels and icons. Unlike the other caches
// below, this is per-package so we can't invalidate the items in the cache based on the last
- // active time. Instead, we rely on the RecentsPackageMonitor to keep us informed whenever a
+ // active time. Instead, we rely on the PackageMonitor to keep us informed whenever a
// package in the cache has been updated, so that we may remove it.
private final LruCache<ComponentName, ActivityInfo> mActivityInfoCache;
private final TaskKeyLruCache<Drawable> mIconCache;
@@ -295,8 +295,6 @@
context.getColor(R.color.recents_task_view_default_background_color);
mMaxThumbnailCacheSize = res.getInteger(R.integer.config_recents_max_thumbnail_count);
mMaxIconCacheSize = res.getInteger(R.integer.config_recents_max_icon_count);
- int iconCacheSize = RecentsDebugFlags.Static.DisableBackgroundCache ? 1 :
- mMaxIconCacheSize;
// Create the default assets
Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
@@ -308,7 +306,7 @@
mHighResThumbnailLoader = new HighResThumbnailLoader(Recents.getSystemServices(),
Looper.getMainLooper(), Recents.getConfiguration().isLowRamDevice);
mLoadQueue = new TaskResourceLoadQueue();
- mIconCache = new TaskKeyLruCache<>(iconCacheSize, mClearActivityInfoOnEviction);
+ mIconCache = new TaskKeyLruCache<>(mMaxIconCacheSize, mClearActivityInfoOnEviction);
mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks, mClearActivityInfoOnEviction);
mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks,
mClearActivityInfoOnEviction);
@@ -437,6 +435,21 @@
}
}
+ public void onPackageChanged(String packageName) {
+ // Remove all the cached activity infos for this package. The other caches do not need to
+ // be pruned at this time, as the TaskKey expiration checks will flush them next time their
+ // cached contents are requested
+ Map<ComponentName, ActivityInfo> activityInfoCache = mActivityInfoCache.snapshot();
+ for (ComponentName cn : activityInfoCache.keySet()) {
+ if (cn.getPackageName().equals(packageName)) {
+ if (DEBUG) {
+ Log.d(TAG, "Removing activity info from cache: " + cn);
+ }
+ mActivityInfoCache.remove(cn);
+ }
+ }
+ }
+
/**
* Returns the cached task label if the task key is not expired, updating the cache if it is.
*/
@@ -625,23 +638,6 @@
mLoadQueue.clearTasks();
}
- /**** Event Bus Events ****/
-
- public final void onBusEvent(PackagesChangedEvent event) {
- // Remove all the cached activity infos for this package. The other caches do not need to
- // be pruned at this time, as the TaskKey expiration checks will flush them next time their
- // cached contents are requested
- Map<ComponentName, ActivityInfo> activityInfoCache = mActivityInfoCache.snapshot();
- for (ComponentName cn : activityInfoCache.keySet()) {
- if (cn.getPackageName().equals(event.packageName)) {
- if (DEBUG) {
- Log.d(TAG, "Removing activity info from cache: " + cn);
- }
- mActivityInfoCache.remove(cn);
- }
- }
- }
-
public synchronized void dump(String prefix, PrintWriter writer) {
String innerPrefix = prefix + " ";
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 e2f157e..e1b22b4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -160,22 +160,20 @@
mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
addView(mEmptyView);
- if (RecentsDebugFlags.Static.EnableStackActionButton) {
- if (mStackActionButton != null) {
- removeView(mStackActionButton);
- }
- mStackActionButton = (TextView) inflater.inflate(Recents.getConfiguration()
- .isLowRamDevice
- ? R.layout.recents_low_ram_stack_action_button
- : R.layout.recents_stack_action_button,
- this, false);
-
- mStackButtonShadowRadius = mStackActionButton.getShadowRadius();
- mStackButtonShadowDistance = new PointF(mStackActionButton.getShadowDx(),
- mStackActionButton.getShadowDy());
- mStackButtonShadowColor = mStackActionButton.getShadowColor();
- addView(mStackActionButton);
+ if (mStackActionButton != null) {
+ removeView(mStackActionButton);
}
+ mStackActionButton = (TextView) inflater.inflate(Recents.getConfiguration()
+ .isLowRamDevice
+ ? R.layout.recents_low_ram_stack_action_button
+ : R.layout.recents_stack_action_button,
+ this, false);
+
+ mStackButtonShadowRadius = mStackActionButton.getShadowRadius();
+ mStackButtonShadowDistance = new PointF(mStackActionButton.getShadowDx(),
+ mStackActionButton.getShadowDy());
+ mStackButtonShadowColor = mStackActionButton.getShadowColor();
+ addView(mStackActionButton);
reevaluateStyles();
}
@@ -358,9 +356,7 @@
mEmptyView.setText(msgResId);
mEmptyView.setVisibility(View.VISIBLE);
mEmptyView.bringToFront();
- if (RecentsDebugFlags.Static.EnableStackActionButton) {
- mStackActionButton.bringToFront();
- }
+ mStackActionButton.bringToFront();
}
/**
@@ -370,9 +366,7 @@
mEmptyView.setVisibility(View.INVISIBLE);
mTaskStackView.setVisibility(View.VISIBLE);
mTaskStackView.bringToFront();
- if (RecentsDebugFlags.Static.EnableStackActionButton) {
- mStackActionButton.bringToFront();
- }
+ mStackActionButton.bringToFront();
}
/**
@@ -420,13 +414,11 @@
MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
}
- if (RecentsDebugFlags.Static.EnableStackActionButton) {
- // Measure the stack action button within the constraints of the space above the stack
- Rect buttonBounds = mTaskStackView.mLayoutAlgorithm.getStackActionButtonRect();
- measureChild(mStackActionButton,
- MeasureSpec.makeMeasureSpec(buttonBounds.width(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(buttonBounds.height(), MeasureSpec.AT_MOST));
- }
+ // Measure the stack action button within the constraints of the space above the stack
+ Rect buttonBounds = mTaskStackView.mLayoutAlgorithm.getStackActionButtonRect();
+ measureChild(mStackActionButton,
+ MeasureSpec.makeMeasureSpec(buttonBounds.width(), MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(buttonBounds.height(), MeasureSpec.AT_MOST));
setMeasuredDimension(width, height);
}
@@ -460,13 +452,11 @@
mBackgroundScrim.setBounds(left, top, right, bottom);
mMultiWindowBackgroundScrim.setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
- if (RecentsDebugFlags.Static.EnableStackActionButton) {
- // Layout the stack action button such that its drawable is start-aligned with the
- // stack, vertically centered in the available space above the stack
- Rect buttonBounds = getStackActionButtonBoundsFromStackLayout();
- mStackActionButton.layout(buttonBounds.left, buttonBounds.top, buttonBounds.right,
- buttonBounds.bottom);
- }
+ // Layout the stack action button such that its drawable is start-aligned with the
+ // stack, vertically centered in the available space above the stack
+ Rect buttonBounds = getStackActionButtonBoundsFromStackLayout();
+ mStackActionButton.layout(buttonBounds.left, buttonBounds.top, buttonBounds.right,
+ buttonBounds.bottom);
if (mAwaitingFirstLayout) {
mAwaitingFirstLayout = false;
@@ -539,10 +529,8 @@
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
- if (RecentsDebugFlags.Static.EnableStackActionButton) {
- // Hide the stack action button
- EventBus.getDefault().send(new HideStackActionButtonEvent());
- }
+ // Hide the stack action button
+ EventBus.getDefault().send(new HideStackActionButtonEvent());
animateBackgroundScrim(0f, taskViewExitToHomeDuration);
if (Recents.getConfiguration().isLowRamDevice) {
@@ -717,18 +705,10 @@
}
public final void onBusEvent(ShowStackActionButtonEvent event) {
- if (!RecentsDebugFlags.Static.EnableStackActionButton) {
- return;
- }
-
showStackActionButton(SHOW_STACK_ACTION_BUTTON_DURATION, event.translate);
}
public final void onBusEvent(HideStackActionButtonEvent event) {
- if (!RecentsDebugFlags.Static.EnableStackActionButton) {
- return;
- }
-
hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */);
}
@@ -744,10 +724,6 @@
* Shows the stack action button.
*/
private void showStackActionButton(final int duration, final boolean translate) {
- if (!RecentsDebugFlags.Static.EnableStackActionButton) {
- return;
- }
-
final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
if (mStackActionButton.getVisibility() == View.INVISIBLE) {
mStackActionButton.setVisibility(View.VISIBLE);
@@ -780,10 +756,6 @@
* Hides the stack action button.
*/
private void hideStackActionButton(int duration, boolean translate) {
- if (!RecentsDebugFlags.Static.EnableStackActionButton) {
- return;
- }
-
final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
hideStackActionButton(duration, translate, postAnimationTrigger);
postAnimationTrigger.flushLastDecrementRunnables();
@@ -794,10 +766,6 @@
*/
private void hideStackActionButton(int duration, boolean translate,
final ReferenceCountedTrigger postAnimationTrigger) {
- if (!RecentsDebugFlags.Static.EnableStackActionButton) {
- return;
- }
-
if (mStackActionButton.getVisibility() == View.VISIBLE) {
if (translate) {
mStackActionButton.animate().translationY(mStackActionButton.getMeasuredHeight()
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 af95b3c..5ba5f44 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -669,7 +669,7 @@
public int getInitialFocusState() {
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
- if (debugFlags.isPagingEnabled() || launchState.launchedWithAltTab) {
+ if (launchState.launchedWithAltTab) {
return STATE_FOCUSED;
} else {
return STATE_UNFOCUSED;
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 fd29708..cda5fb8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -57,7 +57,6 @@
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
-import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchMostRecentTaskRequestEvent;
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
@@ -1698,15 +1697,11 @@
}
public final void onBusEvent(ShowStackActionButtonEvent event) {
- if (RecentsDebugFlags.Static.EnableStackActionButton) {
- mStackActionButtonVisible = true;
- }
+ mStackActionButtonVisible = true;
}
public final void onBusEvent(HideStackActionButtonEvent event) {
- if (RecentsDebugFlags.Static.EnableStackActionButton) {
- mStackActionButtonVisible = false;
- }
+ mStackActionButtonVisible = false;
}
public final void onBusEvent(LaunchNextTaskRequestEvent event) {
@@ -1844,8 +1839,7 @@
mStackScroller.stopScroller();
mStackScroller.stopBoundScrollAnimation();
- setRelativeFocusedTask(true, false /* stackTasksOnly */, true /* animated */, false,
- event.timerIndicatorDuration);
+ setRelativeFocusedTask(true, false /* stackTasksOnly */, true /* animated */, false, 0);
}
public final void onBusEvent(FocusPreviousTaskViewEvent event) {
@@ -1869,8 +1863,7 @@
EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
break;
case DOWN:
- EventBus.getDefault().send(
- new FocusNextTaskViewEvent(0 /* timerIndicatorDuration */));
+ EventBus.getDefault().send(new FocusNextTaskViewEvent());
break;
}
}
@@ -1881,7 +1874,7 @@
mUIDozeTrigger.poke();
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
- if (debugFlags.isFastToggleRecentsEnabled() && mFocusedTask != null) {
+ if (mFocusedTask != null) {
TaskView tv = getChildViewForTask(mFocusedTask);
if (tv != null) {
tv.getHeaderView().cancelFocusTimerIndicator();
@@ -1979,13 +1972,6 @@
event.getAnimationTrigger().increment();
}
- public final void onBusEvent(IterateRecentsEvent event) {
- if (!mEnterAnimationComplete) {
- // Cancel the previous task's window transition before animating the focused state
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
- }
- }
-
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
mEnterAnimationComplete = true;
tryStartEnterAnimation();
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 c4e4e2e..1420a01 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -460,17 +460,6 @@
mDismissButton.setClickable(false);
((RippleDrawable) mDismissButton.getBackground()).setForceSoftware(true);
- if (Recents.getDebugFlags().isFastToggleRecentsEnabled()) {
- if (mFocusTimerIndicator == null) {
- mFocusTimerIndicator = (ProgressBar) Utilities.findViewStubById(this,
- R.id.focus_timer_indicator_stub).inflate();
- }
- mFocusTimerIndicator.getProgressDrawable()
- .setColorFilter(
- getSecondaryColor(t.colorPrimary, t.useLightOnPrimaryColor),
- PorterDuff.Mode.SRC_IN);
- }
-
// In accessibility, a single click on the focused app info button will show it
if (touchExplorationEnabled) {
mIconView.setContentDescription(t.appInfoDescription);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index 578a18a..0997983 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -32,7 +32,7 @@
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
import com.android.systemui.recents.events.component.ShowUserToastEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.recents.misc.TaskStackChangeListener;
import com.android.systemui.stackdivider.events.StartedDragingEvent;
import com.android.systemui.stackdivider.events.StoppedDragingEvent;
@@ -76,7 +76,7 @@
mContext = context;
EventBus.getDefault().register(this);
SystemServicesProxy.getInstance(context).registerTaskStackListener(
- new TaskStackListener() {
+ new TaskStackChangeListener() {
@Override
public void onActivityForcedResizable(String packageName, int taskId,
int reason) {
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 2ad881f..fed2ebe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -36,14 +36,17 @@
import android.view.WindowManager;
import android.widget.LinearLayout;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
+import com.android.systemui.Prefs;
import com.android.systemui.R;
-import com.android.systemui.SwipeHelper;
+import com.android.systemui.classifier.FalsingLog;
+import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.fragments.FragmentHostManager;
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.recents.misc.TaskStackChangeListener;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.StatusBarState;
@@ -52,10 +55,6 @@
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.classifier.FalsingLog;
-import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.Prefs;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -306,10 +305,10 @@
}
/**
- * An implementation of TaskStackListener, that listens for changes in the system task
+ * An implementation of TaskStackChangeListener, that listens for changes in the system task
* stack and notifies the navigation bar.
*/
- private class TaskStackListenerImpl extends TaskStackListener {
+ private class TaskStackListenerImpl extends TaskStackChangeListener {
@Override
public void onTaskStackChanged() {
SystemServicesProxy ssp = Recents.getSystemServices();
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 b0ce577..b876286 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -66,7 +66,7 @@
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.recents.misc.TaskStackChangeListener;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -768,7 +768,7 @@
mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
}
- private final TaskStackListener mTaskListener = new TaskStackListener() {
+ private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
@Override
public void onTaskStackChanged() {
// Listen for changes to stacks and then check which instant apps are foreground.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
index 5fb0a3e..b86fc21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
@@ -44,7 +44,7 @@
import com.android.systemui.keyguard.WorkLockActivity;
import com.android.systemui.keyguard.WorkLockActivityController;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.android.systemui.recents.misc.TaskStackChangeListener;
import org.junit.Before;
import org.junit.Test;
@@ -68,7 +68,7 @@
private @Mock IActivityManager mIActivityManager;
private WorkLockActivityController mController;
- private TaskStackListener mTaskStackListener;
+ private TaskStackChangeListener mTaskStackListener;
@Before
public void setUp() throws Exception {
@@ -78,8 +78,8 @@
doReturn("com.example.test").when(mContext).getPackageName();
// Construct controller. Save the TaskStackListener for injecting events.
- final ArgumentCaptor<TaskStackListener> listenerCaptor =
- ArgumentCaptor.forClass(TaskStackListener.class);
+ final ArgumentCaptor<TaskStackChangeListener> listenerCaptor =
+ ArgumentCaptor.forClass(TaskStackChangeListener.class);
mController =
new WorkLockActivityController(mContext, mSystemServicesProxy, mIActivityManager);
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 599485f..1659133 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -34,6 +34,8 @@
time_zone_distro \
time_zone_distro_installer \
android.hidl.base-V1.0-java \
+ android.hardware.health-V1.0-java \
+ android.hardware.health-V2.0-java \
android.hardware.weaver-V1.0-java \
android.hardware.biometrics.fingerprint-V2.1-java \
android.hardware.oemlock-V1.0-java \
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 8839cfc..6ed0555 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -45,13 +46,14 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.ConfigurationContainer;
+import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Exactly one of these classes per Display in the system. Capable of holding zero or more
* attached {@link ActivityStack}s.
*/
-class ActivityDisplay extends ConfigurationContainer {
+class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
@@ -65,7 +67,7 @@
/** All of the stacks on this display. Order matters, topmost stack is in front of all other
* stacks, bottommost behind. Accessed directly by ActivityManager package classes */
- final ArrayList<ActivityStack> mStacks = new ArrayList<>();
+ private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
/** Array of all UIDs that are present on the display. */
private IntArray mDisplayAccessUIDs = new IntArray();
@@ -77,6 +79,13 @@
private boolean mSleeping;
+ // Cached reference to some special stacks we tend to get a lot so we don't need to loop
+ // through the list to find them.
+ private ActivityStack mHomeStack = null;
+ private ActivityStack mRecentsStack = null;
+ private ActivityStack mPinnedStack = null;
+ private ActivityStack mSplitScreenPrimaryStack = null;
+
ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
mSupervisor = supervisor;
mDisplayId = displayId;
@@ -95,6 +104,7 @@
}
if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
+ " to displayId=" + mDisplayId + " position=" + position);
+ addStackReferenceIfNeeded(stack);
positionChildAt(stack, position);
mSupervisor.mService.updateSleepIfNeededLocked();
}
@@ -103,6 +113,7 @@
if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
+ removeStackReferenceIfNeeded(stack);
mSupervisor.mService.updateSleepIfNeededLocked();
}
@@ -147,6 +158,16 @@
* @see ConfigurationContainer#isCompatible(int, int)
*/
<T extends ActivityStack> T getStack(int windowingMode, int activityType) {
+ if (activityType == ACTIVITY_TYPE_HOME) {
+ return (T) mHomeStack;
+ } else if (activityType == ACTIVITY_TYPE_RECENTS) {
+ return (T) mRecentsStack;
+ }
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ return (T) mPinnedStack;
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ return (T) mSplitScreenPrimaryStack;
+ }
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
// TODO: Should undefined windowing and activity type be compatible with standard type?
@@ -217,7 +238,7 @@
}
}
- final boolean inSplitScreenMode = hasSplitScreenStack();
+ final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
if (!inSplitScreenMode
&& windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
// Switch to fullscreen windowing mode if we are not in split-screen mode and we are
@@ -275,7 +296,7 @@
if (stack.getWindowingMode() != windowingMode) {
continue;
}
- mSupervisor.removeStackLocked(stack.mStackId);
+ mSupervisor.removeStack(stack);
}
}
}
@@ -290,12 +311,63 @@
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
if (stack.getActivityType() == activityType) {
- mSupervisor.removeStackLocked(stack.mStackId);
+ mSupervisor.removeStack(stack);
}
}
}
}
+ void onStackWindowingModeChanged(ActivityStack stack) {
+ removeStackReferenceIfNeeded(stack);
+ addStackReferenceIfNeeded(stack);
+ }
+
+ private void addStackReferenceIfNeeded(ActivityStack stack) {
+ final int activityType = stack.getActivityType();
+ final int windowingMode = stack.getWindowingMode();
+
+ if (activityType == ACTIVITY_TYPE_HOME) {
+ if (mHomeStack != null && mHomeStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+ + mHomeStack + " already exist on display=" + this + " stack=" + stack);
+ }
+ mHomeStack = stack;
+ } else if (activityType == ACTIVITY_TYPE_RECENTS) {
+ if (mRecentsStack != null && mRecentsStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
+ + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
+ }
+ mRecentsStack = stack;
+ }
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ if (mPinnedStack != null && mPinnedStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
+ + mPinnedStack + " already exist on display=" + this
+ + " stack=" + stack);
+ }
+ mPinnedStack = stack;
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded:"
+ + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
+ + " already exist on display=" + this + " stack=" + stack);
+ }
+ mSplitScreenPrimaryStack = stack;
+ }
+ }
+
+ private void removeStackReferenceIfNeeded(ActivityStack stack) {
+ if (stack == mHomeStack) {
+ mHomeStack = null;
+ } else if (stack == mRecentsStack) {
+ mRecentsStack = null;
+ } else if (stack == mPinnedStack) {
+ mPinnedStack = null;
+ } else if (stack == mSplitScreenPrimaryStack) {
+ mSplitScreenPrimaryStack = null;
+ }
+ }
+
/** Returns the top visible stack activity type that isn't in the exclude windowing mode. */
int getTopVisibleStackActivityType(int excludeWindowingMode) {
for (int i = mStacks.size() - 1; i >= 0; --i) {
@@ -310,20 +382,42 @@
return ACTIVITY_TYPE_UNDEFINED;
}
- ActivityStack getSplitScreenStack() {
- return getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ /**
+ * Get the topmost stack on the display. It may be different from focused stack, because
+ * focus may be on another display.
+ */
+ ActivityStack getTopStack() {
+ return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
}
- boolean hasSplitScreenStack() {
- return getSplitScreenStack() != null;
+ boolean isTopStack(ActivityStack stack) {
+ return stack == getTopStack();
+ }
+
+ int getIndexOf(ActivityStack stack) {
+ return mStacks.indexOf(stack);
+ }
+
+ void onLockTaskPackagesUpdated() {
+ for (int i = mStacks.size() - 1; i >= 0; --i) {
+ mStacks.get(i).onLockTaskPackagesUpdated();
+ }
+ }
+
+ ActivityStack getSplitScreenPrimaryStack() {
+ return mSplitScreenPrimaryStack;
+ }
+
+ boolean hasSplitScreenPrimaryStack() {
+ return mSplitScreenPrimaryStack != null;
}
PinnedActivityStack getPinnedStack() {
- return getStack(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+ return (PinnedActivityStack) mPinnedStack;
}
boolean hasPinnedStack() {
- return getPinnedStack() != null;
+ return mPinnedStack != null;
}
@Override
@@ -337,7 +431,7 @@
}
@Override
- protected ConfigurationContainer getChildAt(int index) {
+ protected ActivityStack getChildAt(int index) {
return mStacks.get(index);
}
@@ -385,6 +479,10 @@
mSleeping = asleep;
}
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "displayId=" + mDisplayId + " mStacks=" + mStacks);
+ }
+
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
super.writeToProto(proto, CONFIGURATION_CONTAINER);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5e10ada..51dfa8b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -176,7 +176,6 @@
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
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.proto.ActivityManagerServiceProto.ACTIVITIES;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_NONE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
@@ -209,7 +208,6 @@
import android.app.Dialog;
import android.app.IActivityController;
import android.app.IActivityManager;
-import android.app.IAppTask;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
import android.app.INotificationManager;
@@ -2536,7 +2534,6 @@
synchronized (this) {
mWindowManager = wm;
mStackSupervisor.setWindowManager(wm);
- mActivityStarter.setWindowManager(wm);
mLockTaskController.setWindowManager(wm);
}
}
@@ -2778,7 +2775,7 @@
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mTaskChangeNotificationController =
new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
- mActivityStarter = new ActivityStarter(this, mStackSupervisor);
+ mActivityStarter = new ActivityStarter(this);
mRecentTasks = new RecentTasks(this, mStackSupervisor);
mStackSupervisor.setRecentTasks(mRecentTasks);
mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);
@@ -10157,11 +10154,14 @@
final long ident = Binder.clearCallingIdentity();
try {
final ActivityStack stack = mStackSupervisor.getStack(stackId);
- if (stack != null && !stack.isActivityTypeStandardOrUndefined()) {
+ if (stack == null) {
+ return;
+ }
+ if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException(
"Removing non-standard stack is not allowed.");
}
- mStackSupervisor.removeStackLocked(stackId);
+ mStackSupervisor.removeStack(stack);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -10527,7 +10527,7 @@
try {
synchronized (this) {
final ActivityStack stack =
- mStackSupervisor.getDefaultDisplay().getSplitScreenStack();
+ mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
if (toTop) {
mStackSupervisor.resizeStackLocked(stack, null /* destBounds */,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 790c9a3..40e568c 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1558,7 +1558,7 @@
// On devices that support leanback only (Android TV), Recents activity can only be
// visible if the home stack is the focused stack or we are in split-screen mode.
final ActivityDisplay display = getDisplay();
- boolean hasSplitScreenStack = display != null && display.hasSplitScreenStack();
+ boolean hasSplitScreenStack = display != null && display.hasSplitScreenPrimaryStack();
isVisible = hasSplitScreenStack || mStackSupervisor.isFocusedStack(getStack());
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3d3bae3..f0811dd 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -102,9 +102,6 @@
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;
@@ -473,6 +470,16 @@
return mWindowContainerController;
}
+ @Override
+ public void onConfigurationChanged(Configuration newParentConfig) {
+ final int prevWindowingMode = getWindowingMode();
+ super.onConfigurationChanged(newParentConfig);
+ final ActivityDisplay display = getDisplay();
+ if (display != null && prevWindowingMode != getWindowingMode()) {
+ display.onStackWindowingModeChanged(this);
+ }
+ }
+
/** Adds the stack to specified display and calls WindowManager to do the same. */
void reparent(ActivityDisplay activityDisplay, boolean onTop) {
removeFromDisplay();
@@ -1529,6 +1536,10 @@
&& !mForceHidden;
}
+ boolean isTopStackOnDisplay() {
+ return getDisplay().isTopStack(this);
+ }
+
/**
* Returns true if the stack should be visible.
*
@@ -1539,22 +1550,15 @@
return false;
}
- if (mStackSupervisor.isFrontStackOnDisplay(this) || mStackSupervisor.isFocusedStack(this)) {
+ final ActivityDisplay display = getDisplay();
+ if (isTopStackOnDisplay() || mStackSupervisor.isFocusedStack(this)) {
return true;
}
- final ActivityDisplay display = getDisplay();
- final ArrayList<ActivityStack> displayStacks = display.mStacks;
- final int stackIndex = displayStacks.indexOf(this);
-
- if (stackIndex == displayStacks.size() - 1) {
- Slog.wtf(TAG,
- "Stack=" + this + " isn't front stack but is at the top of the stack list");
- return false;
- }
+ final int stackIndex = display.getIndexOf(this);
// Check position and visibility of this stack relative to the front stack on its display.
- final ActivityStack topStack = getTopStackOnDisplay();
+ final ActivityStack topStack = getDisplay().getTopStack();
final int windowingMode = getWindowingMode();
final int activityType = getActivityType();
@@ -1571,22 +1575,21 @@
// A case would be if recents stack exists but has no tasks and is below the docked stack
// and home stack is below recents
if (activityType == ACTIVITY_TYPE_HOME) {
- final ActivityStack splitScreenStack = display.getStack(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
- int dockedStackIndex = displayStacks.indexOf(splitScreenStack);
+ final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
+ int dockedStackIndex = display.getIndexOf(splitScreenStack);
if (dockedStackIndex > stackIndex && stackIndex != dockedStackIndex - 1) {
return false;
}
}
// Find the first stack behind front stack that actually got something visible.
- int stackBehindTopIndex = displayStacks.indexOf(topStack) - 1;
+ int stackBehindTopIndex = display.getIndexOf(topStack) - 1;
while (stackBehindTopIndex >= 0 &&
- displayStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
+ display.getChildAt(stackBehindTopIndex).topRunningActivityLocked() == null) {
stackBehindTopIndex--;
}
final ActivityStack stackBehindTop = (stackBehindTopIndex >= 0)
- ? displayStacks.get(stackBehindTopIndex) : null;
+ ? display.getChildAt(stackBehindTopIndex) : null;
int stackBehindTopWindowingMode = WINDOWING_MODE_UNDEFINED;
int stackBehindTopActivityType = ACTIVITY_TYPE_UNDEFINED;
if (stackBehindTop != null) {
@@ -1635,8 +1638,9 @@
return false;
}
- for (int i = stackIndex + 1; i < displayStacks.size(); i++) {
- final ActivityStack stack = displayStacks.get(i);
+ final int stackCount = display.getChildCount();
+ for (int i = stackIndex + 1; i < stackCount; i++) {
+ final ActivityStack stack = display.getChildAt(i);
if (!stack.mFullscreen && !stack.hasFullscreenTask()) {
continue;
@@ -2572,8 +2576,8 @@
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
- } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
- mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
+ } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null
+ && lastStack.isTopStackOnDisplay()) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwitch */);
}
@@ -4428,7 +4432,7 @@
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
- final ActivityStack topStack = getTopStackOnDisplay();
+ final ActivityStack topStack = getDisplay().getTopStack();
final ActivityRecord topActivity = topStack != null ? topStack.topActivity() : null;
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
@@ -4518,7 +4522,7 @@
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (mStackSupervisor.isFrontStackOnDisplay(this) && mService.mController != null) {
+ if (isTopStackOnDisplay() && mService.mController != null) {
ActivityRecord next = topRunningActivityLocked(null, taskId);
if (next == null) {
next = topRunningActivityLocked(null, 0);
@@ -4566,7 +4570,7 @@
}
if (inPinnedWindowingMode()) {
- mStackSupervisor.removeStackLocked(mStackId);
+ mStackSupervisor.removeStack(this);
return true;
}
@@ -4598,15 +4602,6 @@
return true;
}
- /**
- * Get the topmost stack on the current display. It may be different from focused stack, because
- * focus may be on another display.
- */
- private ActivityStack getTopStackOnDisplay() {
- final ArrayList<ActivityStack> stacks = getDisplay().mStacks;
- return stacks.isEmpty() ? null : stacks.get(stacks.size() - 1);
- }
-
static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) {
final Uri data = r.intent.getData();
final String strData = data != null ? data.toSafeString() : null;
@@ -5249,7 +5244,7 @@
+ mTaskHistory.size() + " tasks}";
}
- void onLockTaskPackagesUpdatedLocked() {
+ void onLockTaskPackagesUpdated() {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
mTaskHistory.get(taskNdx).setLockTaskAuth();
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 333d759..5c91e3c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -631,15 +631,6 @@
return stack != null && stack == mFocusedStack;
}
- /** The top most stack on its display. */
- boolean isFrontStackOnDisplay(ActivityStack stack) {
- return isFrontOfStackList(stack, stack.getDisplay().mStacks);
- }
-
- private boolean isFrontOfStackList(ActivityStack stack, List<ActivityStack> stackList) {
- return stack == stackList.get((stackList.size() - 1));
- }
-
/** NOTE: Should only be called from {@link ActivityStack#moveToFront} */
void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
if (!focusCandidate.isFocusable()) {
@@ -735,9 +726,9 @@
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
final TaskRecord task = stack.taskForIdLocked(id);
if (task != null) {
return task;
@@ -780,9 +771,10 @@
ActivityRecord isInAnyStackLocked(IBinder token) {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityRecord r = stack.isInStackLocked(token);
if (r != null) {
return r;
}
@@ -820,18 +812,21 @@
void lockAllProfileTasks(@UserIdInt int userId) {
mWindowManager.deferSurfaceLayout();
try {
- final List<ActivityStack> stacks = getStacks();
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; stackNdx--) {
- final List<TaskRecord> tasks = stacks.get(stackNdx).getAllTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
- final TaskRecord task = tasks.get(taskNdx);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final List<TaskRecord> tasks = stack.getAllTasks();
+ for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
+ final TaskRecord task = tasks.get(taskNdx);
- // Check the task for a top activity belonging to userId, or returning a result
- // to an activity belonging to userId. Example case: a document picker for
- // personal files, opened by a work app, should still get locked.
- if (taskTopActivityIsUser(task, userId)) {
- mService.mTaskChangeNotificationController.notifyTaskProfileLocked(
- task.taskId, userId);
+ // Check the task for a top activity belonging to userId, or returning a
+ // result to an activity belonging to userId. Example case: a document
+ // picker for personal files, opened by a work app, should still get locked.
+ if (taskTopActivityIsUser(task, userId)) {
+ mService.mTaskChangeNotificationController.notifyTaskProfileLocked(
+ task.taskId, userId);
+ }
}
}
}
@@ -897,9 +892,9 @@
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
@@ -932,9 +927,9 @@
boolean allResumedActivitiesIdle() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!isFocusedStack(stack) || stack.numActivities() == 0) {
continue;
}
@@ -953,9 +948,9 @@
boolean allResumedActivitiesComplete() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (isFocusedStack(stack)) {
final ActivityRecord r = stack.mResumedActivity;
if (r != null && r.state != RESUMED) {
@@ -972,12 +967,12 @@
return true;
}
- boolean allResumedActivitiesVisible() {
+ private boolean allResumedActivitiesVisible() {
boolean foundResumed = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
final ActivityRecord r = stack.mResumedActivity;
if (r != null) {
if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) {
@@ -1001,9 +996,9 @@
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
boolean someActivityPaused = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + stack.mResumedActivity);
@@ -1018,9 +1013,9 @@
boolean allPausedActivitiesComplete() {
boolean pausing = true;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
final ActivityRecord r = stack.mPausingActivity;
if (r != null && r.state != PAUSED && r.state != STOPPED && r.state != STOPPING) {
if (DEBUG_STATES) {
@@ -1038,9 +1033,10 @@
void cancelInitializingActivities() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- stacks.get(stackNdx).cancelInitializingActivities();
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.cancelInitializingActivities();
}
}
}
@@ -1138,13 +1134,10 @@
for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
final int displayId = mTmpOrderedDisplayIds.get(i);
- final List<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks;
- if (stacks == null) {
- continue;
- }
- for (int j = stacks.size() - 1; j >= 0; --j) {
- final ActivityStack stack = stacks.get(j);
- if (stack != focusedStack && isFrontStackOnDisplay(stack) && stack.isFocusable()) {
+ final ActivityDisplay display = mActivityDisplays.get(displayId);
+ for (int j = display.getChildCount() - 1; j >= 0; --j) {
+ final ActivityStack stack = display.getChildAt(j);
+ if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) {
r = stack.topRunningActivityLocked();
if (r != null) {
return r;
@@ -1160,9 +1153,9 @@
ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists = new ArrayList<>();
final int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<>();
runningTaskLists.add(stackTaskList);
stack.getTasksLocked(stackTaskList, callingUid, allowed);
@@ -1942,9 +1935,10 @@
boolean handleAppDiedLocked(ProcessRecord app) {
boolean hasVisibleActivities = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ hasVisibleActivities |= stack.handleAppDiedLocked(app);
}
}
return hasVisibleActivities;
@@ -1952,9 +1946,10 @@
void closeSystemDialogsLocked() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- stacks.get(stackNdx).closeSystemDialogsLocked();
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.closeSystemDialogsLocked();
}
}
}
@@ -1980,9 +1975,9 @@
boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (stack.finishDisabledPackageActivitiesLocked(
packageName, filterByClasses, doit, evenPersistent, userId)) {
didSomething = true;
@@ -2002,9 +1997,9 @@
// hosted by the process that is actually still the foreground.
ProcessRecord fgApp = null;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (isFocusedStack(stack)) {
if (stack.mResumedActivity != null) {
fgApp = stack.mResumedActivity.app;
@@ -2054,9 +2049,10 @@
void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- stacks.get(stackNdx).updateActivityApplicationInfoLocked(aInfo);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.updateActivityApplicationInfoLocked(aInfo);
}
}
}
@@ -2065,10 +2061,10 @@
TaskRecord finishedTask = null;
ActivityStack focusedStack = getFocusedStack();
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int numStacks = stacks.size();
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ final int numStacks = display.getChildCount();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityStack stack = display.getChildAt(stackNdx);
TaskRecord t = stack.finishTopRunningActivityLocked(app, reason);
if (stack == focusedStack || finishedTask == null) {
finishedTask = t;
@@ -2080,10 +2076,10 @@
void finishVoiceTask(IVoiceInteractionSession session) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int numStacks = stacks.size();
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ final int numStacks = display.getChildCount();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.finishVoiceTask(session);
}
}
@@ -2139,7 +2135,7 @@
"findTaskToMoveToFront: moved to front of stack=" + currentStack);
handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY,
- currentStack.mStackId, forceNonResizeable);
+ currentStack, forceNonResizeable);
}
boolean canUseActivityOptionsLaunchBounds(ActivityOptions options) {
@@ -2334,8 +2330,8 @@
}
final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
if (display != null) {
- for (int i = display.mStacks.size() - 1; i >= 0; --i) {
- stack = (T) display.mStacks.get(i);
+ for (int i = display.getChildCount() - 1; i >= 0; --i) {
+ stack = (T) display.getChildAt(i);
if (stack.isCompatible(windowingMode, activityType)) {
return stack;
}
@@ -2403,8 +2399,8 @@
}
// Return the topmost valid stack on the display.
- for (int i = activityDisplay.mStacks.size() - 1; i >= 0; --i) {
- final ActivityStack stack = activityDisplay.mStacks.get(i);
+ for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = activityDisplay.getChildAt(i);
if (isValidLaunchStack(stack, displayId, r)) {
return stack;
}
@@ -2442,18 +2438,6 @@
return false;
}
- ArrayList<ActivityStack> getStacks() {
- ArrayList<ActivityStack> allStacks = new ArrayList<>();
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
- }
- return allStacks;
- }
-
- ArrayList<ActivityStack> getStacksOnDefaultDisplay() {
- return mActivityDisplays.valueAt(DEFAULT_DISPLAY).mStacks;
- }
-
/**
* Get next focusable stack in the system. This will search across displays and stacks
* in last-focused order for a focusable and visible stack, different from the target stack.
@@ -2468,10 +2452,9 @@
for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
final int displayId = mTmpOrderedDisplayIds.get(i);
// If a display is registered in WM, it must also be available in AM.
- @SuppressWarnings("ConstantConditions")
- final List<ActivityStack> stacks = getActivityDisplayOrCreateLocked(displayId).mStacks;
- for (int j = stacks.size() - 1; j >= 0; --j) {
- final ActivityStack stack = stacks.get(j);
+ final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
+ for (int j = display.getChildCount() - 1; j >= 0; --j) {
+ final ActivityStack stack = display.getChildAt(j);
if (stack != currentFocus && stack.isFocusable()
&& stack.shouldBeVisible(null)) {
return stack;
@@ -2539,7 +2522,7 @@
return;
}
- final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenStack();
+ final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenPrimaryStack();
if (!allowResizeInDockedMode
&& !stack.getWindowConfiguration().tasksAreFloating() && splitScreenActive) {
// If the docked stack exists, don't resize non-floating stacks independently of the
@@ -2614,9 +2597,8 @@
// We are moving all tasks from the docked stack to the fullscreen stack,
// which is dismissing the docked stack, so resize all other stacks to
// fullscreen here already so we don't end up with resize trashing.
- final ArrayList<ActivityStack> displayStacks = toDisplay.mStacks;
- for (int i = displayStacks.size() - 1; i >= 0; --i) {
- final ActivityStack otherStack = displayStacks.get(i);
+ for (int i = toDisplay.getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack otherStack = toDisplay.getChildAt(i);
if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
continue;
}
@@ -2711,8 +2693,7 @@
return;
}
- final ActivityStack stack = getDefaultDisplay().getStack(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ final ActivityStack stack = getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
Slog.w(TAG, "resizeDockedStackLocked: docked stack not found");
return;
@@ -2741,10 +2722,10 @@
// static stacks need to be adjusted so they don't overlap with the docked stack.
// We get the bounds to use from window manager which has been adjusted for any
// screen controls and is also the same for all stacks.
- final ArrayList<ActivityStack> stacks = getStacksOnDefaultDisplay();
+ final ActivityDisplay display = getDefaultDisplay();
final Rect otherTaskRect = new Rect();
- for (int i = stacks.size() - 1; i >= 0; --i) {
- final ActivityStack current = stacks.get(i);
+ for (int i = display.getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack current = display.getChildAt(i);
if (current.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
continue;
}
@@ -2776,8 +2757,7 @@
void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
// TODO(multi-display): Pinned stack display should be passed in.
- final PinnedActivityStack stack = getDefaultDisplay().getStack(
- WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+ final PinnedActivityStack stack = getDefaultDisplay().getPinnedStack();
if (stack == null) {
Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
return;
@@ -2815,12 +2795,7 @@
}
}
- private void removeStackInSurfaceTransaction(int stackId) {
- final ActivityStack stack = getStack(stackId);
- if (stack == null) {
- return;
- }
-
+ private void removeStackInSurfaceTransaction(ActivityStack stack) {
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
if (stack.getWindowingMode() == WINDOWING_MODE_PINNED) {
/**
@@ -2850,12 +2825,12 @@
}
/**
- * Removes the stack associated with the given {@param stackId}. If the {@param stackId} is the
+ * Removes the stack associated with the given {@param stack}. If the {@param stack} is the
* pinned stack, then its tasks are not explicitly removed when the stack is destroyed, but
* instead moved back onto the fullscreen stack.
*/
- void removeStackLocked(int stackId) {
- mWindowManager.inSurfaceTransaction(() -> removeStackInSurfaceTransaction(stackId));
+ void removeStack(ActivityStack stack) {
+ mWindowManager.inSurfaceTransaction(() -> removeStackInSurfaceTransaction(stack));
}
/**
@@ -3273,9 +3248,9 @@
ActivityRecord affinityMatch = null;
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!r.hasCompatibleActivityType(stack)) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) "
+ stack);
@@ -3308,12 +3283,13 @@
}
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
- boolean compareIntentFilters) {
+ boolean compareIntentFilters) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord ar = stacks.get(stackNdx)
- .findActivityLocked(intent, info, compareIntentFilters);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityRecord ar = stack.findActivityLocked(
+ intent, info, compareIntentFilters);
if (ar != null) {
return ar;
}
@@ -3407,9 +3383,8 @@
}
// Set the sleeping state of the stacks on the display.
- final ArrayList<ActivityStack> stacks = display.mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (displayShouldSleep) {
stack.goToSleepIfPossible(false /* shuttingDown */);
} else {
@@ -3471,12 +3446,13 @@
private boolean putStacksToSleepLocked(boolean allowDelay, boolean shuttingDown) {
boolean allSleep = true;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (allowDelay) {
- allSleep &= stacks.get(stackNdx).goToSleepIfPossible(shuttingDown);
+ allSleep &= stack.goToSleepIfPossible(shuttingDown);
} else {
- stacks.get(stackNdx).goToSleep();
+ stack.goToSleep();
}
}
}
@@ -3501,11 +3477,10 @@
void handleAppCrashLocked(ProcessRecord app) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- int stackNdx = stacks.size() - 1;
- while (stackNdx >= 0) {
- stacks.get(stackNdx).handleAppCrashLocked(app);
- stackNdx--;
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.handleAppCrashLocked(app);
}
}
}
@@ -3538,10 +3513,9 @@
try {
// First the front stacks. In case any are not fullscreen and are in front of home.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int topStackNdx = stacks.size() - 1;
- for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows);
}
}
@@ -3552,10 +3526,9 @@
void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int topStackNdx = stacks.size() - 1;
- for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.addStartingWindowsForVisibleActivities(taskSwitch);
}
}
@@ -3571,20 +3544,20 @@
}
mTaskLayersChanged = false;
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
int baseLayer = 0;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- baseLayer += stacks.get(stackNdx).rankTaskLayers(baseLayer);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ baseLayer += stack.rankTaskLayers(baseLayer);
}
}
}
void clearOtherAppTimeTrackers(AppTimeTracker except) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int topStackNdx = stacks.size() - 1;
- for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.clearOtherAppTimeTrackers(except);
}
}
@@ -3592,10 +3565,9 @@
void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int numStacks = stacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.scheduleDestroyActivities(app, reason);
}
}
@@ -3647,10 +3619,11 @@
// let's iterate through the tasks and release the oldest one.
final int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ final int stackCount = display.getChildCount();
// Step through all stacks starting from behind, to hit the oldest things first.
- for (int stackNdx = 0; stackNdx < stacks.size(); stackNdx++) {
- final ActivityStack stack = stacks.get(stackNdx);
+ for (int stackNdx = 0; stackNdx < stackCount; stackNdx++) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
// Try to release activities in this stack; if we manage to, we are done.
if (stack.releaseSomeActivitiesLocked(app, tasks, reason) > 0) {
return;
@@ -3662,7 +3635,7 @@
boolean switchUserLocked(int userId, UserState uss) {
final int focusStackId = mFocusedStack.getStackId();
// We dismiss the docked stack whenever we switch users.
- final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenStack();
+ final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null) {
moveTasksToFullscreenStackLocked(dockedStack, mFocusedStack == dockedStack);
}
@@ -3677,9 +3650,9 @@
mStartingUsers.add(uss);
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.switchUserLocked(userId);
TaskRecord task = stack.topTask();
if (task != null) {
@@ -3777,9 +3750,9 @@
void validateTopActivitiesLocked() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
final ActivityRecord r = stack.topRunningActivityLocked();
final ActivityState state = r == null ? DESTROYED : r.state;
if (isFocusedStack(stack)) {
@@ -3814,7 +3787,7 @@
pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
final ActivityDisplay display = mActivityDisplays.valueAt(i);
- pw.println(prefix + "displayId=" + display.mDisplayId + " mStacks=" + display.mStacks);
+ display.dump(pw, prefix);
}
if (!mWaitingForActivityVisible.isEmpty()) {
pw.print(prefix); pw.println("mWaitingForActivityVisible=");
@@ -3871,9 +3844,9 @@
ArrayList<ActivityRecord> activities = new ArrayList<>();
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
activities.addAll(stack.getDumpActivitiesLocked(name));
}
@@ -3906,9 +3879,9 @@
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
pw.print("Display #"); pw.print(activityDisplay.mDisplayId);
pw.println(" (activities from top to bottom):");
- ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
pw.println();
pw.println(" Stack #" + stack.mStackId
+ ": type=" + activityTypeToString(stack.getActivityType())
@@ -4156,30 +4129,29 @@
}
synchronized (mService) {
- ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
- if (activityDisplay != null) {
- final boolean destroyContentOnRemoval
- = activityDisplay.shouldDestroyContentOnRemove();
- final ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
- while (!stacks.isEmpty()) {
- final ActivityStack stack = stacks.get(0);
- if (destroyContentOnRemoval) {
- moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY,
- false /* onTop */);
- stack.finishAllActivitiesLocked(true /* immediately */);
- } else {
- // Moving all tasks to fullscreen stack, because it's guaranteed to be
- // a valid launch stack for all activities. This way the task history from
- // external display will be preserved on primary after move.
- moveTasksToFullscreenStackLocked(stack, true /* onTop */);
- }
- }
-
- releaseSleepTokens(activityDisplay);
-
- mActivityDisplays.remove(displayId);
- mWindowManager.onDisplayRemoved(displayId);
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay == null) {
+ return;
}
+ final boolean destroyContentOnRemoval
+ = activityDisplay.shouldDestroyContentOnRemove();
+ while (activityDisplay.getChildCount() > 0) {
+ final ActivityStack stack = activityDisplay.getChildAt(0);
+ if (destroyContentOnRemoval) {
+ moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, false /* onTop */);
+ stack.finishAllActivitiesLocked(true /* immediately */);
+ } else {
+ // Moving all tasks to fullscreen stack, because it's guaranteed to be
+ // a valid launch stack for all activities. This way the task history from
+ // external display will be preserved on primary after move.
+ moveTasksToFullscreenStackLocked(stack, true /* onTop */);
+ }
+ }
+
+ releaseSleepTokens(activityDisplay);
+
+ mActivityDisplays.remove(displayId);
+ mWindowManager.onDisplayRemoved(displayId);
}
}
@@ -4251,7 +4223,7 @@
info.userId = stack.mCurrentUser;
info.visible = stack.shouldBeVisible(null);
// A stack might be not attached to a display.
- info.position = display != null ? display.mStacks.indexOf(stack) : 0;
+ info.position = display != null ? display.getIndexOf(stack) : 0;
info.configuration.setTo(stack.getConfiguration());
ArrayList<TaskRecord> tasks = stack.getAllTasks();
@@ -4297,25 +4269,25 @@
ArrayList<StackInfo> getAllStackInfosLocked() {
ArrayList<StackInfo> list = new ArrayList<>();
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
- list.add(getStackInfo(stacks.get(ndx)));
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ list.add(getStackInfo(stack));
}
}
return list;
}
void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
- int preferredDisplayId, int actualStackId) {
+ int preferredDisplayId, ActivityStack actualStack) {
handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId,
- actualStackId, false /* forceNonResizable */);
+ actualStack, false /* forceNonResizable */);
}
void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
- int preferredDisplayId, int actualStackId, boolean forceNonResizable) {
+ int preferredDisplayId, ActivityStack actualStack, boolean forceNonResizable) {
final boolean isSecondaryDisplayPreferred =
(preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY);
- final ActivityStack actualStack = getStack(actualStackId);
final boolean inSplitScreenMode = actualStack != null
&& actualStack.inSplitScreenWindowingMode();
if (((!inSplitScreenMode && preferredWindowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
@@ -4362,10 +4334,9 @@
// Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
// we need to move it to top of fullscreen stack, otherwise it will be covered.
- final ActivityStack dockedStack = task.getStack().getDisplay().getSplitScreenStack();
+ final ActivityStack dockedStack = task.getStack().getDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null) {
- moveTasksToFullscreenStackLocked(dockedStack,
- actualStackId == dockedStack.getStackId());
+ moveTasksToFullscreenStackLocked(dockedStack, actualStack == dockedStack);
}
} else if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
&& !topActivity.noDisplay) {
@@ -4577,14 +4548,13 @@
if (display == null) {
return null;
}
- final ArrayList<ActivityStack> stacks = display.mStacks;
- for (int i = stacks.size() - 1; i >= 0; i--) {
- if (stacks.get(i) == stack && i > 0) {
- return stacks.get(i - 1);
+ for (int i = display.getChildCount() - 1; i >= 0; i--) {
+ if (display.getChildAt(i) == stack && i > 0) {
+ return display.getChildAt(i - 1);
}
}
throw new IllegalStateException("Failed to find a stack behind stack=" + stack
- + " in=" + stacks);
+ + " in=" + display);
}
/**
@@ -4697,8 +4667,8 @@
for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
final ActivityDisplay display = mActivityDisplays.valueAt(i);
// Traverse all stacks on a display.
- for (int j = display.mStacks.size() - 1; j >= 0; j--) {
- final ActivityStack stack = display.mStacks.get(j);
+ for (int j = display.getChildCount() - 1; j >= 0; --j) {
+ final ActivityStack stack = display.getChildAt(j);
// Get top activity from a visible stack and add it to the list.
if (stack.shouldBeVisible(null /* starting */)) {
final ActivityRecord top = stack.topActivity();
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index cceb576..6f74d85 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -29,7 +29,6 @@
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_SPLIT_SCREEN_PRIMARY;
@@ -116,7 +115,6 @@
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
import com.android.server.pm.InstantAppResolver;
-import com.android.server.wm.WindowManagerService;
import java.io.PrintWriter;
import java.text.DateFormat;
@@ -135,11 +133,11 @@
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
+ private static final int INVALID_LAUNCH_MODE = -1;
private final ActivityManagerService mService;
private final ActivityStackSupervisor mSupervisor;
private final ActivityStartInterceptor mInterceptor;
- private WindowManagerService mWindowManager;
final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
@@ -149,9 +147,7 @@
private int mCallingUid;
private ActivityOptions mOptions;
- private boolean mLaunchSingleTop;
- private boolean mLaunchSingleInstance;
- private boolean mLaunchSingleTask;
+ private int mLaunchMode;
private boolean mLaunchTaskBehind;
private int mLaunchFlags;
@@ -161,6 +157,7 @@
private boolean mDoResume;
private int mStartFlags;
private ActivityRecord mSourceRecord;
+
// The display to launch the activity onto, barring any strong reason to do otherwise.
private int mPreferredDisplayId;
@@ -190,8 +187,6 @@
private IVoiceInteractionSession mVoiceSession;
private IVoiceInteractor mVoiceInteractor;
- private boolean mUsingVr2dDisplay;
-
// Last home activity record we attempted to start
private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
// The result of the last home activity we attempted to start.
@@ -211,11 +206,9 @@
mCallingUid = -1;
mOptions = null;
- mLaunchSingleTop = false;
- mLaunchSingleInstance = false;
- mLaunchSingleTask = false;
mLaunchTaskBehind = false;
mLaunchFlags = 0;
+ mLaunchMode = INVALID_LAUNCH_MODE;
mLaunchBounds = null;
@@ -243,16 +236,13 @@
mVoiceSession = null;
mVoiceInteractor = null;
- mUsingVr2dDisplay = false;
-
mIntentDelivered = false;
}
- ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
+ ActivityStarter(ActivityManagerService service) {
mService = service;
- mSupervisor = supervisor;
+ mSupervisor = mService.mStackSupervisor;
mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
- mUsingVr2dDisplay = false;
}
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
@@ -618,15 +608,14 @@
}
if (startedActivityStack.inSplitScreenPrimaryWindowingMode()) {
- final ActivityStack homeStack = mSupervisor.getDefaultDisplay().getStack(
- WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
+ final ActivityStack homeStack = mSupervisor.mHomeStack;
final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
if (homeStackVisible) {
// We launch an activity while being in home stack, which means either launcher or
// recents into docked stack. We don't want the launched activity to be alone in a
// docked stack, so we want to immediately launch recents too.
if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
- mWindowManager.showRecentApps(true /* fromHome */);
+ mService.mWindowManager.showRecentApps(true /* fromHome */);
}
return;
}
@@ -1061,7 +1050,7 @@
// operations.
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
- || mLaunchSingleInstance || mLaunchSingleTask) {
+ || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
final TaskRecord task = reusedActivity.getTask();
// In this situation we want to remove all activities from the task up to the one
@@ -1144,7 +1133,7 @@
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
- || mLaunchSingleTop || mLaunchSingleTask);
+ || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
if (dontStart) {
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
@@ -1163,7 +1152,7 @@
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
- preferredLaunchDisplayId, topStack.mStackId);
+ preferredLaunchDisplayId, topStack);
return START_DELIVERED_TO_TOP;
}
@@ -1226,7 +1215,7 @@
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
- mWindowManager.executeAppTransition();
+ mService.mWindowManager.executeAppTransition();
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
@@ -1245,7 +1234,7 @@
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
- preferredLaunchDisplayId, mTargetStack.mStackId);
+ preferredLaunchDisplayId, mTargetStack);
return START_SUCCESS;
}
@@ -1267,13 +1256,13 @@
mLaunchBounds = getOverrideBounds(r, options, inTask);
- mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
- mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
- mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
+ mLaunchMode = r.launchMode;
+
mLaunchFlags = adjustLaunchFlagsToDocumentMode(
- r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
+ r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
+ LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
mLaunchTaskBehind = r.mLaunchTaskBehind
- && !mLaunchSingleTask && !mLaunchSingleInstance
+ && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
sendNewTaskResultRequestIfNeeded();
@@ -1383,7 +1372,7 @@
// If this task is empty, then we are adding the first activity -- it
// determines the root, and must be launching as a NEW_TASK.
- if (mLaunchSingleInstance || mLaunchSingleTask) {
+ if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
ActivityOptions.abort(mOptions);
throw new IllegalArgumentException("Trying to launch singleInstance/Task "
@@ -1445,7 +1434,7 @@
// instance... this new activity it is starting must go on its
// own task.
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
- } else if (mLaunchSingleInstance || mLaunchSingleTask) {
+ } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
// The activity being started is a single instance... it always
// gets launched into its own task.
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
@@ -1496,7 +1485,7 @@
// launch this as a new task behind the current one.
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
- || mLaunchSingleInstance || mLaunchSingleTask;
+ || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
// If bring to front is requested, and no result is requested and we have not been given
// an explicit task to launch in to, and we can find a task that was started with this
// same component, then instead of launching bring that one to the front.
@@ -1506,7 +1495,7 @@
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
- if (mLaunchSingleInstance) {
+ if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
@@ -1515,7 +1504,7 @@
// For the launch adjacent case we only want to put the activity in an existing
// task if the activity already exists in the history.
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
- !mLaunchSingleTask);
+ !(LAUNCH_SINGLE_TASK == mLaunchMode));
} else {
// Otherwise find the best task to put the activity in.
intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
@@ -1544,7 +1533,6 @@
if (DEBUG_STACK) {
Slog.d(TAG, "getSourceDisplayId :" + displayId);
}
- mUsingVr2dDisplay = true;
return displayId;
}
@@ -1666,7 +1654,7 @@
}
mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
- WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack.mStackId);
+ WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
// If the caller has requested that the target task be reset, then do so.
if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
@@ -1718,7 +1706,7 @@
// mTaskToReturnTo values and we don't want to overwrite them accidentally.
mMovedOtherTask = true;
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
- || mLaunchSingleInstance || mLaunchSingleTask) {
+ || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
mLaunchFlags);
if (top == null) {
@@ -1747,7 +1735,8 @@
// so we take that as a request to bring the task to the foreground. If the top
// activity in the task is the root activity, deliver this new intent to it if it
// desires.
- if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
+ if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
+ || LAUNCH_SINGLE_TOP == mLaunchMode)
&& intentActivity.realActivity.equals(mStartActivity.realActivity)) {
if (intentActivity.frontOfTask) {
intentActivity.getTask().setIntent(mStartActivity);
@@ -1951,7 +1940,7 @@
if (top != null && top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId) {
if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
- || mLaunchSingleTop || mLaunchSingleTask) {
+ || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
@@ -2114,10 +2103,9 @@
}
if (stack == null) {
// We first try to put the task in the first dynamic stack on home display.
- final ArrayList<ActivityStack> homeDisplayStacks =
- mSupervisor.getStacksOnDefaultDisplay();
- for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- stack = homeDisplayStacks.get(stackNdx);
+ final ActivityDisplay display = mSupervisor.getDefaultDisplay();
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ stack = display.getChildAt(stackNdx);
if (!stack.isOnHomeDisplay()) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting focused stack=" + stack);
@@ -2175,7 +2163,8 @@
return mReuseTask.getStack();
}
- final int vrDisplayId = mUsingVr2dDisplay ? mPreferredDisplayId : INVALID_DISPLAY;
+ final int vrDisplayId = mPreferredDisplayId == mService.mVr2dDisplayId
+ ? mPreferredDisplayId : INVALID_DISPLAY;
final ActivityStack launchStack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP,
vrDisplayId);
@@ -2213,8 +2202,8 @@
// If the parent is not in the docked stack, we check if there is docked window
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
- final ActivityStack dockedStack = mSupervisor.getDefaultDisplay().getStack(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ final ActivityStack dockedStack =
+ mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
return null;
@@ -2234,8 +2223,8 @@
return newBounds;
}
- void setWindowManager(WindowManagerService wm) {
- mWindowManager = wm;
+ private boolean isLaunchModeOneOf(int mode1, int mode2) {
+ return mode1 == mLaunchMode || mode2 == mLaunchMode;
}
static boolean isDocumentLaunchesIntoExisting(int flags) {
@@ -2316,11 +2305,11 @@
}
pw.print(prefix);
pw.print("mLaunchSingleTop=");
- pw.print(mLaunchSingleTop);
+ pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
pw.print(" mLaunchSingleInstance=");
- pw.print(mLaunchSingleInstance);
+ pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
pw.print(" mLaunchSingleTask=");
- pw.println(mLaunchSingleTask);
+ pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
pw.print(prefix);
pw.print("mLaunchFlags=0x");
pw.print(Integer.toHexString(mLaunchFlags));
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index ba541e6..c3fed17 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -46,7 +46,6 @@
import com.android.server.wm.WindowManagerService;
import java.io.PrintWriter;
-import java.util.ArrayList;
/**
* Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
@@ -237,9 +236,9 @@
final ActivityRecord lastDismissingKeyguardActivity = mDismissingKeyguardActivity;
mOccluded = false;
mDismissingKeyguardActivity = null;
- final ArrayList<ActivityStack> stacks = mStackSupervisor.getStacksOnDefaultDisplay();
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mStackSupervisor.getDefaultDisplay();
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
// Only the focused stack top activity may control occluded state
if (mStackSupervisor.isFocusedStack(stack)) {
@@ -341,7 +340,7 @@
// show on top of the lock screen. In this can we want to dismiss the docked
// stack since it will be complicated/risky to try to put the activity on top
// of the lock screen in the right fullscreen configuration.
- final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenStack();
+ final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
return;
}
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index 72b5de8..940f905 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -19,7 +19,6 @@
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.StatusBarManager.DISABLE_BACK;
import static android.app.StatusBarManager.DISABLE_HOME;
import static android.app.StatusBarManager.DISABLE_MASK;
@@ -59,7 +58,6 @@
import android.util.Slog;
import android.util.SparseArray;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
@@ -433,7 +431,7 @@
mWindowManager.executeAppTransition();
} else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
- DEFAULT_DISPLAY, task.getStackId(), true /* forceNonResizable */);
+ DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */);
}
}
@@ -494,11 +492,7 @@
}
for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mSupervisor.getChildAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
- stack.onLockTaskPackagesUpdatedLocked();
- }
+ mSupervisor.getChildAt(displayNdx).onLockTaskPackagesUpdated();
}
final ActivityRecord r = mSupervisor.topRunningActivityLocked();
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index e4a5980..0bc30cf 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -83,7 +83,6 @@
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
@@ -650,7 +649,7 @@
// In some cases the focused stack isn't the front stack. E.g. pinned stack.
// Whenever we are moving the top activity from the front stack we want to make sure to
// move the stack to the front.
- final boolean wasFront = r != null && supervisor.isFrontStackOnDisplay(sourceStack)
+ final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
&& (sourceStack.topRunningActivityLocked() == r);
// Adjust the position for the new parent stack as needed.
@@ -739,9 +738,9 @@
}
// TODO: Handle incorrect request to move before the actual move, not after.
- final boolean inSplitScreenMode = supervisor.getDefaultDisplay().hasSplitScreenStack();
+ final boolean inSplitScreenMode = supervisor.getDefaultDisplay().hasSplitScreenPrimaryStack();
supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
- DEFAULT_DISPLAY, toStack.mStackId);
+ DEFAULT_DISPLAY, toStack);
boolean successful = (preferredStack == toStack);
if (successful && toStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 0aa6a90..e41c17d 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -417,7 +417,11 @@
// stops output right at 600m/s, depriving this of the information of a device that reaches
// greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
- private boolean mItarSpeedLimitExceeded = false;
+
+ // TODO: improve comment
+ // Volatile to ensure that potentially near-concurrent outputs from HAL
+ // react to this value change promptly
+ private volatile boolean mItarSpeedLimitExceeded = false;
// GNSS Metrics
private GnssMetrics mGnssMetrics;
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 8ebeeae..cf0ffbb 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -236,9 +236,10 @@
*/
@GuardedBy("mInstallLock")
private int dexOptPath(PackageParser.Package pkg, String path, String isa,
- String compilerFilter, boolean profileUpdated, String sharedLibrariesPath,
+ String compilerFilter, boolean profileUpdated, String classLoaderContext,
int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade) {
- int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, profileUpdated, downgrade);
+ int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext,
+ profileUpdated, downgrade);
if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) {
return DEX_OPT_SKIPPED;
}
@@ -251,8 +252,8 @@
Log.i(TAG, "Running dexopt (dexoptNeeded=" + dexoptNeeded + ") on: " + path
+ " pkg=" + pkg.applicationInfo.packageName + " isa=" + isa
+ " dexoptFlags=" + printDexoptFlags(dexoptFlags)
- + " target-filter=" + compilerFilter + " oatDir=" + oatDir
- + " sharedLibraries=" + sharedLibrariesPath);
+ + " targetFilter=" + compilerFilter + " oatDir=" + oatDir
+ + " classLoaderContext=" + classLoaderContext);
try {
long startTime = System.currentTimeMillis();
@@ -261,7 +262,7 @@
// installd only uses downgrade flag for secondary dex files and ignores it for
// primary dex files.
mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags,
- compilerFilter, pkg.volumeUuid, sharedLibrariesPath, pkg.applicationInfo.seInfo,
+ compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo,
false /* downgrade*/);
if (packageStats != null) {
@@ -508,11 +509,11 @@
* configuration (isa, compiler filter, profile).
*/
private int getDexoptNeeded(String path, String isa, String compilerFilter,
- boolean newProfile, boolean downgrade) {
+ String classLoaderContext, boolean newProfile, boolean downgrade) {
int dexoptNeeded;
try {
- dexoptNeeded = DexFile.getDexOptNeeded(path, isa, compilerFilter, newProfile,
- downgrade);
+ dexoptNeeded = DexFile.getDexOptNeeded(path, isa, compilerFilter, classLoaderContext,
+ newProfile, downgrade);
} catch (IOException ioe) {
Slog.w(TAG, "IOException reading apk: " + path, ioe);
return DEX_OPT_FAILED;
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 e1623b0..026abce 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -60,7 +60,7 @@
public void setUp() throws Exception {
super.setUp();
mService = createActivityManagerService();
- mStarter = new ActivityStarter(mService, mService.mStackSupervisor);
+ mStarter = new ActivityStarter(mService);
}
@Test
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 5e85802..cb87737 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -739,12 +739,8 @@
AssetManager assets;
int32_t assetsCookie;
- if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
- fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
- return 1;
- }
- // Now add any dependencies passed in.
+ // Add any dependencies passed in.
for (size_t i = 0; i < bundle->getPackageIncludes().size(); i++) {
const String8& assetPath = bundle->getPackageIncludes()[i];
if (!assets.addAssetPath(assetPath, NULL)) {
@@ -753,6 +749,11 @@
}
}
+ if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
+ fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
+ return 1;
+ }
+
// Make a dummy config for retrieving resources... we need to supply
// non-default values for some configs so that we can retrieve resources
// in the app that don't have a default. The most important of these is
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 041cb4f..8ebde75 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -25,8 +25,8 @@
namespace aapt {
-static const char* sDevelopmentSdkCodeName = "O";
-static ApiVersion sDevelopmentSdkLevel = 26;
+static const char* sDevelopmentSdkCodeName = "P";
+static ApiVersion sDevelopmentSdkLevel = 28;
static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
{0x021c, 1},
@@ -53,6 +53,7 @@
{0x0527, SDK_NOUGAT},
{0x0530, SDK_NOUGAT_MR1},
{0x0568, SDK_O},
+ {0x056d, SDK_O_MR1},
};
static bool less_entry_id(const std::pair<uint16_t, ApiVersion>& p, uint16_t entryId) {
@@ -70,680 +71,6 @@
return iter->second;
}
-static const std::unordered_map<std::string, ApiVersion> sAttrMap = {
- {"marqueeRepeatLimit", 2},
- {"windowNoDisplay", 3},
- {"backgroundDimEnabled", 3},
- {"inputType", 3},
- {"isDefault", 3},
- {"windowDisablePreview", 3},
- {"privateImeOptions", 3},
- {"editorExtras", 3},
- {"settingsActivity", 3},
- {"fastScrollEnabled", 3},
- {"reqTouchScreen", 3},
- {"reqKeyboardType", 3},
- {"reqHardKeyboard", 3},
- {"reqNavigation", 3},
- {"windowSoftInputMode", 3},
- {"imeFullscreenBackground", 3},
- {"noHistory", 3},
- {"headerDividersEnabled", 3},
- {"footerDividersEnabled", 3},
- {"candidatesTextStyleSpans", 3},
- {"smoothScrollbar", 3},
- {"reqFiveWayNav", 3},
- {"keyBackground", 3},
- {"keyTextSize", 3},
- {"labelTextSize", 3},
- {"keyTextColor", 3},
- {"keyPreviewLayout", 3},
- {"keyPreviewOffset", 3},
- {"keyPreviewHeight", 3},
- {"verticalCorrection", 3},
- {"popupLayout", 3},
- {"state_long_pressable", 3},
- {"keyWidth", 3},
- {"keyHeight", 3},
- {"horizontalGap", 3},
- {"verticalGap", 3},
- {"rowEdgeFlags", 3},
- {"codes", 3},
- {"popupKeyboard", 3},
- {"popupCharacters", 3},
- {"keyEdgeFlags", 3},
- {"isModifier", 3},
- {"isSticky", 3},
- {"isRepeatable", 3},
- {"iconPreview", 3},
- {"keyOutputText", 3},
- {"keyLabel", 3},
- {"keyIcon", 3},
- {"keyboardMode", 3},
- {"isScrollContainer", 3},
- {"fillEnabled", 3},
- {"updatePeriodMillis", 3},
- {"initialLayout", 3},
- {"voiceSearchMode", 3},
- {"voiceLanguageModel", 3},
- {"voicePromptText", 3},
- {"voiceLanguage", 3},
- {"voiceMaxResults", 3},
- {"bottomOffset", 3},
- {"topOffset", 3},
- {"allowSingleTap", 3},
- {"handle", 3},
- {"content", 3},
- {"animateOnClick", 3},
- {"configure", 3},
- {"hapticFeedbackEnabled", 3},
- {"innerRadius", 3},
- {"thickness", 3},
- {"sharedUserLabel", 3},
- {"dropDownWidth", 3},
- {"dropDownAnchor", 3},
- {"imeOptions", 3},
- {"imeActionLabel", 3},
- {"imeActionId", 3},
- {"imeExtractEnterAnimation", 3},
- {"imeExtractExitAnimation", 3},
- {"tension", 4},
- {"extraTension", 4},
- {"anyDensity", 4},
- {"searchSuggestThreshold", 4},
- {"includeInGlobalSearch", 4},
- {"onClick", 4},
- {"targetSdkVersion", 4},
- {"maxSdkVersion", 4},
- {"testOnly", 4},
- {"contentDescription", 4},
- {"gestureStrokeWidth", 4},
- {"gestureColor", 4},
- {"uncertainGestureColor", 4},
- {"fadeOffset", 4},
- {"fadeDuration", 4},
- {"gestureStrokeType", 4},
- {"gestureStrokeLengthThreshold", 4},
- {"gestureStrokeSquarenessThreshold", 4},
- {"gestureStrokeAngleThreshold", 4},
- {"eventsInterceptionEnabled", 4},
- {"fadeEnabled", 4},
- {"backupAgent", 4},
- {"allowBackup", 4},
- {"glEsVersion", 4},
- {"queryAfterZeroResults", 4},
- {"dropDownHeight", 4},
- {"smallScreens", 4},
- {"normalScreens", 4},
- {"largeScreens", 4},
- {"progressBarStyleInverse", 4},
- {"progressBarStyleSmallInverse", 4},
- {"progressBarStyleLargeInverse", 4},
- {"searchSettingsDescription", 4},
- {"textColorPrimaryInverseDisableOnly", 4},
- {"autoUrlDetect", 4},
- {"resizeable", 4},
- {"required", 5},
- {"accountType", 5},
- {"contentAuthority", 5},
- {"userVisible", 5},
- {"windowShowWallpaper", 5},
- {"wallpaperOpenEnterAnimation", 5},
- {"wallpaperOpenExitAnimation", 5},
- {"wallpaperCloseEnterAnimation", 5},
- {"wallpaperCloseExitAnimation", 5},
- {"wallpaperIntraOpenEnterAnimation", 5},
- {"wallpaperIntraOpenExitAnimation", 5},
- {"wallpaperIntraCloseEnterAnimation", 5},
- {"wallpaperIntraCloseExitAnimation", 5},
- {"supportsUploading", 5},
- {"killAfterRestore", 5},
- {"restoreNeedsApplication", 5},
- {"smallIcon", 5},
- {"accountPreferences", 5},
- {"textAppearanceSearchResultSubtitle", 5},
- {"textAppearanceSearchResultTitle", 5},
- {"summaryColumn", 5},
- {"detailColumn", 5},
- {"detailSocialSummary", 5},
- {"thumbnail", 5},
- {"detachWallpaper", 5},
- {"finishOnCloseSystemDialogs", 5},
- {"scrollbarFadeDuration", 5},
- {"scrollbarDefaultDelayBeforeFade", 5},
- {"fadeScrollbars", 5},
- {"colorBackgroundCacheHint", 5},
- {"dropDownHorizontalOffset", 5},
- {"dropDownVerticalOffset", 5},
- {"quickContactBadgeStyleWindowSmall", 6},
- {"quickContactBadgeStyleWindowMedium", 6},
- {"quickContactBadgeStyleWindowLarge", 6},
- {"quickContactBadgeStyleSmallWindowSmall", 6},
- {"quickContactBadgeStyleSmallWindowMedium", 6},
- {"quickContactBadgeStyleSmallWindowLarge", 6},
- {"author", 7},
- {"autoStart", 7},
- {"expandableListViewWhiteStyle", 8},
- {"installLocation", 8},
- {"vmSafeMode", 8},
- {"webTextViewStyle", 8},
- {"restoreAnyVersion", 8},
- {"tabStripLeft", 8},
- {"tabStripRight", 8},
- {"tabStripEnabled", 8},
- {"logo", 9},
- {"xlargeScreens", 9},
- {"immersive", 9},
- {"overScrollMode", 9},
- {"overScrollHeader", 9},
- {"overScrollFooter", 9},
- {"filterTouchesWhenObscured", 9},
- {"textSelectHandleLeft", 9},
- {"textSelectHandleRight", 9},
- {"textSelectHandle", 9},
- {"textSelectHandleWindowStyle", 9},
- {"popupAnimationStyle", 9},
- {"screenSize", 9},
- {"screenDensity", 9},
- {"allContactsName", 11},
- {"windowActionBar", 11},
- {"actionBarStyle", 11},
- {"navigationMode", 11},
- {"displayOptions", 11},
- {"subtitle", 11},
- {"customNavigationLayout", 11},
- {"hardwareAccelerated", 11},
- {"measureWithLargestChild", 11},
- {"animateFirstView", 11},
- {"dropDownSpinnerStyle", 11},
- {"actionDropDownStyle", 11},
- {"actionButtonStyle", 11},
- {"showAsAction", 11},
- {"previewImage", 11},
- {"actionModeBackground", 11},
- {"actionModeCloseDrawable", 11},
- {"windowActionModeOverlay", 11},
- {"valueFrom", 11},
- {"valueTo", 11},
- {"valueType", 11},
- {"propertyName", 11},
- {"ordering", 11},
- {"fragment", 11},
- {"windowActionBarOverlay", 11},
- {"fragmentOpenEnterAnimation", 11},
- {"fragmentOpenExitAnimation", 11},
- {"fragmentCloseEnterAnimation", 11},
- {"fragmentCloseExitAnimation", 11},
- {"fragmentFadeEnterAnimation", 11},
- {"fragmentFadeExitAnimation", 11},
- {"actionBarSize", 11},
- {"imeSubtypeLocale", 11},
- {"imeSubtypeMode", 11},
- {"imeSubtypeExtraValue", 11},
- {"splitMotionEvents", 11},
- {"listChoiceBackgroundIndicator", 11},
- {"spinnerMode", 11},
- {"animateLayoutChanges", 11},
- {"actionBarTabStyle", 11},
- {"actionBarTabBarStyle", 11},
- {"actionBarTabTextStyle", 11},
- {"actionOverflowButtonStyle", 11},
- {"actionModeCloseButtonStyle", 11},
- {"titleTextStyle", 11},
- {"subtitleTextStyle", 11},
- {"iconifiedByDefault", 11},
- {"actionLayout", 11},
- {"actionViewClass", 11},
- {"activatedBackgroundIndicator", 11},
- {"state_activated", 11},
- {"listPopupWindowStyle", 11},
- {"popupMenuStyle", 11},
- {"textAppearanceLargePopupMen", 11},
- {"textAppearanceSmallPopupMen", 11},
- {"breadCrumbTitle", 11},
- {"breadCrumbShortTitle", 11},
- {"listDividerAlertDialog", 11},
- {"textColorAlertDialogListItem", 11},
- {"loopViews", 11},
- {"dialogTheme", 11},
- {"alertDialogTheme", 11},
- {"dividerVertical", 11},
- {"homeAsUpIndicator", 11},
- {"enterFadeDuration", 11},
- {"exitFadeDuration", 11},
- {"selectableItemBackground", 11},
- {"autoAdvanceViewId", 11},
- {"useIntrinsicSizeAsMinimum", 11},
- {"actionModeCutDrawable", 11},
- {"actionModeCopyDrawable", 11},
- {"actionModePasteDrawable", 11},
- {"textEditPasteWindowLayout", 11},
- {"textEditNoPasteWindowLayout", 11},
- {"textIsSelectable", 11},
- {"windowEnableSplitTouch", 11},
- {"indeterminateProgressStyle", 11},
- {"progressBarPadding", 11},
- {"animationResolution", 11},
- {"state_accelerated", 11},
- {"baseline", 11},
- {"homeLayout", 11},
- {"opacity", 11},
- {"alpha", 11},
- {"transformPivotX", 11},
- {"transformPivotY", 11},
- {"translationX", 11},
- {"translationY", 11},
- {"scaleX", 11},
- {"scaleY", 11},
- {"rotation", 11},
- {"rotationX", 11},
- {"rotationY", 11},
- {"showDividers", 11},
- {"dividerPadding", 11},
- {"borderlessButtonStyle", 11},
- {"dividerHorizontal", 11},
- {"itemPadding", 11},
- {"buttonBarStyle", 11},
- {"buttonBarButtonStyle", 11},
- {"segmentedButtonStyle", 11},
- {"staticWallpaperPreview", 11},
- {"allowParallelSyncs", 11},
- {"isAlwaysSyncable", 11},
- {"verticalScrollbarPosition", 11},
- {"fastScrollAlwaysVisible", 11},
- {"fastScrollThumbDrawable", 11},
- {"fastScrollPreviewBackgroundLeft", 11},
- {"fastScrollPreviewBackgroundRight", 11},
- {"fastScrollTrackDrawable", 11},
- {"fastScrollOverlayPosition", 11},
- {"customTokens", 11},
- {"nextFocusForward", 11},
- {"firstDayOfWeek", 11},
- {"showWeekNumber", 11},
- {"minDate", 11},
- {"maxDate", 11},
- {"shownWeekCount", 11},
- {"selectedWeekBackgroundColor", 11},
- {"focusedMonthDateColor", 11},
- {"unfocusedMonthDateColor", 11},
- {"weekNumberColor", 11},
- {"weekSeparatorLineColor", 11},
- {"selectedDateVerticalBar", 11},
- {"weekDayTextAppearance", 11},
- {"dateTextAppearance", 11},
- {"solidColor", 11},
- {"spinnersShown", 11},
- {"calendarViewShown", 11},
- {"state_multiline", 11},
- {"detailsElementBackground", 11},
- {"textColorHighlightInverse", 11},
- {"textColorLinkInverse", 11},
- {"editTextColor", 11},
- {"editTextBackground", 11},
- {"horizontalScrollViewStyle", 11},
- {"layerType", 11},
- {"alertDialogIcon", 11},
- {"windowMinWidthMajor", 11},
- {"windowMinWidthMinor", 11},
- {"queryHint", 11},
- {"fastScrollTextColor", 11},
- {"largeHeap", 11},
- {"windowCloseOnTouchOutside", 11},
- {"datePickerStyle", 11},
- {"calendarViewStyle", 11},
- {"textEditSidePasteWindowLayout", 11},
- {"textEditSideNoPasteWindowLayout", 11},
- {"actionMenuTextAppearance", 11},
- {"actionMenuTextColor", 11},
- {"textCursorDrawable", 12},
- {"resizeMode", 12},
- {"requiresSmallestWidthDp", 12},
- {"compatibleWidthLimitDp", 12},
- {"largestWidthLimitDp", 12},
- {"state_hovered", 13},
- {"state_drag_can_accept", 13},
- {"state_drag_hovered", 13},
- {"stopWithTask", 13},
- {"switchTextOn", 13},
- {"switchTextOff", 13},
- {"switchPreferenceStyle", 13},
- {"switchTextAppearance", 13},
- {"track", 13},
- {"switchMinWidth", 13},
- {"switchPadding", 13},
- {"thumbTextPadding", 13},
- {"textSuggestionsWindowStyle", 13},
- {"textEditSuggestionItemLayout", 13},
- {"rowCount", 13},
- {"rowOrderPreserved", 13},
- {"columnCount", 13},
- {"columnOrderPreserved", 13},
- {"useDefaultMargins", 13},
- {"alignmentMode", 13},
- {"layout_row", 13},
- {"layout_rowSpan", 13},
- {"layout_columnSpan", 13},
- {"actionModeSelectAllDrawable", 13},
- {"isAuxiliary", 13},
- {"accessibilityEventTypes", 13},
- {"packageNames", 13},
- {"accessibilityFeedbackType", 13},
- {"notificationTimeout", 13},
- {"accessibilityFlags", 13},
- {"canRetrieveWindowContent", 13},
- {"listPreferredItemHeightLarge", 13},
- {"listPreferredItemHeightSmall", 13},
- {"actionBarSplitStyle", 13},
- {"actionProviderClass", 13},
- {"backgroundStacked", 13},
- {"backgroundSplit", 13},
- {"textAllCaps", 13},
- {"colorPressedHighlight", 13},
- {"colorLongPressedHighlight", 13},
- {"colorFocusedHighlight", 13},
- {"colorActivatedHighlight", 13},
- {"colorMultiSelectHighlight", 13},
- {"drawableStart", 13},
- {"drawableEnd", 13},
- {"actionModeStyle", 13},
- {"minResizeWidth", 13},
- {"minResizeHeight", 13},
- {"actionBarWidgetTheme", 13},
- {"uiOptions", 13},
- {"subtypeLocale", 13},
- {"subtypeExtraValue", 13},
- {"actionBarDivider", 13},
- {"actionBarItemBackground", 13},
- {"actionModeSplitBackground", 13},
- {"textAppearanceListItem", 13},
- {"textAppearanceListItemSmall", 13},
- {"targetDescriptions", 13},
- {"directionDescriptions", 13},
- {"overridesImplicitlyEnabledSubtype", 13},
- {"listPreferredItemPaddingLeft", 13},
- {"listPreferredItemPaddingRight", 13},
- {"requiresFadingEdge", 13},
- {"publicKey", 13},
- {"parentActivityName", 16},
- {"isolatedProcess", 16},
- {"importantForAccessibility", 16},
- {"keyboardLayout", 16},
- {"fontFamily", 16},
- {"mediaRouteButtonStyle", 16},
- {"mediaRouteTypes", 16},
- {"supportsRtl", 17},
- {"textDirection", 17},
- {"textAlignment", 17},
- {"layoutDirection", 17},
- {"paddingStart", 17},
- {"paddingEnd", 17},
- {"layout_marginStart", 17},
- {"layout_marginEnd", 17},
- {"layout_toStartOf", 17},
- {"layout_toEndOf", 17},
- {"layout_alignStart", 17},
- {"layout_alignEnd", 17},
- {"layout_alignParentStart", 17},
- {"layout_alignParentEnd", 17},
- {"listPreferredItemPaddingStart", 17},
- {"listPreferredItemPaddingEnd", 17},
- {"singleUser", 17},
- {"presentationTheme", 17},
- {"subtypeId", 17},
- {"initialKeyguardLayout", 17},
- {"widgetCategory", 17},
- {"permissionGroupFlags", 17},
- {"labelFor", 17},
- {"permissionFlags", 17},
- {"checkedTextViewStyle", 17},
- {"showOnLockScreen", 17},
- {"format12Hour", 17},
- {"format24Hour", 17},
- {"timeZone", 17},
- {"mipMap", 18},
- {"mirrorForRtl", 18},
- {"windowOverscan", 18},
- {"requiredForAllUsers", 18},
- {"indicatorStart", 18},
- {"indicatorEnd", 18},
- {"childIndicatorStart", 18},
- {"childIndicatorEnd", 18},
- {"restrictedAccountType", 18},
- {"requiredAccountType", 18},
- {"canRequestTouchExplorationMode", 18},
- {"canRequestEnhancedWebAccessibility", 18},
- {"canRequestFilterKeyEvents", 18},
- {"layoutMode", 18},
- {"keySet", 19},
- {"targetId", 19},
- {"fromScene", 19},
- {"toScene", 19},
- {"transition", 19},
- {"transitionOrdering", 19},
- {"fadingMode", 19},
- {"startDelay", 19},
- {"ssp", 19},
- {"sspPrefix", 19},
- {"sspPattern", 19},
- {"addPrintersActivity", 19},
- {"vendor", 19},
- {"category", 19},
- {"isAsciiCapable", 19},
- {"autoMirrored", 19},
- {"supportsSwitchingToNextInputMethod", 19},
- {"requireDeviceUnlock", 19},
- {"apduServiceBanner", 19},
- {"accessibilityLiveRegion", 19},
- {"windowTranslucentStatus", 19},
- {"windowTranslucentNavigation", 19},
- {"advancedPrintOptionsActivity", 19},
- {"banner", 20},
- {"windowSwipeToDismiss", 20},
- {"isGame", 20},
- {"allowEmbedded", 20},
- {"setupActivity", 20},
- {"fastScrollStyle", 21},
- {"windowContentTransitions", 21},
- {"windowContentTransitionManager", 21},
- {"translationZ", 21},
- {"tintMode", 21},
- {"controlX1", 21},
- {"controlY1", 21},
- {"controlX2", 21},
- {"controlY2", 21},
- {"transitionName", 21},
- {"transitionGroup", 21},
- {"viewportWidth", 21},
- {"viewportHeight", 21},
- {"fillColor", 21},
- {"pathData", 21},
- {"strokeColor", 21},
- {"strokeWidth", 21},
- {"trimPathStart", 21},
- {"trimPathEnd", 21},
- {"trimPathOffset", 21},
- {"strokeLineCap", 21},
- {"strokeLineJoin", 21},
- {"strokeMiterLimit", 21},
- {"colorControlNormal", 21},
- {"colorControlActivated", 21},
- {"colorButtonNormal", 21},
- {"colorControlHighlight", 21},
- {"persistableMode", 21},
- {"titleTextAppearance", 21},
- {"subtitleTextAppearance", 21},
- {"slideEdge", 21},
- {"actionBarTheme", 21},
- {"textAppearanceListItemSecondary", 21},
- {"colorPrimary", 21},
- {"colorPrimaryDark", 21},
- {"colorAccent", 21},
- {"nestedScrollingEnabled", 21},
- {"windowEnterTransition", 21},
- {"windowExitTransition", 21},
- {"windowSharedElementEnterTransition", 21},
- {"windowSharedElementExitTransition", 21},
- {"windowAllowReturnTransitionOverlap", 21},
- {"windowAllowEnterTransitionOverlap", 21},
- {"sessionService", 21},
- {"stackViewStyle", 21},
- {"switchStyle", 21},
- {"elevation", 21},
- {"excludeId", 21},
- {"excludeClass", 21},
- {"hideOnContentScroll", 21},
- {"actionOverflowMenuStyle", 21},
- {"documentLaunchMode", 21},
- {"maxRecents", 21},
- {"autoRemoveFromRecents", 21},
- {"stateListAnimator", 21},
- {"toId", 21},
- {"fromId", 21},
- {"reversible", 21},
- {"splitTrack", 21},
- {"targetName", 21},
- {"excludeName", 21},
- {"matchOrder", 21},
- {"windowDrawsSystemBarBackgrounds", 21},
- {"statusBarColor", 21},
- {"navigationBarColor", 21},
- {"contentInsetStart", 21},
- {"contentInsetEnd", 21},
- {"contentInsetLeft", 21},
- {"contentInsetRight", 21},
- {"paddingMode", 21},
- {"layout_rowWeight", 21},
- {"layout_columnWeight", 21},
- {"translateX", 21},
- {"translateY", 21},
- {"selectableItemBackgroundBorderless", 21},
- {"elegantTextHeight", 21},
- {"searchKeyphraseId", 21},
- {"searchKeyphrase", 21},
- {"searchKeyphraseSupportedLocales", 21},
- {"windowTransitionBackgroundFadeDuration", 21},
- {"overlapAnchor", 21},
- {"progressTint", 21},
- {"progressTintMode", 21},
- {"progressBackgroundTint", 21},
- {"progressBackgroundTintMode", 21},
- {"secondaryProgressTint", 21},
- {"secondaryProgressTintMode", 21},
- {"indeterminateTint", 21},
- {"indeterminateTintMode", 21},
- {"backgroundTint", 21},
- {"backgroundTintMode", 21},
- {"foregroundTint", 21},
- {"foregroundTintMode", 21},
- {"buttonTint", 21},
- {"buttonTintMode", 21},
- {"thumbTint", 21},
- {"thumbTintMode", 21},
- {"fullBackupOnly", 21},
- {"propertyXName", 21},
- {"propertyYName", 21},
- {"relinquishTaskIdentity", 21},
- {"tileModeX", 21},
- {"tileModeY", 21},
- {"actionModeShareDrawable", 21},
- {"actionModeFindDrawable", 21},
- {"actionModeWebSearchDrawable", 21},
- {"transitionVisibilityMode", 21},
- {"minimumHorizontalAngle", 21},
- {"minimumVerticalAngle", 21},
- {"maximumAngle", 21},
- {"searchViewStyle", 21},
- {"closeIcon", 21},
- {"goIcon", 21},
- {"searchIcon", 21},
- {"voiceIcon", 21},
- {"commitIcon", 21},
- {"suggestionRowLayout", 21},
- {"queryBackground", 21},
- {"submitBackground", 21},
- {"buttonBarPositiveButtonStyle", 21},
- {"buttonBarNeutralButtonStyle", 21},
- {"buttonBarNegativeButtonStyle", 21},
- {"popupElevation", 21},
- {"actionBarPopupTheme", 21},
- {"multiArch", 21},
- {"touchscreenBlocksFocus", 21},
- {"windowElevation", 21},
- {"launchTaskBehindTargetAnimation", 21},
- {"launchTaskBehindSourceAnimation", 21},
- {"restrictionType", 21},
- {"dayOfWeekBackground", 21},
- {"dayOfWeekTextAppearance", 21},
- {"headerMonthTextAppearance", 21},
- {"headerDayOfMonthTextAppearance", 21},
- {"headerYearTextAppearance", 21},
- {"yearListItemTextAppearance", 21},
- {"yearListSelectorColor", 21},
- {"calendarTextColor", 21},
- {"recognitionService", 21},
- {"timePickerStyle", 21},
- {"timePickerDialogTheme", 21},
- {"headerTimeTextAppearance", 21},
- {"headerAmPmTextAppearance", 21},
- {"numbersTextColor", 21},
- {"numbersBackgroundColor", 21},
- {"numbersSelectorColor", 21},
- {"amPmTextColor", 21},
- {"amPmBackgroundColor", 21},
- {"searchKeyphraseRecognitionFlags", 21},
- {"checkMarkTint", 21},
- {"checkMarkTintMode", 21},
- {"popupTheme", 21},
- {"toolbarStyle", 21},
- {"windowClipToOutline", 21},
- {"datePickerDialogTheme", 21},
- {"showText", 21},
- {"windowReturnTransition", 21},
- {"windowReenterTransition", 21},
- {"windowSharedElementReturnTransition", 21},
- {"windowSharedElementReenterTransition", 21},
- {"resumeWhilePausing", 21},
- {"datePickerMode", 21},
- {"timePickerMode", 21},
- {"inset", 21},
- {"letterSpacing", 21},
- {"fontFeatureSettings", 21},
- {"outlineProvider", 21},
- {"contentAgeHint", 21},
- {"country", 21},
- {"windowSharedElementsUseOverlay", 21},
- {"reparent", 21},
- {"reparentWithOverlay", 21},
- {"ambientShadowAlpha", 21},
- {"spotShadowAlpha", 21},
- {"navigationIcon", 21},
- {"navigationContentDescription", 21},
- {"fragmentExitTransition", 21},
- {"fragmentEnterTransition", 21},
- {"fragmentSharedElementEnterTransition", 21},
- {"fragmentReturnTransition", 21},
- {"fragmentSharedElementReturnTransition", 21},
- {"fragmentReenterTransition", 21},
- {"fragmentAllowEnterTransitionOverlap", 21},
- {"fragmentAllowReturnTransitionOverlap", 21},
- {"patternPathData", 21},
- {"strokeAlpha", 21},
- {"fillAlpha", 21},
- {"windowActivityTransitions", 21},
- {"colorEdgeEffect", 21}};
-
-ApiVersion FindAttributeSdkLevel(const ResourceName& name) {
- if (name.package != "android" && name.type != ResourceType::kAttr) {
- return 0;
- }
-
- auto iter = sAttrMap.find(name.entry);
- if (iter != sAttrMap.end()) {
- return iter->second;
- }
- return SDK_LOLLIPOP_MR1;
-}
-
std::pair<StringPiece, ApiVersion> GetDevelopmentSdkCodeNameAndVersion() {
return std::make_pair(StringPiece(sDevelopmentSdkCodeName), sDevelopmentSdkLevel);
}
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index 13584c0..5b7be3b 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -57,7 +57,6 @@
};
ApiVersion FindAttributeSdkLevel(const ResourceId& id);
-ApiVersion FindAttributeSdkLevel(const ResourceName& name);
std::pair<android::StringPiece, ApiVersion> GetDevelopmentSdkCodeNameAndVersion();
} // namespace aapt